Spring MVC 的拦截器(Interceptor)是一种在请求处理过程中插入自定义逻辑的机制。它类似于 Servlet 的过滤器(Filter),但与过滤器不同的是,拦截器可以更加细粒度地控制请求处理流程,并且可以访问 Spring MVC 的控制器和模型对象。
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- public class RefreshTokenInterceptor implements HandlerInterceptor{
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- return HandlerInterceptor.super.preHandle(request, response, handler);
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
- }
- }
1. preHandle 方法:
在请求处理之前调用。它允许拦截器在实际的请求处理之前执行一些预处理操作。该方法会返回一个布尔值,用于指示是否继续处理该请求。如果返回 true,则继续往后执行;如果返回 false,则中断请求的处理流程。
2. postHandle 方法:
在请求处理完成后(视图渲染之前)调用。它允许拦截器在请求处理完成后执行一些后处理操作,但不能修改响应内容。可以通过修改传入的 ModelAndView 对象来影响最终的视图渲染结果。该方法走完后拦截器中的其他拦截器仍然有机会进一步处理请求。
3. afterCompletion方法:
在整个请求完成后调用,包括视图渲染完成和异常处理(如果有)。它允许拦截器执行一些资源清理操作或记录请求处理过程中的异常信息。afterCompletion 方法主要用于在整个请求处理流程结束后进行一些资源清理操作或记录请求处理过程中的异常信息等。在该方法中,可以获取到请求处理过程中产生的异常,并对其进行处理。
作为示例,这里我们就在拦截器拦截到请求后执行prehandle方法时进行一个token的校验和有效时间刷新
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- //1.获取请求头中的token
- String token = request.getHeader("authorization");
- if (StrUtil.isBlank(token)) {
- return true;//由于该拦截器主要是做token的有效期刷新功能,具体拦截放行到后面的拦截器
- }
- //2.基于token获取redis中的用户
- String key = LOGIN_USER_KEY + token;
- Map
- //3.判断用户是否存在
- if (userMap.isEmpty()) {
- return true;
- }
- //4.将查询到的hash数据转为UserDTO存到ThreadLocal中
- UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);
- //5.将存在的用户信息保存到ThreadLocal中
- UserHolder.saveUser(userDTO);
- //6.刷新token有效期
- stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.SECONDS);
-
- return true;
- }
写完拦截器,但是我们还没有将写好的拦截器告诉给springmvc让它帮我们进行管理,所以我们现在要创建配置类将拦截器进行注册,注册后拦截器就会成功生效了。
- import com.hmdp.Interceptor.LoginInterceptor;
- import com.hmdp.Interceptor.RefreshTokenInterceptor;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.data.redis.core.StringRedisTemplate;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
- import javax.annotation.Resource;
-
- @Configuration
- public class MvcConfig implements WebMvcConfigurer {
- @Resource
- private StringRedisTemplate stringRedisTemplate;
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- //添加刷新token的拦截器
- registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate))
- .addPathPatterns("/**").order(0);//设置要拦截的请求路径
-
-
- }
- }