filter:过滤器
2016-02-01 23:37
183 查看
一、什么是过滤器及它的作用
1、过滤器的作用好比一个保安,是Servlet规范中的技术
2、用户在访问应用的资源之前或之后,可以对请求和响应做出一定的处理
二、编写过滤器的步骤
1、编写一个类,实现javax.servlet.Filter接口
2、配置过滤哪些资源
修改web.xml,配置要过滤器的资源的映射地址
3、让目标资源执行,放行
三、过滤器的生命周期
1、过滤器的实例由服务器创建的,其中的方法也是由服务器调用的
2、过滤器在应用被加载时实例化并初始化(调用init方法),只有一次;
用户每次访问过滤范围之内的资源,过滤器的doFIlter方法都会执行;应用被卸载或服务器停止时会调用销毁方法(destroy)。
3、特点:过滤器中的实例变量,注意线程安全问题
四、过滤器的过滤顺序
总结:多个过滤器过滤相同的资源,过滤顺序按照web.xml中filter-mapping的出现顺序依次进行过滤的。
Servlet VS. Filter
1、Servlet能做的过滤器都能做;过滤器比Servlet多了一个是否放行的功能。
2、Servlet在开发中是作为控制器来用的;Filter也可以作为控制器来用。
3、Struts1框架:Servlet作为控制器
Struts2框架:FIlter作为控制器(Struts2框架)
过滤器的简单案例
2、动态资源不要缓存过滤器
3、控制静态资源的缓存时间
Base64编码(很重要)
1、原理:3字节变为4字节(计算机中存储的都是字节)
2、编码原理:
1010 0101 1110 0100 1001 1111 3个字节
0010 1001 0001 1110 0001 0010 0001 1111 4个字节
每个字节表示的范围:00000000~0011111
表示的整数范围:0~63。每一个整数都对应着键盘上的一个可见字符
3、Base64是一个码表
可以把任何的二进制转变为可见字符串(A~Za~z0-9+/)
4、自动登录过滤器
向浏览器发送自定义cookie:记录登录用户密码的cookie
过滤器的高级配置
1、过滤器的作用好比一个保安,是Servlet规范中的技术
2、用户在访问应用的资源之前或之后,可以对请求和响应做出一定的处理
二、编写过滤器的步骤
1、编写一个类,实现javax.servlet.Filter接口
public class FilterDemo1 implements Filter { public FilterDemo1(){ System.out.println("调用了FIlterDemo1的默认构造方法"); } public void init(FilterConfig filterConfig) throws ServletException { System.out.println("调用了FIlterDemo1的init方法"); } //每次访问都会经过该方法 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("FilterDemo1过滤器了"); chain.doFilter(request, response);//让目标资源执行。放行 } public void destroy() { System.out.println("调用了FIlterDemo1的销毁方法"); } }
2、配置过滤哪些资源
修改web.xml,配置要过滤器的资源的映射地址
<servlet> <servlet-name>ServletDemo1</servlet-name> <servlet-class>com.itheima.servlet.ServletDemo1</servlet-class> </servlet> <filter> <!-- 定义过滤器 --> <filter-name>FilterDemo1</filter-name> <filter-class>com.itheima.filter.FilterDemo1</filter-class> </filter> <filter-mapping> <filter-name>FilterDemo1</filter-name> <!-- 过滤本应用中的所有资源 --> <url-pattern>/*</url-pattern> </filter-mapping>
3、让目标资源执行,放行
//每次访问都会经过该方法 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("FilterDemo1过滤器了"); chain.doFilter(request, response);//让目标资源执行。放行 }
三、过滤器的生命周期
1、过滤器的实例由服务器创建的,其中的方法也是由服务器调用的
2、过滤器在应用被加载时实例化并初始化(调用init方法),只有一次;
用户每次访问过滤范围之内的资源,过滤器的doFIlter方法都会执行;应用被卸载或服务器停止时会调用销毁方法(destroy)。
3、特点:过滤器中的实例变量,注意线程安全问题
四、过滤器的过滤顺序
总结:多个过滤器过滤相同的资源,过滤顺序按照web.xml中filter-mapping的出现顺序依次进行过滤的。
Servlet VS. Filter
1、Servlet能做的过滤器都能做;过滤器比Servlet多了一个是否放行的功能。
2、Servlet在开发中是作为控制器来用的;Filter也可以作为控制器来用。
3、Struts1框架:Servlet作为控制器
Struts2框架:FIlter作为控制器(Struts2框架)
过滤器的简单案例
<filter> <filter-name>SetAllCharacterEncodingFilter</filter-name> <filter-class>com.itheima.filter.SetAllCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>SetAllCharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
//解决GET和POST请求参数和响应输出的编码过滤器 public class SetAllCharacterEncodingFilter implements Filter { private FilterConfig filterConfig; public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request; HttpServletResponse response; try{ request = (HttpServletRequest)req; response = (HttpServletResponse)resp; }catch(Exception e){ throw new RuntimeException("non-http request"); } String encoding = "UTF-8";//默认参数 String value = filterConfig.getInitParameter("encoding"); if(value!=null){ encoding = value; } //请求时的编码 request.setCharacterEncoding(encoding);//POST请求方式 //响应时的编码 response.setCharacterEncoding(encoding); response.setContentType("text/html;charset="+encoding); //对request 请求进行包装,处理get提交的乱码 MyHttpServletRequest mrequest = new MyHttpServletRequest(request); chain.doFilter(mrequest, response); } public void destroy() { } } //装饰设计模式应用: class MyHttpServletRequest extends HttpServletRequestWrapper{ private HttpServletRequest request; public MyHttpServletRequest(HttpServletRequest request){ super(request); this.request = request; } public String getParameter(String name) { String value = request.getParameter(name); if(value==null) return value; try { if("get".equalsIgnoreCase(request.getMethod())) //utf-8 进行编码 value = new String(value.getBytes("ISO-8859-1"),request.getCharacterEncoding()); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return value; } }
2、动态资源不要缓存过滤器
<filter> <filter-name>DynamicResourceNoCacheFilter</filter-name> <filter-class>com.itheima.filter.DynamicResourceNoCacheFilter</filter-class> </filter> <filter-mapping> <filter-name>DynamicResourceNoCacheFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>DynamicResourceNoCacheFilter</filter-name> <url-pattern>/servlet/*</url-pattern> </filter-mapping>
//动态资源不要缓存 public class DynamicResourceNoCacheFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request; HttpServletResponse response; try{ request = (HttpServletRequest)req; response = (HttpServletResponse)resp; }catch(Exception e){ throw new RuntimeException("non-http request"); } //设置响应头,不缓存 response.setHeader("Expires", "-1"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); chain.doFilter(request, response); } public void destroy() { } }
3、控制静态资源的缓存时间
<filter> <filter-name>StaticResourceNeedCache</filter-name> <filter-class>com.itheima.filter.StaticResourceNeedCache</filter-class> <init-param> <param-name>html</param-name> <param-value>1</param-value> </init-param> <init-param> <param-name>css</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>js</param-name> <param-value>3</param-value> </init-param> </filter> <filter-mapping> <filter-name>StaticResourceNeedCache</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping> <filter-mapping> <filter-name>StaticResourceNeedCache</filter-name> <url-pattern>*.css</url-pattern> </filter-mapping> <filter-mapping> <filter-name>StaticResourceNeedCache</filter-name> <url-pattern>*.js</url-pattern> </filter-mapping>
//控制静态资源的缓存时间 public class StaticResourceNeedCache implements Filter { private FilterConfig filterConfig; public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request; HttpServletResponse response; try{ request = (HttpServletRequest)req; response = (HttpServletResponse)resp; }catch(Exception e){ throw new RuntimeException("non-http request"); } long time = 0;//缓存的时间 //针对不同的资源,获取参数,并设置缓存的时间 String uri = request.getRequestURI();// request.getRequestURI():/day19_01_simpleFilterDemo/1.html //截取要访问的资源的扩展名 String type = uri.substring(uri.lastIndexOf(".")+1);// html //获取参数,根据访问的资源类型获取时间 String htmlTime = filterConfig.getInitParameter("html"); String cssTime = filterConfig.getInitParameter("css"); String jsTime = filterConfig.getInitParameter("js"); //根据请求的不同后缀,来设置不同文件的缓存时间 if("html".equals(type)){ //访问的是html资源 time = Long.parseLong(htmlTime)*60*60*1000; } if("css".equals(type)){ //访问的是html资源 time = Long.parseLong(cssTime)*60*60*1000; } if("js".equals(type)){ //访问的是html资源 time = Long.parseLong(jsTime)*60*60*1000; } response.setDateHeader("Expires", System.currentTimeMillis()+time); chain.doFilter(request, response); } public void destroy() { } }
Base64编码(很重要)
1、原理:3字节变为4字节(计算机中存储的都是字节)
2、编码原理:
1010 0101 1110 0100 1001 1111 3个字节
0010 1001 0001 1110 0001 0010 0001 1111 4个字节
每个字节表示的范围:00000000~0011111
表示的整数范围:0~63。每一个整数都对应着键盘上的一个可见字符
3、Base64是一个码表
可以把任何的二进制转变为可见字符串(A~Za~z0-9+/)
public class Base64Demo { @Test public void test1(){ String s = "王斐"; BASE64Encoder base64 = new BASE64Encoder(); String s1 = base64.encode(s.getBytes());//GBK System.out.println(s1); //编码 } // @Test public void test2() throws IOException{ String s = "zfXssw=="; BASE64Decoder base64 = new BASE64Decoder(); byte b[] = base64.decodeBuffer(s); System.out.println(new String(b));//GBK //解码 } }
public class MD5Demo { @Test public void test1() throws NoSuchAlgorithmException{ MessageDigest md = MessageDigest.getInstance("MD5"); byte b[] = md.digest("123".getBytes());//返回值是二进制,不一定对应着可见字符 //数据指纹 String s = new BASE64Encoder().encode(b); System.out.println(s); } }
4、自动登录过滤器
//实现自动登录的过滤器 public class AutoLoginFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request; HttpServletResponse response; try{ request = (HttpServletRequest)req; response = (HttpServletResponse)resp; }catch(Exception e){ throw new RuntimeException("non-http request"); } //判断用户是否登录 HttpSession session = request.getSession(); User user = (User)session.getAttribute("user"); //没有登录:自动登录 if(user==null){ //从cookie中取数据:用户名和密码 Cookie cs[] = request.getCookies(); for(int i=0;cs!=null&&i<cs.length;i++){ Cookie c = cs[i]; //查询保存密码的cookie if("loginInfo".equals(c.getName())){ //再次验证用户名和密码的正确性 String usernameBase64 = c.getValue().split("_")[0]; String passwordMD5 = c.getValue().split("_")[1]; //将cookie中的用户名解析为正常的字符 String username = Base64Util.base64decode(usernameBase64); //从数据库查询密码 User dbUser = UserDB.findUser(username); if(passwordMD5.equals(MD5Util.md5(dbUser.getPassword()))){ //用户名和密码都正确 session.setAttribute("user", dbUser); } } } } //放行 chain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException { } public void destroy() { } }
向浏览器发送自定义cookie:记录登录用户密码的cookie
public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); String remember = request.getParameter("remember"); //查询用户 User user = UserDB.findUser(username, password); if(user!=null){ request.getSession().setAttribute("user", user); username = Base64Util.base64encode(username); password = MD5Util.md5(password); //保存cookie Cookie cookie = new Cookie("loginInfo", username+"_"+password);//用户名_密码 cookie.setPath(request.getContextPath());//当前应用都能获取该Cookie System.err.println("request.getContextPath()"+request.getContextPath()); //判断用户是否选择了下次自动登录功能 if(remember!=null){ //cookie的保存时间 cookie.setMaxAge(Integer.MAX_VALUE); }else{ cookie.setMaxAge(0); } //将浏览器写cookie response.addCookie(cookie); //刷新跳转 response.getWriter().write("登录成功!2秒后转向主页"); response.setHeader("Refresh", "2;URL="+request.getContextPath()); }else{ response.getWriter().write("错误的用户名或密码"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
过滤器的高级配置
<filter> <filter-name>FilterDemo1</filter-name> <filter-class>com.itheima.filter.FilterDemo1</filter-class> </filter> <filter-mapping> <filter-name>FilterDemo1</filter-name> <url-pattern>/*</url-pattern> //过滤其它类型的请求配置 <dispatcher>REQUEST</dispatcher> //默认 <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> //jsp error指令的配置请求过滤 </filter-mapping> <error-page> <exception-type>java.lang.Exception</exception-type> <location>/error.jsp</location> </error-page>
相关文章推荐
- C实现的排序
- 3-1MapReduce原理,原理图要记住
- hdu3861The King’s Problem
- 8个实用的SVG工具,20 个有用的 SVG 工具,五款超实用的开源SVG工具
- n年的一次聚会
- Delphi 如何计算字符串表达式呢?
- Qt 入门导航
- 顺序表和链表的区别
- 密码学初级教程(六)数字签名 Digital Signature
- 第十章编程练习(2)
- android源码分析之notification
- JAVA中的几种设计模式
- direcrx11 学习日记supersampling (超采样抗锯齿)和(多重采样抗锯齿)的区别
- SGU 531 Bonnie and Clyde(二分)
- 坚果手机使用感受
- 坚果手机使用感受
- 9. Oracle深度学习笔记——性能调优汇总
- JAVA中接口与抽象类的区别
- HDU 4429 Split the Rectangle(暴力)
- C遇到的问题