zoukankan      html  css  js  c++  java
  • Filter体现职责链模式

     1. 前言

           Filter—Filter 技术是servlet2.3 新添加�的功能。完毕的流程:对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对server响应进行后处理。

           Filter体现了一种职责琏模式。那么他是怎样体现的呢?

    2. 职责链模式

          在详细的解释这个之前先看看职责链模式的定义:使多个对象都有机会处理请求 ,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一个链,并沿着这条链传递请求,直到有一个对象处理它为止。

           对于Filter而言就是,请求传给详细的web资源(比方jsp/servlet)之前要经过Filter的预处理,在web资源处理完毕返回给client之前也要被Filter处理一遍。就好比以下的这样的图

      

           当创建了多个Filter之后,client传来一个Request请求,它就面对着这一个Filter链,职责琏模式就体如今这里。这个请求会在这个Filter链上一个一个被传递下去对它进行预处理,处理完毕之后就传给下一个Filter直到最后一个,然后才交给web进行对应的訪问和处理。它的uml图(并非完毕的结构图,仅仅是体现职责琏模式的结构图)例如以下:

         

           一个Filter接口定义了三个方法:init()(初始化方法);destroy()(销毁方法);doFilter()(核心的职责方法);两个详细类实现了Filter接口:ConcreteFilter1和ConcreteFilter2;

          一个FilterChain接口定义了一个方法:doFilter();一个详细的实现类ConcreteFilterChain;

          当中FilterChain基本的作用是完毕找到下一个Filter。

    3. 详细的实现

         以下是对于上面结构图的一个简单实现,帮助我们理解一下Filter体现的职责琏模式。

       ConcreteFilter1类

    package com.test.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    /**
     * ConcreteFilter1类
     * @author pf
     *
     */
    public class ConcreteFilter1 implements Filter {
    	
    //	private String encoding;
    	
    	@Override
    	public void destroy() {
    		System.out.println("ConcreteFilter1()的destroy()运行");
    	}
    
    	@Override
    	public void doFilter(ServletRequest request, ServletResponse response,
    			FilterChain chain) throws IOException, ServletException {
    		System.out.println("----ConcreteFilter1()的chain.doFilter()调用之前:对用户请求(request)进行预处理");
    		//继续运行
    		//后面有filter继续调用,没有的话就进入到了jsp,一直调用最后
    		chain.doFilter(request, response);
    		System.out.println("ConcreteFilter1()的chain.doFilter()调用之后:对server响应(response)进行后处理");
    	}
    
    	@Override
    	public void init(FilterConfig filterConfig) throws ServletException {
    //		System.out.println("init開始");
    //		this.encoding = filterConfig.getInitParameter("encoding");
    //		System.out.println("init得到encoding:" + encoding);
    		System.out.println("ConcreteFilter1()的init()方法调用");
    		
    	}
    
    }
    

    ConcreteFilter2类

    package com.test.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    /**
     * 採用Filter统一处理字符集
     * @author pf
     *
     */
    public class ConcreteFilter2 implements Filter {
    	
    //	private String encoding;
    	@Override
    	public void destroy() {
    		System.out.println("ConcreteFilter2()的destroy()运行");
    	}
    
    	@Override
    	public void doFilter(ServletRequest request, ServletResponse response,
    			FilterChain chain) throws IOException, ServletException {
    		System.out.println("ConcreteFilter2()的chain.doFilter()调用之前");
    //		request.setCharacterEncoding(encoding);
    		//后面有filter继续调用,没有的话就进入到了jsp,一直调用最后
    		chain.doFilter(request, response);
    		System.out.println("ConcreteFilter2()的chain.doFilter()调用完毕");
    	}
    
    	@Override
    	public void init(FilterConfig filterConfig) throws ServletException {
    //		System.out.println("init開始");
    //		this.encoding = filterConfig.getInitParameter("encoding");
    //		System.out.println("init得到encoding:" + encoding);
    		System.out.println("ConcreteFilter2()的init()方法调用");
    	}
    
    }
    

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.4" 
    	xmlns="http://java.sun.com/xml/ns/j2ee" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    	
    	<filter>
    		<filter-name>ConcreteFilter1</filter-name>
    		<filter-class>com.test.filter.ConcreteFilter1</filter-class>
    	</filter>
    	<filter-mapping>
    		<filter-name>ConcreteFilter1</filter-name>
    		<url-pattern>*.jsp</url-pattern>
    	</filter-mapping>
    		<filter>
    		<filter-name>ConcreteFilter2</filter-name>
    		<filter-class>com.test.filter.ConcreteFilter2</filter-class>
    	</filter>
    	<filter-mapping>
    		<filter-name>ConcreteFilter2</filter-name>
    		<url-pattern>*.jsp</url-pattern>
    	</filter-mapping>
    	
    </web-app>
    

    完毕之后启动server,我这里是tomcat,会显演示样例如以下信息:


    说明在启动server的时候就会创建我们的Filter对象

    随便訪问一个页面再次查看console


           关闭server:说明在关闭server的时候销毁创建的Filter对象

         

           从上面的运行结果再来看一下Filter。我们设置了两个Filter,各自是ConcreteFilter1和ConcreteFilter2.依照我们在web.xml中配置的顺序来运行,先运行了ConcreteFilter1,在运行ConcreteFilter2.

          可是注意观察,他们在真正调用chain的doFilter方法之后的调用顺序正好相反了。所以我们从这个结果能够看到Filter的运行顺序是遵循”后进先出”的原则。现将传来的url依照配置中的顺序进行预处理,可是确实先依照相反的filter顺序运行处理好的请求。

    以下是讲他的调用过程画了一个时序图:


    3. 总结:

           通过上面代码运行的结果来看,Filter非常好的实现了职责链模式,对于不论什么一个请求来讲都有一条Filter链能够处理它,详细是哪一个处理了我们事实上并不知道可是在到达servlet之前就是已经给我们处理好了,这样子就非常好的做到了对象之间的解耦和。



  • 相关阅读:
    redis-cluster
    Mycat-主从结构的准备
    Mycat-多实例的搭建
    MSC添加shard节点
    MongoDB -MSC集群的部署
    MySQL知识-redis实例
    MySQL知识-MySQL不同版本多实例
    #Linux学习# 用户和用户组管理
    #Linux学习# 软件包管理
    #Linux学习# 文本编辑器vim
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4007098.html
Copyright © 2011-2022 走看看