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

Spring MVC afterCompletion方法详解

afterCompletion是HandlerInterceptor接口的三个核心方法之一,在视图渲染完成后执行,用于资源清理和日志记录。

方法定义

Java
void afterCompletion(HttpServletRequest request,
                     HttpServletResponse response,
                     Object handler,
                     Exception ex) throws Exception;

执行时机

Java
请求到达
    ↓
preHandle() → 返回true继续
    ↓
Controller处理
    ↓
postHandle() → 视图渲染前
    ↓
视图渲染完成
    ↓
afterCompletion() → 无论是否异常都会执行

参数详解

参数类型说明
requestHttpServletRequest当前HTTP请求对象
responseHttpServletResponse当前HTTP响应对象
handlerObject处理器对象(HandlerMethod)
exException处理过程中抛出的异常,无异常则为null

基本实现

Java
@Component
public class LogInterceptor implements HandlerInterceptor {

    private static final String START_TIME = "startTime";

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

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) {
        Long startTime = (Long) request.getAttribute(START_TIME);
        long duration = System.currentTimeMillis() - startTime;

        String uri = request.getRequestURI();
        String method = request.getMethod();
        int status = response.getStatus();

        if (ex != null) {
            log.error("请求异常: {} {}, 耗时: {}ms, 状态: {}, 异常: {}",
                method, uri, duration, status, ex.getMessage());
        } else {
            log.info("请求完成: {} {}, 耗时: {}ms, 状态: {}",
                method, uri, duration, status);
        }
    }
}

获取处理器信息

Java
@Override
public void afterCompletion(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler,
                            Exception ex) {
    if (handler instanceof HandlerMethod) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;

        // 获取Controller类名和方法名
        String className = handlerMethod.getBeanType().getSimpleName();
        String methodName = handlerMethod.getMethod().getName();

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

        log.info("处理器: {}.{}", className, methodName);
    }
}

异常处理场景

Java
@Override
public void afterCompletion(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler,
                            Exception ex) {
    // 正常执行完成
    if (ex == null) {
        log.info("请求正常完成: {}", request.getRequestURI());
        return;
    }

    // 异常处理
    if (ex instanceof BusinessException) {
        BusinessException be = (BusinessException) ex;
        log.warn("业务异常: code={}, message={}", be.getCode(), be.getMessage());
    } else if (ex instanceof IllegalArgumentException) {
        log.warn("参数异常: {}", ex.getMessage());
    } else {
        log.error("系统异常: ", ex);
    }
}

资源清理

Java
@Component
public class ResourceCleanupInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler) {
        // 在请求开始时创建资源
        request.setAttribute("dbContext", new DbContext());
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) {
        // 请求结束后清理资源
        DbContext dbContext = (DbContext) request.getAttribute("dbContext");
        if (dbContext != null) {
            dbContext.close();
            request.removeAttribute("dbContext");
        }

        // 清理ThreadLocal
        UserContext.clear();
        TraceContext.clear();
    }
}

性能监控统计

Java
@Component
public class PerformanceInterceptor implements HandlerInterceptor {

    private final MeterRegistry meterRegistry;

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

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) {
        long startTime = (long) request.getAttribute("startTime");
        long duration = System.nanoTime() - startTime;

        String uri = request.getRequestURI();
        String method = request.getMethod();
        int status = response.getStatus();

        // 记录到监控系统
        Timer.builder("http.request.duration")
            .tag("uri", uri)
            .tag("method", method)
            .tag("status", String.valueOf(status))
            .tag("success", ex == null ? "true" : "false")
            .register(meterRegistry)
            .record(duration, TimeUnit.NANOSECONDS);
    }
}

多拦截器执行顺序

当配置多个拦截器时,afterCompletion执行顺序与preHandle相反:

text
// preHandle执行顺序: Interceptor1 → Interceptor2 → Interceptor3
// afterCompletion执行顺序: Interceptor3 → Interceptor2 → Interceptor1
方法执行顺序
preHandle顺序执行
postHandle逆序执行
afterCompletion逆序执行

afterCompletion只在preHandle返回true的拦截器上执行。

要点总结

  • afterCompletion在视图渲染完成后执行
  • 无论Controller是否抛出异常都会执行
  • ex参数携带处理过程中的异常信息
  • 适合资源清理、日志记录、性能统计等场景
  • 执行顺序与preHandle相反

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

← 上一篇 Spring MVC 返回JSON格式错误信息
下一篇 → Spring MVC postHandle方法详解
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

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

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