我提出了两种解决方案,一种更简单,无需流传输,另一种支持流传输。
如果您 不需要流式传输 ,请使用custom
ClientHttpRequestInterceptor,一个Spring功能。
RestTemplate rt = new RestTemplate();rt.setInterceptors(Collections.singletonList(interceptor));
interceptor可能在哪里:
ClientHttpRequestInterceptor interceptor = new ClientHttpRequestInterceptor() { @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { request.getHeaders().add("Content-Encoding", "gzip"); byte[] gzipped = getGzip(body); return execution.execute(request, gzipped); } }getGzip我复制了
private byte[] getGzip(byte[] body) throws IOException { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); try { GZIPOutputStream zipStream = new GZIPOutputStream(byteStream); try { zipStream.write(body); } finally { zipStream.close(); } } finally { byteStream.close(); } byte[] compressedData = byteStream.toByteArray(); return compressedData; }配置拦截器后,所有请求将被压缩。
这种方法的缺点是它不支持流式传输,因为
ClientHttpRequestInterceptor将内容作为
byte[]
如果您 需要流式传输,请 创建一个custom
ClientHttpRequestFactory,说出来
GZipClientHttpRequestFactory,然后像这样使用它:
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setBufferRequestBody(false); ClientHttpRequestFactory gzipRequestFactory = new GZipClientHttpRequestFactory(requestFactory); RestTemplate rt = new RestTemplate(gzipRequestFactory);
哪里
GZipClientHttpRequestFactory是:
public class GZipClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper { public GZipClientHttpRequestFactory(ClientHttpRequestFactory requestFactory) { super(requestFactory); } @Override protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) throws IOException { ClientHttpRequest delegate = requestFactory.createRequest(uri, httpMethod); return new ZippedClientHttpRequest(delegate); }}并且
ZippedClientHttpRequest是:
public class ZippedClientHttpRequest extends WrapperClientHttpRequest{ private GZIPOutputStream zip; public ZippedClientHttpRequest(ClientHttpRequest delegate) { super(delegate); delegate.getHeaders().add("Content-Encoding", "gzip"); // here or in getBody could add content-length to avoid chunking // but is it available ? // delegate.getHeaders().add("Content-Length", "39"); } @Override public OutputStream getBody() throws IOException { final OutputStream body = super.getBody(); zip = new GZIPOutputStream(body); return zip; } @Override public ClientHttpResponse execute() throws IOException { if (zip!=null) zip.close(); return super.execute(); }}最后
WrapperClientHttpRequest是:
public class WrapperClientHttpRequest implements ClientHttpRequest { private final ClientHttpRequest delegate; protected WrapperClientHttpRequest(ClientHttpRequest delegate) { super(); if (delegate==null) throw new IllegalArgumentException("null delegate"); this.delegate = delegate; } protected final ClientHttpRequest getDelegate() { return delegate; } @Override public OutputStream getBody() throws IOException { return delegate.getBody(); } @Override public HttpHeaders getHeaders() { return delegate.getHeaders(); } @Override public URI getURI() { return delegate.getURI(); } @Override public HttpMethod getMethod() { return delegate.getMethod(); } @Override public ClientHttpResponse execute() throws IOException { return delegate.execute(); }}这种方法使用分块传输编码创建请求,如果知道大小,则可以设置内容长度标头来更改此请求。
ClientHttpRequestInterceptor和/或自定义
ClientHttpRequestFactory方法的优点是它可以与RestTemplate的任何方法一起使用。另一种方法,传递一个RequestCallback能够仅与
execute方法,这是因为RestTemplate的其它方法在内部创建他们自己的RequestCallback(S)产生的内容。



