实现过滤器需要实现 javax.servlet.Filter
接口。重写三个方法。其中 init()
方法在服务启动时执行,destroy()
在服务停止之前执行。
可用两种方式注册过滤器:
FilterRegistrationBean
来注入。可使用 setOrder(0)
设置过滤器的优先级,越小优先级越高。@WebFilter(filterName = "myFilter2" ,urlPatterns = "/*")
配合 @ServletComponentScan()
实现注入。(@Order
注解无效)package com.example.recorddemo.filters; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; public class MyFilter1 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("初始化过滤器:" + filterConfig.getFilterName()); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("在请求之前做处理"); if (servletRequest instanceof HttpServletRequest) { System.out.println(" URL:" + ((HttpServletRequest)servletRequest).getRequestURL()); } // 调用filter链中的下一个filter filterChain.doFilter(servletRequest, servletResponse); System.out.println("在请求之后做处理"); } @Override public void destroy() { System.out.println("销毁:MyFilter1"); } }
在配置类中注册一个 FilterRegistrationBean
类型的Bean。
UrlPatterns
, 那么会自动关联到 /*
上。When no URL pattern or servlets are specified the filter will be associated to ‘/*’. The filter name will be deduced if not specified.
setOrder(0)
方法设置过滤器的优先级,如果优先级相同,则先定义的优先级更高。@Configuration public class FilterConfiguration { @Bean public FilterRegistrationBean myFilter1(){ MyFilter1 filter = new MyFilter1(); FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter); // filterRegistrationBean.addUrlPatterns("/*"); // filterRegistrationBean.setEnabled(true); return filterRegistrationBean; } }
@WebFilter
修饰filter。@ServletComponentScan("com.example.recorddemo.filters")
,包名可以不填。import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @WebFilter(filterName = "myFilter2" ,urlPatterns = "/*") public class MyFilter2 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // 调用filter链中的下一个filter filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() {} }
拦截器会在处理指定请求之前和之后进行相关操作,配置拦截器需要两步
HandlerInterceptor
接口)WebMvcConfigurer
接口,并重写 addInterceptors()
方法)addPathPatterns()
规定拦截哪些请求。(/*
表示只拦截/
下的所有目录,但是不包括子目录, /**
表示拦截/
下的所有目录,及其子目录)拦截器类:
package com.example.recorddemo.interceptor; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author wangchao */ @Component public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // handle可拿到执行方法的反射对象。 System.out.println("preHandle: MyInterceptor"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 对于RESTful 接口用处不大 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 可捕捉异常,但是springboot已经有了全局异常捕捉 } }
配置拦截器:
package com.example.recorddemo.configuration; import com.example.recorddemo.interceptor.MyInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.config.annotation.InterceptorRegistration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; @Configuration public class InterceptorConfiguration implements WebMvcConfigurer { @Resource MyInterceptor myInterceptor; /** * 添加拦截器 * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myInterceptor).addPathPatterns("/**"); } }
registry.addInterceptor()
方法会返回当前的 interceptor
, 因此可直接执行 addPathPatterns()
方法
public InterceptorRegistration addInterceptor(HandlerInterceptor interceptor) { InterceptorRegistration registration = new InterceptorRegistration(interceptor); this.registrations.add(registration); return registration; }
拦截器的执行顺序类似于栈,按照如下顺序执行:
preHandle-1, preHandle-2, postHandle-2, postHandle-1, afterCompletion-2, afterCompletion-1