Servlet 之 Filter的实现原理

1. 概念

filter 过滤器, 对从客户端向服务端发送的请求进行过滤,也可以对服务端返回的响应进行处理。Filter 不是Servlet,它不能产生一个response,它能否在一个request到达servlet之前预处理request,也可以在response离开servlet时处理response。

在这里插入图片描述
注意:
Filter 只能拦截请求和响应,不能产生响应,而servlet是用来处理请求并产生响应的

2.应用场景

  1. 权限认证
  2. 敏感词过滤
  3. 压缩响应等

3. Filter 拦截流程

  • 当客户端发送请求后,在HttpServletRequest到达Servlet之前,Filter拦截客户端的HttpServletRequest
  • 根据需要检查HttpServletRequest
  • 在Filter调用doFilter对过滤放行。
  • 到达Servlet后,处理请求,并产生HttpServletResponse响应给客户端
  • 在HttpServletResponse到达客户端之前过滤拦截
  • 根据需要对HttpServletResponse进行处理
  • HttpServletResponse 到达客户端

4. Filter生命周期

4.1 filter 有三个重要方法

init() : 初始化参数,在Filter创建时调用,并且只调用一次
doFilter(): 拦截时调用,客户端发送和响应时调用
destroy(): 在销毁FIlter时调用

Filter的创建和销毁由web服务器来控制
当web服务器启动时,创建Filter实例对象,并调用init()方法,filter对象只会创建一次,因此init方法也只会执行一次。
拦截请求时,会执行doFilter方法,因此会执行多次。
当web服务器关闭时,会销毁Filter对象,会调用destroy方法

5. Filter调用的原理

Filter 是基于链式递归调用,如下两个图所示
在这里插入图片描述
在这里插入图片描述
使用代码模拟Filter的调用原理,使用两种方式来实现,计数器和移除方式

  1. 创建Filter接口
package pattern.chain;

public interface Filter {

	void doFilter(FilterChain filter, String something);
	
}
  1. 创建FilterChain接口
    package pattern.chain;
    
    public interface FilterChain {
    
    	void add(Filter filter);
    	
    	void doFilter(String something);
    }
    
  2. 创建FirstFilter实现Filter接口
    package pattern.chain;
    
    public class FirstFilter implements Filter {
    
    	@Override
    	public void doFilter(String request, String response, FilterChain filter) {
    		System.out.println("before first...");
    		filter.doFilter(request, response);
    		System.out.println("after first...");
    		
    	}
    
    }
    
  3. 创建SecondFilter实现Filter接口
    package pattern.chain;
    
    public class SecondFilter implements Filter {
    
    	@Override
    	public void doFilter(String request, String response, FilterChain filter) {
    		System.out.println("befor second...");
    		filter.doFilter(request, response);
    		System.out.println("after second...");
    	}
    
    }
    	```
    
  4. 创建ThirdFilter实现FIlter接口
    package pattern.chain;
    
    public class ThirdFilter implements Filter {
    
    	@Override
    	public void doFilter(String request, String response, FilterChain filter) {
    		System.out.println("before third filter ....");
    		filter.doFilter(request, response);
    		System.out.println("after third filter ....");
    	}
    
    }
    
    
  5. FilterChain实现类的
    基于移除方式实现
    package pattern.chain;
    
    import java.util.LinkedList;
    
    public class FilterChainImpl implements FilterChain {
    
    	private LinkedList<Filter> filters = new LinkedList<>();
    
    	@Override
    	public void add(Filter filter) {
    		filters.add(filter);
    	}
    
    	public boolean hasNextFilter() {
    		return filters.size() > 0;
    	}
    
    	public Filter nextFilter() {
    		return filters.pop();
    	}
    
    	@Override
    	public void doFilter(String request, String response) {
    		if(hasNextFilter()) {
    			nextFilter().doFilter(request, response, this);
    		}
    	}
    }
    
    

基于计数实现方式

package pattern.chain;

import java.util.ArrayList;
import java.util.List;

public class FilterChainImpl implements FilterChain {

	private List<Filter> list = new ArrayList<>();
	
	private int index;
	
	@Override
	public void add(Filter filter) {
		list.add(filter);
	}

	@Override
	public void doFilter(String request, String response) {
		if(index < list.size()) {
			Filter filter = list.get(index);
			index ++;
			filter.doFilter(request, response, this);
		}
	}
}

  1. 测试调用,创建FilterChainMain类
    package pattern.chain;
    
    public class FilterChainMain {
    
    	public static void main(String[] args) {
    		FilterChain filterChain = new FilterChainImpl();
    		filterChain.add(new FirstFilter());
    		filterChain.add(new SecondFilter());
    		filterChain.add(new ThirdFilter());
    		filterChain.doFilter(null, null);
    	}
    	
    }
    
    

结果打印
在这里插入图片描述

6 undertow与tomcat 的Filter实现

undertow 是基于计数实现Filter的调用,实现类是FilterHandler.FilterChainImpl 类
tomcat 是基于计数实现Filter的调用,实现类是ApplicationFilterChain

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值