Servlet中的过滤器Filter详解
web.xml中元素执行的顺序listener->filter->struts拦截器->servlet。
1.过滤器的概念
Java中的Filter 并不是一个标准的Servlet ,它不能处理用户请求,也不能对客户端生成响应。 主要用于对HttpServletRequest 进行预处理,也可以对HttpServletResponse 进行后处理,是个典型的处理链。
优点:过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。而在实际使用时,就要特别注意过滤链的执行顺序问题
2.过滤器的作用描述
- 在HttpServletRequest 到达Servlet 之前,拦截客户的HttpServletRequest 。
- 根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。
- 在HttpServletResponse 到达客户端之前,拦截HttpServletResponse 。
- 根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。
3.过滤器的执行流程
4.Filter接口
1.如何驱动
在 web 应用程序启动时,web 服务器将根据 web.xml 文件中的配置信息来创建每个注册的 Filter 实例对象,并将其保存在服务器的内存中
2.方法介绍
- init() Init 方法在 Filter 生命周期中仅执行一次,web 容器在调用 init 方法时
- destory() 在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。
- doFilter() Filter 链的执行
5.FilterChain接口
1.如何实例化
代表当前 Filter 链的对象。由容器实现,容器将其实例作为参数传入过滤器对象的doFilter()方法中
2.作用
调用过滤器链中的下一个过滤器
filter实例:
web.xml配置
1 <!-- 编码过滤器 --> 2 <filter> 3 <filter-name>setCharacterEncoding</filter-name> 4 <filter-class>com.company.strutstudy.web.servletstudy.filter.EncodingFilter</filter-class> 5 <init-param> 6 <param-name>encoding</param-name> 7 <param-value>utf-8</param-value> 8 </init-param> 9 </filter> 10 <filter-mapping> 11 <filter-name>setCharacterEncoding</filter-name> 12 <url-pattern>/*</url-pattern> 13 </filter-mapping> 14 15 <!-- 请求url日志记录过滤器 --> 16 <filter> 17 <filter-name>logfilter</filter-name> 18 <filter-class>com.company.strutstudy.web.servletstudy.filter.LogFilter</filter-class> 19 </filter> 20 <filter-mapping> 21 <filter-name>logfilter</filter-name> 22 <url-pattern>/*</url-pattern> 23 </filter-mapping>
编码拦截器:
1 public class EncodingFilter implements Filter { 2 private String encoding; 3 private Map<String, String> params = new HashMap<String, String>(); 4 // 项目结束时就已经进行销毁 5 public void destroy() { 6 System.out.println("end do the encoding filter!"); 7 params=null; 8 encoding=null; 9 } 10 public void doFilter(ServletRequest req, ServletResponse resp, 11 FilterChain chain) throws IOException, ServletException { 12 //UtilTimerStack.push("EncodingFilter_doFilter:"); 13 System.out.println("before encoding " + encoding + " filter!"); 14 req.setCharacterEncoding(encoding); 15 // resp.setCharacterEncoding(encoding); 16 // resp.setContentType("text/html;charset="+encoding); 17 chain.doFilter(req, resp); 18 System.out.println("after encoding " + encoding + " filter!"); 19 System.err.println("----------------------------------------"); 20 //UtilTimerStack.pop("EncodingFilter_doFilter:"); 21 } 22 23 // 项目启动时就已经进行读取 24 public void init(FilterConfig config) throws ServletException { 25 System.out.println("begin do the encoding filter!"); 26 encoding = config.getInitParameter("encoding"); 27 for (Enumeration e = config.getInitParameterNames(); e 28 .hasMoreElements();) { 29 String name = (String) e.nextElement(); 30 String value = config.getInitParameter(name); 31 params.put(name, value); 32 } 33 } 34 }
日志拦截器:
1 public class LogFilter implements Filter { 2 FilterConfig config; 3 4 public void destroy() { 5 this.config = null; 6 } 7 8 public void doFilter(ServletRequest req, ServletResponse res, 9 FilterChain chain) throws IOException, ServletException { 10 // 获取ServletContext 对象,用于记录日志 11 ServletContext context = this.config.getServletContext(); 12 //long before = System.currentTimeMillis(); 13 System.out.println("before the log filter!"); 14 //context.log("开始过滤"); 15 // 将请求转换成HttpServletRequest 请求 16 HttpServletRequest hreq = (HttpServletRequest) req; 17 // 记录日志 18 System.out.println("Log Filter已经截获到用户的请求的地址:"+hreq.getServletPath() ); 19 //context.log("Filter已经截获到用户的请求的地址: " + hreq.getServletPath()); 20 try { 21 // Filter 只是链式处理,请求依然转发到目的地址。 22 chain.doFilter(req, res); 23 } catch (Exception e) { 24 e.printStackTrace(); 25 } 26 System.out.println("after the log filter!"); 27 //long after = System.currentTimeMillis(); 28 // 记录日志 29 //context.log("过滤结束"); 30 // 再次记录日志 31 //context.log(" 请求被定位到" + ((HttpServletRequest) req).getRequestURI() 32 // + "所花的时间为: " + (after - before)); 33 } 34 35 public void init(FilterConfig config) throws ServletException { 36 System.out.println("begin do the log filter!"); 37 this.config = config; 38 } 39 40 }
HelloServlet类:
1 public class HelloWorldServlet extends HttpServlet{ 2 3 /** 4 * 查看httpservlet实现的service一看便知,起到了一个controll控制器的作用(转向的) 5 * 之后便是跳转至我们熟悉的doget,dopost等方法中 6 */ 7 @Override 8 protected void service(HttpServletRequest req, HttpServletResponse resp) 9 throws ServletException, IOException { 10 System.out.println("doservice..."+this.getInitParameter("encoding")); 11 12 super.service(req, resp); 13 } 14 15 @Override 16 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 17 throws ServletException, IOException { 18 System.out.println("doget..."); 19 doPost(req, resp); 20 } 21 22 @Override 23 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 24 throws ServletException, IOException { 25 System.out.println("dopost..."); 26 } 27 28 29 30 }
结果:
1 before encoding utf-8 filter! 2 before the log filter! 3 Log Filter已经截获到用户的请求的地址:/hello 4 doservice...UTF-8 5 doget... 6 dopost... 7 after the log filter! 8 after encoding utf-8 filter! 9 ----------------------------------------
总结:
1.过滤器执行流程
2.常用过滤器
1 <pre name="code" class="plain"><pre></pre><pre name="code" class="plain"></pre><pre></pre> 2 <pre></pre> 3 <pre></pre> 4 <pre></pre> 5 <pre></pre> 6 <pre></pre> 7 <pre></pre> 8 9 </pre>