全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 6 分钟 ✍️ juanwangdev

Spring MVC 实现HandlerInterceptor接口

HandlerInterceptor接口是Spring MVC拦截器的核心接口,包含三个方法分别在不同时机执行。

接口定义

Java
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,
                            ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request,
                                 HttpServletResponse response,
                                 Object handler,
                                 Exception ex) throws Exception {
    }
}

基本实现方式

方式一:直接实现接口

Java
@Component
public class SimpleInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler) throws Exception {
        log.info("preHandle: {}", request.getRequestURI());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView modelAndView) throws Exception {
        log.info("postHandle: {}", request.getRequestURI());
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) throws Exception {
        log.info("afterCompletion: {}", request.getRequestURI());
    }
}

方式二:继承HandlerInterceptorAdapter

Java
@Component
public class LegacyInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler) throws Exception {
        // 只覆盖需要的方法
        return true;
    }
}

HandlerInterceptorAdapter已废弃,推荐直接实现接口(接口方法均为default)。

preHandle方法实现

Java
@Override
public boolean preHandle(HttpServletRequest request,
                        HttpServletResponse response,
                        Object handler) throws Exception {
    // 1. 获取请求信息
    String uri = request.getRequestURI();
    String method = request.getMethod();
    String ip = request.getRemoteAddr();

    // 2. 获取Handler信息
    if (handler instanceof HandlerMethod) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        String controllerName = handlerMethod.getBeanType().getSimpleName();
        String methodName = handlerMethod.getMethod().getName();

        log.info("请求: {} -> {}.{}", uri, controllerName, methodName);
    }

    // 3. 前置处理逻辑
    request.setAttribute("startTime", System.currentTimeMillis());

    // 4. 返回true继续执行,返回false中断请求
    return true;
}

返回false中断请求

Java
@Override
public boolean preHandle(HttpServletRequest request,
                        HttpServletResponse response,
                        Object handler) throws Exception {
    HttpSession session = request.getSession(false);

    if (session == null || session.getAttribute("user") == null) {
        // 未登录,中断请求并重定向
        response.sendRedirect("/login");
        return false;
    }

    return true;
}

postHandle方法实现

Java
@Override
public void postHandle(HttpServletRequest request,
                       HttpServletResponse response,
                       Object handler,
                       ModelAndView modelAndView) throws Exception {
    // 1. 添加公共数据
    if (modelAndView != null) {
        modelAndView.addObject("timestamp", System.currentTimeMillis());
        modelAndView.addObject("version", "1.0.0");
    }

    // 2. 计算处理时间
    Long startTime = (Long) request.getAttribute("startTime");
    long duration = System.currentTimeMillis() - startTime;
    request.setAttribute("duration", duration);

    // 3. 修改响应头
    response.setHeader("X-Process-Time", String.valueOf(duration));
}

postHandle限制

Controller抛出异常时postHandle不执行。

afterCompletion方法实现

Java
@Override
public void afterCompletion(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler,
                            Exception ex) throws Exception {
    // 1. 计算总耗时
    Long startTime = (Long) request.getAttribute("startTime");
    long duration = System.currentTimeMillis() - startTime;

    // 2. 记录日志
    if (ex != null) {
        log.error("请求异常: {} {}, 耗时: {}ms, 异常: {}",
            request.getMethod(), request.getRequestURI(), duration, ex.getMessage());
    } else {
        log.info("请求完成: {} {}, 耗时: {}ms, 状态: {}",
            request.getMethod(), request.getRequestURI(), duration, response.getStatus());
    }

    // 3. 清理资源
    UserContext.clear();
    TraceContext.clear();

    // 4. 清理请求属性
    request.removeAttribute("startTime");
}

Handler参数详解

Java
@Override
public boolean preHandle(HttpServletRequest request,
                        HttpServletResponse response,
                        Object handler) throws Exception {
    if (handler instanceof HandlerMethod) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;

        // 获取Controller类
        Class<?> controllerClass = handlerMethod.getBeanType();

        // 获取方法
        Method method = handlerMethod.getMethod();

        // 获取方法参数
        MethodParameter[] parameters = handlerMethod.getMethodParameters();

        // 获取方法注解
        Annotation[] annotations = method.getAnnotations();

        // 获取方法上的特定注解
        MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);

        // 获取类上的注解
        MyAnnotation classAnnotation = controllerClass.getAnnotation(MyAnnotation.class);
    }

    return true;
}

注册拦截器

Java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private SimpleInterceptor simpleInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(simpleInterceptor)
            .addPathPatterns("/**")            // 拦截所有路径
            .excludePathPatterns("/static/**") // 排除静态资源
            .order(1);                         // 设置执行顺序
    }
}

拦截器注解配置

Java
// 定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    String value() default "";
}

// 拦截器实现
@Component
public class AnnotationInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Log logAnnotation = handlerMethod.getMethodAnnotation(Log.class);

            if (logAnnotation != null) {
                log.info("注解日志: {}", logAnnotation.value());
            }
        }
        return true;
    }
}

// Controller使用
@RestController
public class UserController {

    @Log("查询用户列表")
    @GetMapping("/users")
    public List<User> listUsers() {
        return userService.findAll();
    }
}

异步请求拦截器

Java
@Component
public class AsyncInterceptor implements HandlerInterceptor, AsyncHandlerInterceptor {

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request,
                                               HttpServletResponse response,
                                               Object handler) throws Exception {
        log.info("异步处理开始: {}", request.getRequestURI());
    }
}

实现注意事项

注意点说明
preHandle返回值true继续执行,false中断请求
postHandle执行条件Controller无异常时执行
afterCompletion执行条件preHandle返回true的拦截器才执行
ModelAndView参数REST接口返回null,传统接口有值
Exception参数无异常时为null
资源清理afterCompletion中清理ThreadLocal

要点总结

  • 直接实现HandlerInterceptor接口,三个方法均为default
  • preHandle返回true继续,返回false中断请求
  • postHandle只在Controller无异常时执行
  • afterCompletion无论是否有异常都执行
  • handler参数可获取Controller和方法信息
  • 必须在WebMvcConfigurer中注册拦截器

📝 发现内容有误?点击此处直接编辑

← 上一篇 Spring MVC 多个拦截器的执行顺序
下一篇 → Spring MVC 拦截器与过滤器的区别
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库