spring boot拦截器
拦截器都需要实现 HandIerInterceptor 接口
HandlerInterceptor 源码
public interface HandlerInterceptor { // 处理器执行前方法 default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } // 处理器处理后方法 default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } // 处理器完成后方法 default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } }
Interceptor 基于Java的反射机制,属于AOP的一种运用
优点:
由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用
缺点:
只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。
拦截器中方法的执行流程

请求到达 DispatcherServlet,DispatcherServlet 发送至 Interceptor ,执行 preHandle 方法,该方法会返回一个布尔值。如果为 false ,则结束所有流程:如果为 true , 则执行下一步。
请求达到 Controller,执行处理器逻辑,包含控制器的功能 。
执行 postHandle 方法。
执行视图解析和视图渲染 。
执行 afterCompletion 方法。
Spring Boot2整合拦截器Interceptor 示例
1、实现HandlerInterceptor接口编写拦截器,继承HandlerInterceptorAdapter也可以
package com.example.boot_interceptor.interceptor; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptor implements HandlerInterceptor { /** * preHandle在执行Controller之前执行 * 返回true:继续执行处理器逻辑,包含Controller的功能 * 返回false:中断请求 * * 处理器执行前方法 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandler"); return true; } /** * postHandle在请求执行完之后 渲染ModelAndView返回之前执行 * 处理器处理后方法 */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("postHandler"); } /** * afterCompletion在整个请求执行完毕后执行,无论是否发生异常都会执行 * * 处理器完成后方法 */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("afterCompletion"); } }
2、实现WebMvcConfigurer接口注册拦截器
可以用来注册拦截器的类和接口
- WebMvcConfigurationSupport: 不需要返回逻辑视图,可以选择继承此类
- WebMvcConfigurer:返回逻辑视图,可以选择实现此方法,重写addInterceptor方法
package com.example.boot_interceptor.config; import com.example.boot_interceptor.interceptor.MyInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer{ @Override public void addInterceptors(InterceptorRegistry registry) { // 注册拦截器到 Spring MVC 机制, 然后 它会返 回 一个拦截器注册 InterceptorRegistration regist = registry.addInterceptor(new MyInterceptor()); // 指定拦截匹配模式,限制拦截器拦截请求 regist.addPathPatterns("/interceptor/*"); // 不拦截的路径 regist.excludePathPatterns("/interceptor/exclude/*"); } }
3、验证
package com.example.boot_interceptor.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/interceptor") public class TestController { @GetMapping("/test") public String testInterceptor() { System.out.println("执行处理器逻辑testInterceptor...."); return "请观察控制台中拦截器的日志输出"; } @GetMapping("/exclude/test") public String testExcludeInterceptor() { System.out.println("执行处理器逻辑testExcludeInterceptor...."); return "exclude排除,不会被拦截器拦截"; } }
Filter 过滤器

既然是配置在web.xml中,那肯定是依赖于servlet容器.
优点:
- 在实现上Filter是基于函数回调,可以对几乎所有请求进行过滤
缺点:
- 一个过滤器实例只能在容器初始化时调用一次 . 当容器第一次加载该过滤器时,init() 方法将被调用
使用场景:
传统的JavaEE项目开发filter的主要2个步骤
实现Filter接口,并实现其doFilter方法。
在 web.xml 文件中使用<filter>和<filter-mapping>元素对编写的filter类进行注册,并设置它所能拦截的资源
可以开发编写多个Filter,组成一个Filter链,根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter
方式一 FilterRegistrationBean注册
Step1 实现Filter接口 开发过滤器
package com.example.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; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HttpFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("HttpFilter init"); Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("HttpFilter doFilter begin"); HttpServletRequest req =(HttpServletRequest) request; HttpServletResponse res =(HttpServletResponse) response; System.out.println("HttpFilter name:" + request.getParameter("name")); // 将请求转发给过滤器链上下一个对象。这里的下一个指的是下一个filter,如果没有filter那就是请求的资源。 chain.doFilter(request, response); System.out.println("HttpFilter doFilter end"); } @Override public void destroy() { System.out.println("HttpFilter destroy"); Filter.super.destroy(); } }
在配置类中注册该过滤器
package com.example.conf; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.artisan.filter.HttpFilter; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<HttpFilter> httpFilter(){ FilterRegistrationBean<HttpFilter> filterRegistrationBean = new FilterRegistrationBean<HttpFilter>(); // 设置filter filterRegistrationBean.setFilter(new HttpFilter()); // 拦截规则 filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } }
方式二 @WebServlet+ @ServletComponentScan注解的方式
Step1 @WebFilter注解开发过滤器
@WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器
package com.example.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; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebFilter(filterName = "HttpFilter", urlPatterns = "/*") public class HttpFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("HttpFilter init"); Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("HttpFilter doFilter begin"); HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; System.out.println("HttpFilter name:" + request.getParameter("name")); // 将请求转发给过滤器链上下一个对象。这里的下一个指的是下一个filter,如果没有filter那就是请求的资源。 chain.doFilter(request, response); System.out.println("HttpFilter doFilter end"); } @Override public void destroy() { System.out.println("HttpFilter2 destroy"); Filter.super.destroy(); } }
Step2 启动类增加@ServletComponentScan注解
在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册
@SpringBootApplication @ServletComponentScan public class BootInterceptorApplication { public static void main(String[] args) { SpringApplication.run(BootInterceptorApplication.class, args); } }
总结:
Filter的执行顺序在Interceptor之前 。 拦截器(Interceptor)是基于Java的反射机制,而过滤器(Filter)是基于函数回调。从灵活性上说拦截器功能更强大些,Filter能做的事情,Interceptor都能做,而且可以在请求前,请求后执行,比较灵活。

浙公网安备 33010602011771号