怎么做网站的软文推广,网站建设运营的成本,青岛外贸网站制作,四会建设局网站问题描述
想在postHandle方法里执行addHeader方法来补充一些Header信息#xff08;如分页信息#xff09;#xff0c;但是最后执行却未如期显示
拦截器源码
import com.zhangziwa.practisesvr.utils.response.ResponseContext;
import jakarta.servlet.http.HttpServletR…问题描述
想在postHandle方法里执行addHeader方法来补充一些Header信息如分页信息但是最后执行却未如期显示
拦截器源码
import com.zhangziwa.practisesvr.utils.response.ResponseContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;Component
public class ResponsePostInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true;}Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {# 想在postHandle方法里执行addHeader方法来补充一些Header信息HttpHeaders headers ResponseContext.getHeaders();if (headers ! null) {headers.forEach((key, values) - values.forEach((value) - {if (!response.getHeaderNames().contains(key)) {response.addHeader(key, value);}}));}if (ResponseContext.getResponseCode() ! null) {response.setStatus(ResponseContext.getResponseCode().value());}}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {ResponseContext.clear();}
}Controller 构造初始的HttpHeaders RequestMapping(value /getAllStudents4, method RequestMethod.GET)public ResponseEntityListStudent getAllStudents4() {System.err.println(***Controller.getAllStudents4***);ListStudent students userService.listStudents3(1, 5);HttpHeaders httpHeaders new HttpHeaders();httpHeaders.add(test, test);return ResponseEntity.ok().headers(httpHeaders).contentType(MediaType.APPLICATION_JSON).body(students);}postHandle 补充HttpHeaders的代码正常执行 执行结果却没有补充的HttpHeaders 原因分析 [Ref] springboot设置返回的response中的header解决办法
解决方案
方案1postHandle追加HttpHeaders的逻辑前移到preHandle方法 Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.err.println(***ResponsePostInterceptor.preHandle***);response.addHeader(test1, test1);return true;}验证可行 弊端 preHandle执行时机是在进入Controller层之前如果要追加的HttpHeaders是在Controller层里计算得到的则此方案完全用不上
方案2使用ResponseBodyAdvice ControllerAdvice
Further Reading ControllerAdvice
源码HandlerInterceptor 去除补充HttpHeaders逻辑
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;Component
public class ResponsePostInterceptor implements HandlerInterceptor {//在Controller执行之前调用如果返回falsecontroller不执行Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.err.println(***ResponsePostInterceptor.preHandle***);return true;}//controller执行之后且页面渲染之前调用Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.err.println(***ResponsePostInterceptor.postHandle***);}//页面渲染之后调用一般用于资源清理操作Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.err.println(***ResponsePostInterceptor.afterCompletion***);ResponseContext.clear();}
}源码ResponseBodyAdvice 补充HttpHeaders逻辑
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;import static java.util.Objects.nonNull;ControllerAdvice
public class ResponsePostAdvice implements ResponseBodyAdvice {Overridepublic boolean supports(MethodParameter returnType, Class converterType) {System.err.println(***ResponsePostAdvice.supports***);return true;}Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class clazz, ServerHttpRequest request, ServerHttpResponse response) {System.err.println(***ResponsePostAdvice.beforeBodyWrite***);HttpHeaders headers response.getHeaders();// 分页信息添加到ServerHttpResponseHttpHeaders headersContext ResponseContext.getHeaders();// 实现方式1: 一次性梭哈 重复项新值覆盖旧值
// if (nonNull(headersContext) !headersContext.isEmpty()) {
// headers.addAll(headersContext);
// }// 实现方式1: 逐个补充 重复项不添加if (nonNull(headersContext) !headersContext.isEmpty()) {headersContext.forEach((key, values) - values.forEach((value) - {headers.addIfAbsent(key, value);}));}// 状态码添加到ServerHttpResponseif (nonNull(ResponseContext.getResponseCode())) {response.setStatusCode(ResponseContext.getResponseCode());}return body;}
}验证好用 补充执行顺序为 ResponseBodyAdvice → HandlerInterceptor
***ResponsePostInterceptor.preHandle***
***Controller.getAllStudents4***
***ResponsePostAdvice.supports***
***ResponsePostAdvice.beforeBodyWrite***
***ResponsePostInterceptor.postHandle***
***ResponsePostInterceptor.afterCompletion***