linux url过滤器,Filter的过滤链理解

一、Filter过滤链

web.xml配置了filter过滤器,在容器启动的时候执行了init()方法进行了初始化,然后在容器关闭的时候执行了destroy()方法销毁过滤器,在每次服务器接受请求的时候每次都会先过一遍过滤器,如果有合适的过滤器就会执行相应过滤器的doFilter方法。

doFilter方法有3个参数 ServletRequest、ServletResponse、FilterChain;前两个分别是请求和返回对象,为的是过滤后还能够进行请求或转发。FilterChain是一个过滤链,他包含了相同过滤条件的所有过滤器,例如:

4094a59d8cfb7eb6f1335e8045061d70.png

类似这种相同匹配模式的过滤器会存在于同一个过滤链中,然后按照初始化的先后顺一次排列,实现逐层过滤。其中filterChain中有个doFilter方法,他的作用是将当前请求转发给过滤链中的下一个过滤器进行过滤,然后将过滤结果,只有等待下一个过滤器执行过滤完成后才能继续执行。该执行过程类似如下图:

253cbced991c265bd0c7e1e27f39c4fb.png

如上图,通过过滤链逐层执行过滤就像一层嵌套,一层套一层,如果过滤链中只有一个过滤器(或者执行到最后一个)的话,执行了chain.doFilter()他会直接将请求转发出去,获取request resource资源,因为从始至终都是同一个request和response在传递,所以每次过滤都可以修改请求或返回结果,实现了过滤修改的目的。

代码实例:(只贴主要代码)

ResponseFilter.java

1 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throwsIOException, ServletException {2 CustomResponseWrapper customResponseWrapper = newCustomResponseWrapper((HttpServletResponse) servletResponse);3 System.out.println("ResponseFilter 执行前");4 filterChain.doFilter(servletRequest,customResponseWrapper);//执行下一层过滤

5 System.out.println("ResponseFilter 执行后");6 }7 }

SecondFilter.java

1 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throwsIOException, ServletException {2 System.out.println("Second doFilter执行前");3 filterChain.doFilter(servletRequest,servletResponse);//这是最后一层过滤器,会直接请求resource

4 System.out.println("Second doFilter执行后");5 }

web.xml (两个过滤器使用了相同的匹配模式‘/*’,所以会处于同一过滤链中)

1

2 ResponseFilter

3 filter.ResponseFilter

4

5

6 ResponseFilter

7 /*

8

9

10 SecondFilter

11 filter.SecondFilter

12

13

14 SecondFilter

15 /*

16

执行结果:

dc3501d5cb52409ee531720a2e53ff32.png

从执行结果并结合以上分析可以很清楚的看出doFilter的执行顺序

二、通过Filter过滤器实现对response内容的修改

CustomPrintWriter.java (重写PrintWriter方法)

1 public class CustomPrintWriter extendsPrintWriter{2 privateStringBuilder buffer;3

4 publicCustomPrintWriter(Writer out) {5 super(out);6 buffer = newStringBuilder();7 }8

9 @Override10 public void write(char[] buf, int off, intlen) {11 char[] dest = new char[len];12 System.arraycopy(buf,off,dest,0,len);//深复制字符数组

13 buffer.append(dest);14 }15

16 publicString getContent() {17 returnbuffer.toString();18 }19 }

CustomResponseWrapper.java (重写HttpServletResponseWrapper方法)

1 public class CustomResponseWrapper extendsHttpServletResponseWrapper{2 privateCustomPrintWriter customPrintWriter;3

4 publicCustomResponseWrapper(HttpServletResponse response) {5 super(response);6 }7

8 @Override9 public PrintWriter getWriter() throwsIOException {10 customPrintWriter = new CustomPrintWriter(super.getWriter());11 returncustomPrintWriter;12 }13

14 publicCustomPrintWriter getCustomPrintWriter() {15 returncustomPrintWriter;16 }17 }

ResponseFilter.java (过滤器)

1 public class ResponseFilter implementsFilter{2 public void init(FilterConfig filterConfig) throwsServletException {}3

4 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throwsIOException, ServletException {5 CustomResponseWrapper customResponseWrapper = newCustomResponseWrapper((HttpServletResponse) servletResponse);6 filterChain.doFilter(servletRequest,customResponseWrapper);//转发请求获取请求返回结果

7 CustomPrintWriter writer = customResponseWrapper.getCustomPrintWriter();//获取请求的返回结果

8 if(writer != null){9 String content =writer.getContent();10 /**

11 * 在不修改jsp源码的情况下修改展示内容12 */

13 content = content.replace("XXX", LoginCheckServlet.username);14 servletResponse.getWriter().write(content);15 }16 }17

18 public voiddestroy() {}19 }

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值