Spring Boot 1.5.9中禁用@RestController的Transfer-Encoding,自动加Content-Length
全局禁用分块编码并自动添加Content-Length的解决方案(Spring Boot 1.5.9.RELEASE)
我来帮你搞定这个问题——不用逐个修改控制器端点为ResponseEntity,就能全局禁用分块编码,让响应自动带上Content-Length头,这里有两个实用的通用方案:
方案一:通过Tomcat容器配置强制关闭分块编码
Spring Boot 1.5.x默认用Tomcat当嵌入式容器,我们可以自定义Tomcat容器工厂,修改Connector参数来强制禁用分块传输:
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatConfig { @Bean public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() { TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(); factory.addConnectorCustomizers(connector -> { // 开启这个配置后,Tomcat会自动计算响应体长度并添加Content-Length,同时禁用分块 connector.setProperty("disableChunking", "true"); }); return factory; } }
这个配置对所有端点生效,只要你的响应体(比如JSON)能被提前计算长度,Tomcat就会自动帮你处理好Content-Length头,再也不会返回Transfer-Encoding: chunked了。
方案二:自定义ResponseBodyAdvice统一处理响应
如果你的应用以后可能切换容器(比如从Tomcat换成Jetty),或者需要更灵活的控制逻辑,可以用ResponseBodyAdvice拦截所有@ResponseBody的响应,手动处理长度和分块:
import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @ControllerAdvice public class DisableChunkingAdvice implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { // 对所有@ResponseBody的接口生效,也可以在这里过滤特定的控制器或方法 return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (response instanceof ServletServerHttpResponse) { HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse(); // 设置足够大的缓冲区,确保响应体能被完整缓存,避免分块 servletResponse.setBufferSize(1024 * 1024); // 清空分块编码的响应头 servletResponse.setHeader("Transfer-Encoding", ""); try { // 把响应体转换成字节数组,计算长度 ByteArrayOutputStream baos = new ByteArrayOutputStream(); HttpMessageConverter<Object> converter = selectedConverterType.newInstance(); converter.write(body, selectedContentType, new ServerHttpResponse() { @Override public OutputStream getBody() throws IOException { return baos; } @Override public HttpHeaders getHeaders() { return new HttpHeaders(); } }); byte[] bodyBytes = baos.toByteArray(); // 设置Content-Length头 servletResponse.setContentLength(bodyBytes.length); // 返回字节数组,让容器直接输出 return bodyBytes; } catch (Exception e) { // 万一出问题,就 fallback 到默认处理逻辑 return body; } } return body; } }
一些注意点
- 方案一只对Tomcat生效,如果用Jetty或Undertow,得对应调整容器配置。比如Jetty可以在
HttpConfiguration里设置setSendContentLength(true)并禁用分块。 - 如果你的接口有流式响应(比如返回InputStream),分块编码是必须的,这种情况可以在
supports方法里排除这些接口。 - 这两个方案都适配Spring Boot 1.5.9.RELEASE的稳定API,不用担心兼容性问题。
内容的提问来源于stack exchange,提问作者Raashith
相关产品推荐
相关产品推荐

