设计模式之 责任链设计模式 下 实战

上一节讲了责任链设计模式的原理和应用场景,本节就来看一个实际应用案例。

我们要分析的就是Java Web项目中的Filter。

Servlet中的Filter的作用就是在浏览器请求实际执行到目标Servlet之前,做前置处理,并可以在目标Servlet将结果返回到浏览器之前,对返回结果进行处理。

首先基于maven新建一个web项目,我们以idea为例,新建web项目。

1、菜单 File–>New–>Project

2、选择Maven,选择“maven-archetype-webapp”

3、定义Manve项目的GroupId和ArtifactId

这样就生成了一个WEB项目,接下来我们新建两个Filter类,分别是FilterA和FilterB。

package com.itzhimei.study;

import java.io.IOException;

public class FilterA implements javax.servlet.Filter {
    public void destroy() {
    }

    public void doFilter(javax.servlet.ServletRequest req, javax.servlet.ServletResponse resp, javax.servlet.FilterChain chain) throws javax.servlet.ServletException, IOException {
        System.out.println("FilterA Start...");
        chain.doFilter(req, resp);
        System.out.println("FilterA End...");
    }

    public void init(javax.servlet.FilterConfig config) throws javax.servlet.ServletException {

    }

}
package com.itzhimei.study;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "FilterB")
public class FilterB implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("FilterB Start...");
        chain.doFilter(req, resp);
        System.out.println("FilterB End...");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

web.xml添加配置:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <filter>
    <filter-name>FilterA</filter-name>
    <filter-class>com.itzhimei.study.FilterA</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>FilterA</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <filter>
    <filter-name>FilterB</filter-name>
    <filter-class>com.itzhimei.study.FilterB</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>FilterB</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
</web-app>

启动这个web服务,并访问首页:

localhost:8080/

输出结果:

FilterA Start...
FilterB Start...
业务Servlet
FilterB End...
FilterA End...

我们按照结果,可以大概倒推出来Filter的逻辑:配置的责任链会依次执行,Filter的执行是在真正的目标Servlet之前和之后执行的。效果如下图:

两个Filter和Servlet的执行,就像是又给链条,一个接一个的执行,浏览器请求到后端服务后,先执行FilterA的code代码,然后执行chain.doFilter()方法;然后执行FilterB的code代码,然后执行chain.doFilter()方法,将请求继续像后传递继续执行,直到业务Servlet执行完成返回,又会依次执行B的code,A的code,然后返回结果给浏览器。

我们对代码进行断点,可以看到,项目中定义的Filter都会存到filters中,当前项目中有3个filter,两个是我们定义的,一个是tomcat的。

每当调用chain.doFilter()的时候,都会从filters中取出下一个filter继续执行。

pos表示当前执行到那个filter,n表示一个有多少个filter。

好了,这节就到这里,动手来自己写一下吧。