1 拦截器的快速使用
使用拦截器很简单,只需要两步即可:定义拦截器和配置拦截器。在配置拦截器中,Spring Boot 2.0 以后的版本和之前的版本有所不同!
1 定义拦截器
定义拦截器,只需要实现 HandlerInterceptor 接口。
HandlerInterceptor 接口是所有自定义拦截器或者 Spring Boot
提供的拦截器的鼻祖,所以,首先来了解下该接口。该接口中有三个方法,分别为 preHandle(……)、postHandle(……) 和 afterCompletion(……)。
preHandle(……) 方法
该方法的执行时机是,当某个 URL 已经匹配到对应的 Controller 中的某个方法,且在这个方法执行之前。所以
preHandle(……) 方法可以决定是否将请求放行,这是通过返回值来决定的,返回 true 则放行,返回 false 则不会向后执行。
postHandle(……) 方法
该方法的执行时机是,当某个 URL 已经匹配到对应的 Controller 中的某个方法,且在执行完了该方法,但是在
DispatcherServlet 视图渲染之前。所以在这个方法中有个 ModelAndView 参数,可以在此做一些修改动作。
afterCompletion(……) 方法
顾名思义,该方法是在整个请求处理完成后(包括视图渲染)执行,这时做一些资源的清理工作,这个方法只有在 preHandle(……)
被成功执行后并且返回 true 才会被执行。
定义一个拦截器
public class MyHandlerInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(MyHandlerInterceptor.class);
/**
* @description: 拦截在控制方法之前拦截
*
* ,当某个 URL 已经匹配到对应的 Controller 中的某个方法,且在这个方法执行之前。
* 所以 preHandle(……) 方法可以决定是否将请求放行,这是通过返回值来决定的,返回 true 则放行,返回 false 则不会向后执行。
*
* @author: tizzy
* @create: 2019-07-06 18:19
* @version 1.0
**/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
String methodName = method.getName();
logger.info("==== preHandle ===== 拦截到了方法:{},在该方法执行之前执行====", methodName);
// 返回 true 才会继续执行,返回 false 则取消当前请求
return true;
}
/**
* @description: 在渲染页面之前拦截
该方法的执行时机是,当某个 URL 已经匹配到对应的 Controller 中的某个方法,且在执行完了该方法,但是在 DispatcherServlet 视图渲染之前。
所以在这个方法中有个 ModelAndView 参数,可以在此做一些修改动作。
* @author: tizzy
* @create: 2019-07-06 18:20
* @version 1.0
**/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.info("=================== postHandle ================== 执行完方法之后进执行(Controller方法调用之后),但是此时还没进行视图渲染");
}
/**
* @description: 在控制方法正确返回后拦截
*
* 该方法是在整个请求处理完成后(包括视图渲染)执行,这时做一些资源的清理工作,
* 这个方法只有在 preHandle(……) 被成功执行后并且返回 true 才会被执行。
* @author: tizzy
* @create: 2019-07-06 18:20
* @version 1.0
**/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.info("============ afterCompletion =================== 整个请求都处理完咯,DispatcherServlet也渲染了对应的视图咯,此时我可以做一些清理的工作了");
}
}
2 配置拦截器
Spring Boot 2.0 之前,我们都是直接继承 WebMvcConfigurerAdapter 类,然后重写 addInterceptors 方法来实现拦截器的配置。但是在 Spring Boot 2.0 之后,该方法已经被废弃了(当然,也可以继续用),取而代之的是 WebMvcConfigurationSupport 方法,如下:
@Configuration
public class MyInterceptorConfig extends WebMvcConfigurationSupport {
@Override
protected void addInterceptors(InterceptorRegistry registry) {
//配置拦截所有请求
registry.addInterceptor(new MyHandlerInterceptor()).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
测试
@RestController
public class TestController {
@GetMapping("/")
public String getRequestInfo(HttpServletRequest request) {
System.out.println("getRequestInfo " );
return "success";
}
}
2019-07-06 18:28:39.057 INFO 4528 — [nio-8080-exec-5]
c.e.s.config.MyHandlerInterceptor : ==== preHandle =====
拦截到了方法:getRequestInfo,在该方法执行之前执行==== getRequestInfo 2019-07-06
18:28:39.062 INFO 4528 — [nio-8080-exec-5]
c.e.s.config.MyHandlerInterceptor : ===================
postHandle ==================
执行完方法之后进执行(Controller方法调用之后),但是此时还没进行视图渲染 2019-07-06 18:28:39.062
INFO 4528 — [nio-8080-exec-5] c.e.s.config.MyHandlerInterceptor
: ============ afterCompletion ===================
整个请求都处理完咯,DispatcherServlet也渲染了对应的视图咯,此时我可以做一些清理的工作了
3 解决静态资源被拦截问题
http://localhost:8080/a.txt
默认的静态资源无法加载
1 使用上面这种配置的话
resources/static/ 静态资源被拦截
Spring Boot 2.0 废弃了 WebMvcConfigurerAdapter,但是 WebMvcConfigurationSupport 又会导致默认的静态资源被拦截,这就需要我们手动将静态资源放开。
除了在 MyInterceptorConfig 配置类中重写 addInterceptors 方法,还需要再重写一个方法 addResourceHandlers,用来将静态资源放开:
/**
* 用来指定静态资源不被拦截,否则继承 WebMvcConfigurationSupport 这种方式会导致静态资源无法直接访问
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
super.addResourceHandlers(registry);
}
2
我们不继承 WebMvcConfigurationSupport 类,直接实现 WebMvcConfigurer 接口,然后重写 addInterceptors 方法,将自定义的拦截器添加进去即可,如下:
@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 实现 WebMvcConfigurer 不会导致静态资源被拦截
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
}
}
这样就非常方便了,通过实现 WebMvcConfigure 接口,使 Spring Boot 默认的静态资源不会拦截。
拦截器多半用于登录拦截
// 判断用户有没有登陆,一般登陆之后的用户都有一个对应的 token
String token = request.getParameter("token");
if (null == token || "".equals(token)) {
logger.info("用户未登录,没有权限执行……请登录");
response.getWriter().println("error");
return false;
}
// 返回 true 才会继续执行,返回 false 则取消当前请求
return true;
或者根据session 中存放的用户信息 来判断空,也可以判断用户登录!