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

Spring MVC postHandle方法详解

postHandle是HandlerInterceptor接口的第二个方法,在Controller执行后、视图渲染前调用,用于修改响应数据。

方法签名

Java
void postHandle(HttpServletRequest request,
                HttpServletResponse response,
                Object handler,
                ModelAndView modelAndView) throws Exception;

执行时机

Java
preHandle() → Controller处理 → postHandle() → 视图渲染 → afterCompletion()

Controller抛出异常时postHandle不执行。

参数详解

参数类型说明
requestHttpServletRequest当前HTTP请求对象
responseHttpServletResponse当前HTTP响应对象
handlerObject处理器对象(HandlerMethod)
modelAndViewModelAndViewController返回的视图模型对象

modelAndView参数

场景modelAndView值
传统Controller返回视图ModelAndView对象
REST Controller返回JSONnull
Controller返回String视图名ModelAndView包含viewName

基本实现

Java
@Override
public void postHandle(HttpServletRequest request,
                       HttpServletResponse response,
                       Object handler,
                       ModelAndView modelAndView) throws Exception {
    // 记录处理完成
    log.info("Controller处理完成: {}", request.getRequestURI());
}

添加公共数据

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

        // 添加用户信息
        User user = UserContext.getUser();
        if (user != null) {
            modelAndView.addObject("currentUser", user);
        }
    }
}

修改视图数据

Java
@Override
public void postHandle(HttpServletRequest request,
                       HttpServletResponse response,
                       Object handler,
                       ModelAndView modelAndView) throws Exception {
    if (modelAndView != null) {
        Map<String, Object> model = modelAndView.getModel();

        // 统一处理日期格式
        Object createTime = model.get("createTime");
        if (createTime instanceof Date) {
            model.put("createTimeStr",
                formatDate((Date) createTime, "yyyy-MM-dd HH:mm:ss"));
        }

        // 添加处理时间统计
        Long startTime = (Long) request.getAttribute("startTime");
        long duration = System.currentTimeMillis() - startTime;
        modelAndView.addObject("processTime", duration);
    }
}

修改响应头

Java
@Override
public void postHandle(HttpServletRequest request,
                       HttpServletResponse response,
                       Object handler,
                       ModelAndView modelAndView) throws Exception {
    Long startTime = (Long) request.getAttribute("startTime");
    long duration = System.currentTimeMillis() - startTime;

    response.setHeader("X-Response-Time", String.valueOf(duration));
    response.setHeader("X-Request-Id", (String) request.getAttribute("requestId"));
}

REST接口处理

Java
@Override
public void postHandle(HttpServletRequest request,
                       HttpServletResponse response,
                       Object handler,
                       ModelAndView modelAndView) throws Exception {
    // REST接口modelAndView为null
    if (modelAndView == null) {
        // 计算处理时间
        Long startTime = (Long) request.getAttribute("startTime");
        long duration = System.currentTimeMillis() - startTime;

        // 设置响应头
        response.setHeader("X-Process-Time", String.valueOf(duration));

        log.info("REST响应: {} {} 耗时:{}ms",
            request.getMethod(), request.getRequestURI(), duration);
        return;
    }

    // 传统视图处理
    modelAndView.addObject("processTime", duration);
}

统一响应封装

Java
@Component
public class ResponseWrapperInterceptor implements HandlerInterceptor {

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView modelAndView) throws Exception {
        // 只处理传统Controller
        if (modelAndView != null) {
            Object result = modelAndView.getModel().get("result");
            if (result != null && !(result instanceof ApiResult)) {
                // 包装为统一响应格式
                ApiResult<Object> apiResult = ApiResult.success(result);
                modelAndView.addObject("result", apiResult);
            }
        }
    }
}

国际化处理

Java
@Override
public void postHandle(HttpServletRequest request,
                       HttpServletResponse response,
                       Object handler,
                       ModelAndView modelAndView) throws Exception {
    if (modelAndView != null) {
        Locale locale = LocaleContextHolder.getLocale();

        // 根据语言设置不同的提示信息
        String message = messageSource.getMessage("welcome.message", null, locale);
        modelAndView.addObject("welcomeMessage", message);
    }
}

执行顺序

多拦截器时postHandle逆序执行:

Java
// 注册顺序:A → B → C
// postHandle执行顺序:C → B → A
Java
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(interceptorA)
        .addPathPatterns("/**")
        .order(1);

    registry.addInterceptor(interceptorB)
        .addPathPatterns("/**")
        .order(2);
}

// postHandle执行:B.postHandle → A.postHandle

不执行的场景

场景postHandle是否执行
Controller正常返回✅ 执行
Controller抛出异常❌ 不执行
preHandle返回false❌ 不执行
异步请求❌ 不执行

异步请求处理

text
@Component
public class AsyncInterceptor implements AsyncHandlerInterceptor {

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView modelAndView) throws Exception {
        // 同步请求的postHandle
        log.info("同步请求postHandle");
    }

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request,
                                               HttpServletResponse response,
                                               Object handler) throws Exception {
        // 异步请求开始时的回调
        log.info("异步请求开始");
    }
}

典型应用总结

应用场景说明
添加公共数据为所有视图添加公共属性
统计处理时间计算Controller执行耗时
修改响应头添加自定义响应头
国际化处理根据Locale添加消息
响应格式封装统一包装响应数据

要点总结

  • postHandle在Controller执行后、视图渲染前调用
  • Controller异常时postHandle不执行
  • modelAndView为null表示REST接口返回JSON
  • 多拦截器时postHandle逆序执行
  • 适合添加公共数据、修改响应头等场景
  • 异步请求不执行postHandle

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

← 上一篇 Spring MVC afterCompletion方法详解
下一篇 → Spring MVC preHandle方法详解
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

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

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