
应用场景
1、登录验证
以后台管理系统为例,大部分接口都应该要求做登录验证。如果每个方法里都加上登录状态检查,那未免太麻烦了,而且也不利于维护。应当把登录验证这个动作封装起来,以便复用。
2、数据统计 / 监控
比如使用 redis 统计指定页面的访问量等
如何使用拦截器?
控制器
先写一个测试的方法:
package com.example.boot.controller;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;import java.util.Map;@RestController@Slf4jpublic class TestController {@RequestMapping("/test/index")public Map index() {Map<String, Object> map = new HashMap<>();map.put("code", 1);map.put("msg", "ok");map.put("data", null);return map;}}

ok,能正常访问测试接口了。
1、编写拦截器类
实现 HandlerInterceptor 接口,并使用 @Component 注解自动注入到容器中。
LoginInterceptor
package com.example.boot.interceptor;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Component;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.util.Enumeration;import java.util.Map;@Component@Slf4jpublic class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("LoginInterceptor -> preHandle 执行了");// HttpSession session = request.getSession();// Map<String, String[]> parameterMap = request.getParameterMap();// Enumeration<String> parameterNames = request.getParameterNames();// urlString scheme = request.getScheme();String serverName = request.getServerName();int serverPort = request.getServerPort();String requestURI = request.getRequestURI();StringBuffer requestURL = request.getRequestURL();log.info("LoginInterceptor -> preHandle -> scheme: {}", scheme);log.info("LoginInterceptor -> preHandle -> serverName: {}", serverName);log.info("LoginInterceptor -> preHandle -> serverPort: {}", serverPort);log.info("LoginInterceptor -> preHandle -> requestURI: {}", requestURI);log.info("LoginInterceptor -> preHandle -> requestURL: {}", requestURL);// headerString userAgentHeader = request.getHeader("User-Agent");log.info("LoginInterceptor -> preHandle -> userAgentHeader: {}", userAgentHeader);Enumeration<String> headerNames = request.getHeaderNames();while (headerNames.hasMoreElements()) {String name = headerNames.nextElement();//通过请求头的名称获取请求头的值String value = request.getHeader(name);log.info("LoginInterceptor -> preHandle -> userAgentHeaders: {} -> {}", name, value);}// cookieCookie[] cookies = request.getCookies();for (Cookie cookie : cookies) {log.info("LoginInterceptor -> preHandle -> cookies: {} -> {}", cookie.getName(), cookie.getValue());}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("LoginInterceptor -> postHandle 执行了");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("LoginInterceptor -> afterCompletion 执行了");}}
2、将拦截器注册到容器中,指定拦截规则
新建一个配置类,使用 @Autowired 注解将拦截器自动装配到配置类中。
实现 WebMvcConfigurer 接口的 addInterceptors 方法。
MyWebMvcConfig
package com.example.boot.config;import com.example.boot.interceptor.LoginInterceptor;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class MyWebMvcConfig implements WebMvcConfigurer {@AutowiredLoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/css/**","/js/**","/images/**");}}
拦截所有请求
addPathPatterns -> /**
放行下列请求
excludePathPatterns -> “”,””
3、测试效果


应该注意哪些东西?
1、公共规则抽取
如果拦截器数量较多,应当把公共规则抽象出来。
public void addInterceptors(InterceptorRegistry registry) {// 公共拦截规则String[] PublicAddPathPatterns = {"/**"};// 公共放行路径规则String[] PublicExcludePathPatterns = {"/static/**","/css/**","/js/**","/images/**"};registry.addInterceptor(loginInterceptor).addPathPatterns(PublicAddPathPatterns).excludePathPatterns(PublicExcludePathPatterns);registry.addInterceptor(login2Interceptor).addPathPatterns(PublicAddPathPatterns).excludePathPatterns(PublicExcludePathPatterns);}
2、不要使用 new 的方式手动创建拦截器实例
如果拦截器内使用了 @Autowired 注解自动装配,那么 new 出来的拦截器中,@Autowired 注解将会失效。
推荐在配置类中,使用 @Autowired 注解自动装配拦截器,而不是 new 的方式。
Reference
1、Springboot过滤器和拦截器详解及使用场景:https://zhuanlan.zhihu.com/p/340397290
