Feign实现GZIP压缩

Feign使用GZIP提高通信效率

 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//响应解码

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;
        }
    }
}
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当使用Feign进行网络请求时,如果请求中包含Gzip压缩的数据,有时会出现错误。 Feign是一个基于Java的HTTP客户端,用于简化和组织HTTP API的调用。它通过使用注解和接口定义来定义和配置请求,从而使得发起HTTP请求变得更加简单。 当使用Gzip压缩数据时,服务器可能会返回带有Gzip压缩的响应。由于Feign默认情况下并不支持Gzip响应的解压缩,因此当收到这样的响应时就会出现错误。 解决这个问题的方法是在Feign的配置中启用Gzip压缩。可以通过在Feign客户端的构建器中添加相应的配置来实现。以下是一种可能的解决方法: ```java import feign.Client; import feign.Feign; import feign.Request; import feign.codec.Decoder; import feign.codec.Encoder; import feign.okhttp.OkHttpClient; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; import okhttp3.internal.http.RealResponseBody; import okio.*; import java.io.IOException; import java.util.zip.GZIPInputStream; public class FeignGzipExample { public interface ApiService { // 定义API请求方法 } public static void main(String[] args) { // 创建自定义的HTTP Client OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new GzipRequestInterceptor()) .addInterceptor(new GzipResponseInterceptor()) .build(); // 使用自定义的Client创建Feign客户端 ApiService apiService = Feign.builder() .client(new feign.okhttp.OkHttpClient(client)) .build() .target(ApiService.class, "http://example.com"); // 发起请求 // apiService.someMethod(); } static class GzipRequestInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { // 请求前处理Gzip压缩 Request originalRequest = chain.request(); Request compressedRequest = originalRequest.newBuilder() .header("Accept-Encoding", "gzip") .build(); return chain.proceed(compressedRequest); } } static class GzipResponseInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { // 响应后处理Gzip压缩 Response response = chain.proceed(chain.request()); if ("gzip".equalsIgnoreCase(response.header("Content-Encoding"))) { ResponseBody responseBody = response.body(); if (responseBody != null) { BufferedSource source = Okio.buffer(Okio.source(responseBody.byteStream())); GZIPInputStream gzipInputStream = new GZIPInputStream(source.inputStream()); String responseBodyString = new String(source.readByteArray()); response = response.newBuilder() .body(ResponseBody.create(MediaType.parse(responseBody.contentType().toString()), responseBodyString)) .build(); } } return response; } } } ``` 以上代码中,我们自定义了一个OkHttpClient,并分别实现GzipRequestInterceptor和GzipResponseInterceptor两个拦截器来处理Gzip压缩和解压缩。然后在Feign客户端的构建中,使用这个自定义的OkHttpClient。 这样,当使用Feign进行请求时,如果响应中包含Gzip压缩的数据,将会被正确地解压缩,避免报错。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值