拦截器

tim-qtp...大约 3 分钟SpringBoot框架

在项目中通常是使用拦截器来进行权限校验、日志记录、处理异常等问题。具体实现如下:

1)实现 HandlerInterceptor 接口,并实现接口中的方法,方法里面包括了几个请求时间点:请求前、请求后 、整个请求结束后(用于资源清理等操作)。

2)通过实现 WebMvcConfigurer 的 addInterceptors 方法来添加自定义的拦截器。

具体代码如下:

1)创建拦截器类: 需要实现 HandlerInterceptor 接口或继承 HandlerInterceptorAdapter(Spring 5.3 及以前)。这个接口提供了三个关键方法:

  • preHandle():在请求到达控制器之前执行,可以进行身份验证、权限校验等操作。
  • postHandle():在控制器处理完请求后但还未渲染视图时执行,可以对响应进行修改。
  • afterCompletion():在视图渲染完成后执行,可以用于资源清理等操作。

示例

public class MyInterceptor implements HandlerInterceptor {

   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       System.out.println("面试鸭请求开始前");
       return true;  // 返回 true 继续处理,false 则拦截请求
   }

   @Override
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       System.out.println("面试鸭请求后");
   }

   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception {
       System.out.println("面试鸭请求完成");
   }
}

2)注册拦截器: 在 Spring Boot 中,需要创建一个配置类,继承 WebMvcConfigurer 接口并实现 addInterceptors() 方法,将自定义的拦截器注册到应用中。

示例

@Configuration
public class WebConfig implements WebMvcConfigurer {

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(new MyInterceptor()).addPathPatterns("/api/**");  // 拦截指定路径
   }
}

在这个例子中,拦截器会拦截所有 /api/** 路径下的请求。

扩展知识

拦截器使用简单示例

1)用户身份验证:在 preHandle() 方法中,可以检查用户的登录状态或 token 是否有效。如果用户未登录或 token 无效,可以在这里返回错误响应,直接终止请求。

示例

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
   String token = request.getHeader("Authorization");
   if (token == null || !validateToken(token)) {
       response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
       return false;
   }
   return true;
}

2)日志记录和性能监控

可以在 preHandle() 方法中记录请求开始的时间,在 afterCompletion() 方法中计算处理请求所花费的时间,从而进行性能监控。同时可以记录请求和响应的日志信息,监控应用的行为。

示例

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
   request.setAttribute("startTime", System.currentTimeMillis());
   return true;
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
   long startTime = (Long) request.getAttribute("startTime");
   long endTime = System.currentTimeMillis();
   System.out.println("Request URL: " + request.getRequestURL() + " | Time Taken: " + (endTime - startTime) + " ms");
}

多个拦截器的链式调用

Spring Boot 支持为同一路径配置多个拦截器。拦截器是按照注册的顺序执行的,preHandle() 会按照顺序调用,postHandle()afterCompletion() 则会按照相反的顺序调用。

示例

registry.addInterceptor(new FirstInterceptor()).addPathPatterns("/api/**");
registry.addInterceptor(new SecondInterceptor()).addPathPatterns("/api/**");

在这个例子中,FirstInterceptorpreHandle() 先执行,而 postHandle()afterCompletion() 最后执行。这样可以实现拦截器链的灵活控制。