Spring Cloud Feign 支持对请求和响应进行GZIP压缩,以提高通信效率。
fegin默认的Client对响应流不支持对gzip后的字节流进行解析,所以在序列化成对象时会存在解析问题。我们可以使用过滤器实现。开始实现。
1.依赖引入,pom文件添加feign-httpclient,将feign的http组件改为OkHttp
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>10.7.4</version>
</dependency>
2.在application.properties中进行配置
ribbon.httpclient.enabled=false
ribbon.okhttp.enabled=true
feign.httpclient.enabled=false
feign.okhttp.enabled=true//(使用okhttp)
feign.compression.request.enabled=true//开启请求压缩
feign.compression.request.min-request-size=1024//设置请求大小,1024kb以上开始压缩
feign.compression.response.enabled=true//响应压缩
feign.compression.response.useGzipDecoder=true//响应解码
在nacos里面配置:
ribbon:
httpclient:
enabled: false
okhttp:
enabled: true
feign:
httpclient:
enabled: false
okhttp:
#使用okhttp
enabled: true
compression:
request:
#开启请求压缩
enabled: true
#设置请求大小,1024kb以上开始压缩
min-request-size: 1024
response:
#响应压缩
enabled: true
#响应解码
useGzipDecoder: true
3.配置启动类
@SpringCloudApplication
//启用Fegin注解
@EnableFeignClients
//启用过滤器,下面使用当前过滤器所在包名
@ServletComponentScan(basePackages = {"com.filter"})
public class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
application.run(args);
}
}
4.配置过滤器
@WebFilter(filterName="GzipFilter",urlPatterns="/*")
@Slf4j
public class GzipFilter implements Filter {
@Override
public void doFilter(
ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain
) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String contentEncoding = request.getHeader("Content-Encoding");
// 如果对内容进行了压缩,则解压
if (null != contentEncoding && contentEncoding.contains("gzip")){
request=new GzipRequestWrapper(request);
}
filterChain.doFilter(request,servletResponse);
}
public class GzipRequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
public GzipRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public ServletInputStream getInputStream() throws IOException {
ServletInputStream stream = request.getInputStream();
try {
final GZIPInputStream gzipInputStream = new GZIPInputStream(stream);
ServletInputStream newStream = new ServletInputStream() {
@Override
public int read() throws IOException {
return gzipInputStream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener arg0) {
// TODO Auto-generated method stub
}
};
return newStream;
} catch (Exception e) {
log.debug("ungzip content fail.", e);
}
return stream;
}
}
}