- HandlerInterceptor接口是Spring框架中用于拦截HTTP请求的接口,它提供了三个方法,分别在请求处理之前、请求处理之后和请求处理完成之后被调用。
实现HandlerInterceptor接口可以帮助我们拦截HTTP请求,并在请求处理之前、之后、以及完成之后执行自定义的逻辑。
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 {
}
}
通常情况下,我们可以使用HandlerInterceptor来实现以下功能:
- 身份认证:在请求处理之前,我们可以使用HandlerInterceptor来检查用户是否已经通过身份认证。如果未通过身份认证,则可以将请求重定向到登录页面或返回错误信息。
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//检查是否认证
if (!isAuthenticated(request)) {
response.sendRedirect("/login");
return false;
}
return true;
}
private boolean isAuthenticated(HttpServletRequest request) {
//检查用户是否认证
// 如果经过身份验证,则返回true,否则返回false
}
}
- 日志记录:在请求处理之前和之后,我们可以使用HandlerInterceptor来记录请求的详细信息,例如请求URL、请求参数、响应状态码等。
@Component
public class LoggingInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(LoggingInterceptor.class);
/**
* LoggerFactory.getLogger(LoggingInterceptor.class)是用于创建日志记录器(Logger)的方法,它是由Slf4j日志框架提供的。
* 在这个例子中,我们使用LoggerFactory.getLogger(LoggingInterceptor.class)方法创建一个名为LoggingInterceptor的日志记录器。
* 日志记录器(Logger)是用于记录应用程序运行时信息的对象。它们通常用于记录调试信息、错误信息、性能信息等。
* Slf4j是一个广泛使用的Java日志框架,它提供了一种简单的方式来记录日志,并且可以与多个日志实现(例如Logback、Log4j、Java Util Logging等)进行集成。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LOGGER.info("收到请求: {} {}", request.getMethod(), request.getRequestURI());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LOGGER.info("已发送响应: {}", response.getStatus());
}
}
实现了一个LoggingInterceptor类,用于记录HTTP请求和响应的详细信息。
在preHandle方法中,我们记录请求的HTTP方法和请求URL。
在afterCompletion方法中,我们记录响应的状态码。
- 性能监控:在请求处理之前和之后,我们可以使用HandlerInterceptor来记录请求的处理时间,以便监控应用程序的性能。
@Component
public class PerformanceInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(PerformanceInterceptor.class);
private static final ThreadLocal<Long> START_TIME = new ThreadLocal<>();
/**
*定义了一个名为START_TIME的ThreadLocal变量,用于在多线程环境下记录请求处理的开始时间。
ThreadLocal是一个Java类,它可以为每个线程存储一个独立的变量副本。
因此,每个线程都可以独立地访问和修改该变量的值,而不会影响其他线程。在多线程环境下,使用ThreadLocal可以避免线程安全问题,从而提高程序的并发性能。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
START_TIME.set(System.currentTimeMillis());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
long duration = System.currentTimeMillis() - START_TIME.get();
LOGGER.info("请求消耗 {} ms: {} {}", duration, request.getMethod(), request.getRequestURI());
}
}
注意,由于ThreadLocal变量是与线程相关的,因在使用完毕后,显式地调用ThreadLocal的remove()方法,以避免内存泄漏。
这个例子中,没有显式地调用remove()方法,因为该变量是静态的,且不会随着线程的结束而被销毁。
- 请求重定向:在请求处理之前或之后,我们可以使用HandlerInterceptor来将请求重定向到其他URL,例如重定向到错误页面或其他应用程序。
@Component
public class RedirectInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//如果需要重定向,则返回true,否则返回false
if (shouldRedirect(request)) {
response.sendRedirect("/new-url");
return false;
}
return true;
}
private boolean shouldRedirect(HttpServletRequest request) {
// 检查是否需要重定向请求
// 如果需要重定向,则返回true,否则返回false
}
}