什么是Filter,看名字就是过滤器的意思,主要是针对用户发起的请求进行拦截预处理,常见的Filter应用有检查当前请求是否登录,记录请求日志,设置上下文信息等等,当然Filter也可以对请求的响应做处理,Filter的设计是个典型的责任链模式
Filter的实现和之前Servlet类似,这里我们就只讲基于注解的方式来配置Filter
在上一篇的项目里,新建一个DemoFilter
init
, doFilter
destroy
/*
表示拦截所有请求 @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(); } }