深入学习SSH框架《三:Servlet中配置过滤器Filter和异步过滤器》

来源:互联网 发布:好学近乎知原文 编辑:程序博客网 时间:2024/05/16 10:19

在SSH应用程序中过滤器是一个很重要的角色,它有以下目的:

过滤器可以拦截访问资源的请求、资源的响应或者两个同时拦截,它们将以某种方式作用于这些请求或响应,过滤器可以检测和修改请求和响应,它们甚至可以拒绝和转发请求。其中过滤器也可编程式配置和在部署描述符中配置。过滤经常用在一下模块==》日志过滤器验证过滤器压缩和加密过滤器错误处理过滤器


1.过滤器的实现。

public class RequestLogFilter implements Filter{    @Override    public void doFilter(ServletRequest request, ServletResponse response,                         FilterChain chain) throws IOException, ServletException    {        Instant time = Instant.now();        StopWatch timer = new StopWatch();        try        {            timer.start();            chain.doFilter(request, response);        }        finally        {            timer.stop();            HttpServletRequest in = (HttpServletRequest)request;            HttpServletResponse out = (HttpServletResponse)response;            String length = out.getHeader("Content-Length");            if(length == null || length.length() == 0)                length = "-";            System.out.println(in.getRemoteAddr() + " - - [" + time + "]" +                    " \"" + in.getMethod() + " " + in.getRequestURI() + " " +                    in.getProtocol() + "\" " + out.getStatus() + " " + length +                    " " + timer);        }    }    @Override    public void init(FilterConfig filterConfig) throws ServletException { }    @Override    public void destroy() { }}

2.部署过滤器。

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">  <display-name>Filter Order Application</display-name>  <filter>    <filter-name>filterA</filter-name>    <filter-class>com.wrox.FilterA</filter-class>    <async-supported>true</async-supported>   </filter>  <filter-mapping>    <filter-name>filterA</filter-name>    <url-pattern>/*</url-pattern>    <!-- <servlet-name>async</servlet-name> -->    <dispatcher>ASYNC</dispatcher>    <!-- <dispatcher>REQUEST</dispatcher> -->  </filter-mapping>  <filter>    <filter-name>filterB</filter-name>    <filter-class>com.wrox.FilterB</filter-class>  </filter>  <filter-mapping>    <filter-name>filterB</filter-name>    <url-pattern>/servletTwo</url-pattern>    <url-pattern>/servletThree</url-pattern>  </filter-mapping>  <filter>    <filter-name>filterC</filter-name>    <filter-class>com.wrox.FilterC</filter-class>  </filter>  <filter-mapping>    <filter-name>filterC</filter-name>    <url-pattern>/servletTwo</url-pattern>  </filter-mapping></web-app>

其中要注意的是filter有一个支持异步属性,
<dispatcher>ASYNC</dispatcher>有效的类型还有REQUEST,FORWARD,INCLUDE,ERROR和ASYNC意思是该过滤器支持的
类型是请求、转发、包含、错误和异步类型,比如下面的示例:

@WebServlet(urlPatterns="/async", asyncSupported=true,name="async")public class AsynServlet extends HttpServlet {private static final long serialVersionUID = 1L;private HttpServletResponse responseAsyn;    /**     * @see HttpServlet#HttpServlet()     */    public AsynServlet() {        super();        // TODO Auto-generated constructor stub    }    @Override      protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {              responseAsyn=resp;    resp.setContentType("text/html;charset=UTF-8");              PrintWriter out = resp.getWriter();              out.println("进入Servlet的时间:" + new Date() + ".");              out.flush();                //在子线程中执行业务调用,并由其负责输出响应,主线程退出              final AsyncContext ctx = req.startAsync();              ctx.setTimeout(200000);              new Work(ctx,responseAsyn).start();              out.println("结束Servlet的时间:" + new Date() + ".");              out.flush();      }  }    class Work extends Thread{      private AsyncContext context;      private HttpServletResponse response;      public Work(AsyncContext context,HttpServletResponse response){          this.context = context;          this.response=response;    }      @Override      public void run() {          try {              Thread.sleep(2000);//让线程休眠2s钟模拟超时操作              PrintWriter wirter = context.getResponse().getWriter();                       response.sendRedirect("/servletOne");            wirter.write("2s后调用servletOne");              wirter.flush();              context.complete();          } catch (InterruptedException e) {                        } catch (IOException e) {                        }      }  }

3.使用注解声明过滤器

package com.wrox;import javax.servlet.DispatcherType;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter;import javax.xml.ws.Dispatch;import java.io.IOException;@WebFilter(urlPatterns={"/servlet/*","/servletone"},servletNames={"servletTwo"},dispatcherTypes={DispatcherType.ASYNC})public class FilterA implements Filter{    @Override    public void doFilter(ServletRequest request, ServletResponse response,                         FilterChain chain) throws IOException, ServletException    {        System.out.println("Entering FilterA.doFilter().ASNY!!!");        chain.doFilter(request, response);        System.out.println("Leaving FilterA.doFilter().");    }    @Override    public void init(FilterConfig config) throws ServletException {    System.out.println("进入了过滤器的init方法==>");    }    @Override    public void destroy() { }}

4.过滤器的排序

由于注解标识的过滤器无法按照需要的顺序过滤,所以只能使用部署描述符进行过滤。排在越前的过滤器先执行,过滤器链就像一条流水线,一个出错了就不会继续执行过滤,实例代码.

5.过滤器处理异步请求。

import javax.servlet.AsyncContext;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpServletResponseWrapper;import java.io.IOException;public class AnyRequestFilter implements Filter{    private String name;    @Override    public void init(FilterConfig config)    {        this.name = config.getFilterName();    }    @Override    public void doFilter(ServletRequest request, ServletResponse response,                         FilterChain chain) throws IOException, ServletException    {        System.out.println("Entering " + this.name + ".doFilter().");        chain.doFilter(                new HttpServletRequestWrapper((HttpServletRequest)request),                new HttpServletResponseWrapper((HttpServletResponse)response)        );        if(request.isAsyncSupported() && request.isAsyncStarted())        {            AsyncContext context = request.getAsyncContext();            System.out.println("Leaving " + this.name + ".doFilter(), async " +                    "context holds wrapped request/response = " +                    !context.hasOriginalRequestAndResponse());        }        else            System.out.println("Leaving " + this.name + ".doFilter().");    }    @Override    public void destroy() { }}

其中异步过滤器只有在标注了异步(@WebServlet(urlPatterns="/async", asyncSupported=true,name="async")或者 
<filter>
    <filter-name>filterA</filter-name>
    <filter-class>com.wrox.FilterA</filter-class>
    <async-supported>true</async-supported> 
  </filter>
才会执行

有关更多实例代码,在我的github地址



1 0