首页 > 代码库 > Head-First Servelts&JSP reading note 5

Head-First Servelts&JSP reading note 5

Filter

过滤器就是一个对所有的请求进行intercept(拦截),然后对请求进行相应的处理,或者servlet处理完成之后,对response进行处理等。

而这一切,servlet永远不可能知道。

 

Filter和Servlet的相同点

1 容器也知道Filter的API

一旦一个java类实现了Filter接口,他就正式的成为了一个过滤器,容器中它也就被注册了。

2 容器管理他们的生命周期

他们也有init和destory方法,不同的是servlet有service方法(doGet/doPost),而filter拥有的是doFileter()方法

3 他们都是被部署在DD中

一个程序可能会拥有多个filter,并且DD中配置了哪一个filter会执行,按照什么顺序执行等。

 

实现一个Filter

如下是一个基本的Filter。

public class BeerRequestFilter implements Filter {    private FilterConfig fc;    public void init(FilterConfig config) throws ServletException {        this.fc = config;    }    public void doFilter(ServletRequest req,                ServletResponse resp,                FilterChain chain) throws ServletException, IOException {        HttpServletRequest httpReq = (HttpServletRequest) req;        String name = httpReq.getRemoteUser();        if (name != null) {            fc.getServletContext().log(“User “ + name + “ is updating”);        }        chain.doFilter(req, resp);    }    public void destroy() {        // do cleanup stuff    }}

1 init方法,接受一个FilterConfig对象作为参数,一般用来初始化Filter中的FilterConfig;

2 destory方法,基本上就是一个空方法;

3 doFilter(ServletRequest req, ServletResponse res, FilterChain chain),前两个参数就是传递进来的请求和响应,而chain是Filter的过滤链。

虽然是ServletRequest,但是我们可以保证他就是一个HttpServletRequest,同理,ServletResponse也肯定是一个HttpServletResponse。

chain.doFileter(req, res);是得以下一个Filter或者是Servlet能够继续进行的原因。

从FilterConfig中能够获得到一个ServletContext对象。

 

DD 设定

filter中filter-name和filter-class是必须的

<filter>    <filter-name>BeerRequest</filter-name>    <filter-class>com.example.web.BeerRequestFilter</filter-class>    <init-param>        <param-name>LogFileName</param-name>        <param-value>UserLog.txt</param-value>    </init-param></filter>

filter-mapping中的filter-name是必须的,另外url-pattern或者servlet-name也是必须的

<filter-mapping>    <filter-name>BeerRequest</filter-name>    <url-pattern>*.do</url-pattern></filter-mapping>

<filter-mapping>    <filter-name>BeerRequest</filter-name>    <servlet-name>AdviceServlet</servlet-name></filter-mapping>

 

对response进行处理

如果想要对response进行处理的话,只需要在

chain.doFilter(req, res);后面进行即可,因为在doFilter的时候已经能够保证servlet已经被执行完成了。

 

wrapper

1 Filter的chain.doFilter(req, res);调用之后,request和response对象传递给下一个filter或者servlet。

2 Servlet执行它的doPost或者doGet方法之后,会跳出方法调用栈,然后filter处在栈的顶层。

3 Servlet完成之后,response会直接发送给客户端,而不是先返回给filter。

4 所以在filter中的chain.doFilter之后的代码对response的处理都太晚了

 

所谓的包装器就是把一个HttpServletRequest或者一个HttpServletResponse对象进行包装,其实质就是把默认的行为进行修改。

有四个Wrapper,分别为:

ServletRequestWrapper

ServletResponseWrapper

HttpServletRequestWrapper

HttpServletResponseWrapper

其中后两种用途较大,HttpServletRequestWrapper已经实现了HttpServletRequest接口了。同样HttpServletResponseWrapper实现了HttpServletResponse接口。

我们只需要把想要修改的行为进行@Override或者追加新的机能就可以了。