背景
对接一个关联方系统,我这边需要提供几个接口。对方要求,这些接口有统一的响应格式,并且有统一的响应头。统一的响应头包含如下:
{
"TT-Encrypt":"noaction",
"Content-Encoding":"gzip",
"Request-Trace":"1111rrr454f45f",
"Date":"Thu, 09 Apr 2021 01:52:28 GMT"
}
统一响应头设置
嗯,需求合理,实现也简单:
filter方式
实现OncePerRequestFilter
,然后在doFilterInternal
中设置响应头:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
response.setHeader("TT-Encrypt", "noaction");
response.setHeader("Request-Trace", "xxxxxxx");
response.setHeader("Content-Encoding", "gzip");
response.setHeader("Date", new Date().toString());
filterChain.doFilter(request, response);
}
注意:这里一定要遭doFilter之前设置,因为在doFilter之后,response的状态已经是committed=true,如果是在doFilter之后设置,结果会正常返回,但是没有设置的header。
使用过滤器:
@Configuration
public class NbWebMvcConfigurer extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册自定义的拦截器
registry.addInterceptor(new HeaderInterceptor());
}
}
public class HeaderInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 设置Header的响应信息
response.addHeader("TT-Encrypt", "noaction");
response.addHeader("Content-Encoding", "gzip");
response.addHeader("Request-Trace", NbCheckListContextHelper.getTraceId());
response.addHeader("Date", new Date().toString());
return true;
}
}
注意:在HeaderInterceptor中,一定是preHandle方法中设置,否则也不会生效。同Filter一样的原因。
其他方式
当然也可以使用其他的方式,例如在@RestControllerAdvice
中设置也是可以的。但是从代码的设计上来看,不妥!
接口无响应?
其实如果完全按照上述方式进行操作,调用该接口的时候,我们后端不会有问题,但是前端得不到response,提示的错误为:Error: incorrect header check!
遇到这种情况,首先要明确,按照这种方式设置response的header是肯定可以的。之所以出现这个问题,主要是因为设置的header参数有问题。这里的问题是:response.addHeader("Content-Encoding", "gzip");
在springboot中,开启gzip压缩可以使用配置:这样,响应头中就可以自动添加上response.addHeader("Content-Encoding", "gzip");
。
server.compression.enabled=true
server.compression.mime-types=application/json