Filter是什么
什么是Filter,看名字就是过滤器的意思,主要是针对用户发起的请求进行拦截预处理,常见的Filter应用有检查当前请求是否登录,记录请求日志,设置上下文信息等等,当然Filter也可以对请求的响应做处理,Filter的设计是个典型的责任链模式
- 客户端发起http请求
- web容器接受到请求后,调用拦截器链,依次调用各个Filter
- 每个Filter执行完自己的逻辑后,显式调用chain.doFilter,进行下个Filter的执行,最终调用到目标servlet
- 返回servlet数据到客户端
如何实现一个Filter
Filter的实现和之前Servlet类似,这里我们就只讲基于注解的方式来配置Filter
在上一篇的项目里,新建一个DemoFilter
- 实现Filter接口,可实现三个方法
init
,doFilter
destroy
- 添加WebFilter注解,其中urlPatterns表示当前Filter需要拦截匹配的url , 这里我们配置
/*
表示拦截所有请求
@WebFilter(filterName = "demoFilter",urlPatterns = "/*")
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("do filter");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("filter destroy");
}
}
应用在启动时会调用filter的init方法,需要特别注意的是,在每个filter的实现里需要显式调用chain.doFilter方法,否则会导致当前请求无法触达到最终的Servlet实现
每当发起一个HTTP请求,就会匹配filter的urlPattern,如果匹配上则进入filter的doFilter方法,多个filter的顺序调用需要显式的调用chain.doFilter方法
责任链模式
Filter主要是责任链模式的实现,模拟实现拦截器实现
抽象处理类
public abstract class Filter {
//顺序
protected Long order;
public Long getOrder() {
return order;
}
public void setOrder(Long order) {
this.order = order;
}
//核心处理方法
abstract boolean doFilter();
}
实际处理类
public class AuthFilter extends Filter{
public AuthFilter(Long order) {
super.order=order;
}
@Override
boolean doFilter() {
System.out.println("AuthFilter");
return true;
}
}
public class LogFilter extends Filter{
public LogFilter(Long order) {
super.order=order;
}
@Override
boolean doFilter() {
System.out.println("LogFilter");
return true;
}
}
责任链类
public class FilterChain {
List<Filter> filterList = new LinkedList<>();
public void doFilter(){
List<Filter> collect = filterList.stream().sorted(Comparator.comparing(Filter::getOrder)).collect(Collectors.toList());
for (Filter filter : collect) {
if(!filter.doFilter()){
break;
}
}
}
public boolean add(Filter filter){
return filterList.add(filter);
}
}
测试链路
public class FilterTest {
public static void main(String[] args) {
AuthFilter authFilter = new AuthFilter(1L);
LogFilter logFilter = new LogFilter(2L);
FilterChain chain =new FilterChain();
chain.add(authFilter);
chain.add(logFilter);
chain.doFilter();
}
}