spring-cloud-feign实战笔记

feign 配置

  1. 针对单个feign接口进行配置
    feign:
      client:
        config:
          # feignName 注意这里与contextId一致,不能写成name(FeignClientFactoryBean#configureFeign)
          # 不能写成 client-b (微服务名称),否则不生效
          helloFeignClient: # contextId
            connectTimeout: 50000 # 连接超时时间
            readTimeout: 50000 # 读超时时间
            loggerLevel: full #配置Feign的日志级别
          #default:
            # 其他默认配置
    
  2. feign 全局默认配置
    feign:
      client:
        config:
          default:
            connectTimeout: 50000 # 连接超时时间
            readTimeout: 50000 # 读超时时间
            loggerLevel: full #配置Feign的日志级别
    
  3. feign开启gzip支持
    feign:
      compression:
        request:
          enabled: true
          mime-types: "text/xml, application/xml, application/json"
          min-request-size: 2048
        response:
          enabled: true # 配置相应GZIP压缩
    

开启gzip支持后接口调用处理(方式一)

  1. feign接口使用ResponseEntity<byte []>接收数据
    @FeignClient(contextId = "testFeignClient", name = "client-a")
    public interface TestFeignClient {
        @GetMapping(value = "/userInfo")
        ResponseEntity<byte []> userInfoCompress(
                @RequestParam("username") String username, @RequestParam("address") String address) ;
    }
    
  2. 编写单元测试(注意需要对byte[] 数组使用Gzip解压)
    @Slf4j
    public class TestFeignClientTest extends BaseJunitTest {
        @Autowired
        private TestFeignClient testFeignClient ;
        @Test
        public void userInfoCompress() throws IOException {
            String username = "张三" ;
            String address = "北京" ;
            ResponseEntity<byte[]> responseEntity = testFeignClient.userInfoCompress(username, address);
            byte[] compressed = responseEntity.getBody();
            String decompressValue = GzipUtils.decompress(compressed);
            log.info("value : {}", decompressValue);
        }
    }
    
  3. 编写gzip解压缩工具类
    public final class GzipUtils {
        public static String decompress(byte [] compressed) throws IOException {
            final StringBuilder output = new StringBuilder() ;
            try(GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(compressed));
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gis, StandardCharsets.UTF_8))){
                String line ;
                while ((line = bufferedReader.readLine()) != null){
                    output.append(line) ;
                }
                return output.toString() ;
            }
        }
    }
    

开启gzip支持后接口调用处理(方式二)

  1. 编写Decoder (内部使用方式一的Gzip解压缩工具类GzipUtils)
    public class FeignResponseDecoder implements Decoder {
        private final Decoder delegate;
        public FeignResponseDecoder(Decoder delegate) {
            Objects.requireNonNull(delegate, "Decoder must not be null. ");
            this.delegate = delegate;
        }
        @Override
        public Object decode(Response response, Type type) throws IOException {
            Collection<String> values = response.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER);
            if (Objects.nonNull(values) && !values.isEmpty() && values.contains(HttpEncoding.GZIP_ENCODING)) {
                byte[] compressed = Util.toByteArray(response.body().asInputStream());
                if ((compressed == null) || (compressed.length == 0)) {
                    return delegate.decode(response, type);
                }
                //decompression part
                //after decompress we are delegating the decompressed response to default
                //decoder
                if (isCompressed(compressed)) {
                    String decompressValue = GzipUtils.decompress(compressed);
                    Response decompressedResponse = response.toBuilder().body(decompressValue.getBytes()).build();
                    return delegate.decode(decompressedResponse, type);
                } else {
                    return delegate.decode(response, type);
                }
            } else {
                return delegate.decode(response, type);
            }
        }
        private static boolean isCompressed(final byte[] compressed) {
            return (compressed[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (compressed[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8));
        }
    }
    
  2. 将Decoder加入到Spring容器管理
    @Configuration
    public class AppConfig{
       @Bean
       public Decoder GZIPResponseDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
          Decoder decoder = new FeignResponseDecoder(new SpringDecoder(messageConverters));
          return decoder;
       }
    }
    
  3. feign接口使用普通java对象接收数据
    @FeignClient(contextId = "testFeignClient", name = "client-a")
    public interface TestFeignClient {
        @GetMapping("/userInfo")
        UserInfoVO userInfo(@RequestParam("username") String username, @RequestParam("address") String address) ;
    }
    
  4. 编写单元测试
    @Slf4j
    public class TestFeignClientTest extends BaseJunitTest {
        @Autowired
        private TestFeignClient testFeignClient ;
        
        @Test
        public void userInfo(){
            String username = "张三" ;
            String address = "北京" ;
            UserInfoVO userInfo = testFeignClient.userInfo(username, address);
            log.info("user info : {}", userInfo);
        }
    }
    

其他知识点补充

  1. SpringBoot服务提供者开启gizp压缩
    server:
      port: 7070
      compression:
        enabled: true
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/5123.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

今年面试好激烈!

金三银四过去一半&#xff0c;市场火热&#xff0c;但是大家就业压力却没有缓解多少。 很多粉丝后台留言&#xff0c;Java程序员面临的竞争太激烈了…… 我自己也有实感&#xff0c;多年身处一线互联网公司&#xff0c;虽没有直面过求职跳槽的残酷&#xff0c;但经常担任技术面…

记一次Git未Commit直接Pull导致本地代码丢失后的挽救过程

第一次遇到这种问题&#xff0c;有点紧张... 好吧&#xff0c;废话不多说&#xff0c;IDEA或者AndroidStudio进入Git Uncommiteed Changes -> Unstash Changes&#xff1a; 在弹出的Unstash Changes对话框点View查看代码&#xff0c;如果代码是本地丢失的代码&#xff0c;那…

MySQL——distinct与group by去重 / 松散索引扫描紧凑索引扫描

本篇介绍MySQL中的 distinct 和 group by的区别&#xff0c;包括用法、效率&#xff0c;涉及松散索引扫描和紧凑索引扫描的概念&#xff1b;distinct用法示例&#xff1a;SELECT DISTINCT columns FROM table_name WHERE where_conditions;DISTINCT关键词修饰查询的列&#xff…

CVE-2023-28708 原理剖析

CVE-2023-28708 原理剖析这应该不是一个严重的漏洞&#xff0c;可能评分只能为低&#xff0c;因为并没有什么卵用。 话不多说&#xff0c;直接进入正题 我的复现环境&#xff1a; tomcat-8.5.50 首先我们得简单写一个servlet&#xff0c;当然不写也没事&#xff0c;因为我们的…

【C语言学习】结构体

结构体&#xff08;Struct&#xff09;从本质上讲是一种自定义的数据类型&#xff0c;只不过这种数据类型比较复杂&#xff0c;是由 int、char、float 等基本类型组成的。你可以认为结构体是一种聚合类型。 在实际开发中&#xff0c;我们可以将一组类型不同的、但是用来描述同…

[技术经理]02 什么是技术经理?

目录01什么是技术经理02总结01什么是技术经理 什么是技术经理&#xff1f; 我用一句话概括为&#xff1a;专业技术团队的管理者。 技术经理&#xff0c;是一种管理职位&#xff0c;通常是在软件开发、互联网等科技公司或技术团队中担任。 技术经理的职责&#xff0c;**是管理…

Docker入门

文章目录Docker为什么出现Docker能干嘛学习途径Docker安装Docker的基本组成环境说明安装步骤阿里云镜像加速底层原理Docker为什么出现 一款产品从开发到上线&#xff0c;从操作系统&#xff0c;到运行环境&#xff0c;再到应用配置。作为开发运维之间的协作我们需要 关心很多东…

文献阅读(247)AIpa

题目&#xff1a;Alpa: Automating Inter- and Intra-Operator Parallelism for Distributed Deep Learning时间&#xff1a;2022会议&#xff1a;OSDI研究机构&#xff1a;UCB 传统的DNN并行策略&#xff1a; 现有的分布式训练系统要么需要用户手动创建并行化计划&#xff0c…

测试笔记:接口测试

目录1.接口&#xff08;1&#xff09;接口概念&#xff08;2&#xff09;接口类型2、接口风格&#xff08;1&#xff09;传统风格&#xff08;2&#xff09;RESTful风格接口3、接口测试&#xff08;1&#xff09;接口测试是什么&#xff08;2&#xff09;接口测试原理&#xff…

Node.js学习笔记——fs模块

fs全称为file system&#xff0c;称之为文件系统&#xff0c;是Node.js中的内置模块&#xff0c;可以对计算机中的磁盘进行操作。 本章节会介绍如下操作&#xff1a; 文件写入文件读取文件移动与重命名文件删除文件夹操作查看资源状态 一、文件写入 文件写入就是将数据保存…

利用nginx实现动静分离的负载均衡集群实战

前言 大家好&#xff0c;我是沐风晓月&#xff0c;今天我们利用nginx来作为负载&#xff0c;实现两台apache服务器的动静分离集群实战&#xff1b; 本文收录于沐风晓月的专栏《linux基本功-系统服务实战》&#xff0c;更多内容可以关注我的博客&#xff1a; https://blog.csd…

Visual Studio 2015 + cmake编译QT5程序

概述 由于QT的集成开发环境QTCreate&#xff0c;在代码调试功能上远不及Visual Studio方便&#xff0c;因此&#xff0c;在Windows平台&#xff0c;可以使用Visual Studio来开发调试QT程序&#xff0c;本文章就主要介绍下&#xff0c;如何使用CMAKE编译QT5程序&#xff0c;并使…

【JAVA真的没出路了吗?】

2023年了&#xff0c;转行IT学习Java是不是已经听过看过很多次了。随之而来的类似学Java没出路、Java不行了、对Java感到绝望等等一系列的制造焦虑的话题也在网上层出不穷&#xff0c;席卷了一大片的对行业不了解的吃瓜群众或是正在学习中的人。如果是行外人真的会被这种言论轻…

【教程】使用ChatGPT制作基于Tkinter的桌面时钟

目录 描述 代码 效果 说明 下载 描述 给ChatGPT的描述内容&#xff1a; python在桌面上显示动态的文字&#xff0c;不要显示窗口边框。窗口背景和标签背景都是透明的&#xff0c;但标签内的文字是有颜色。使用tkinter库实现&#xff0c;并以class的形式书写&#xff0c;方…

GPS时间序列分析---剔除跳跃点,拟合时间序列

通常利用GPS时间序列进行数据分析时&#xff0c;会遇到大地震的发生&#xff0c;这个时候会导致GPS的观测结果出现很大的跳跃值&#xff0c;这对后续的数据处理和分析带来了困难。这里分享一个最近了解的&#xff0c;可以用于处理这一问题的工具包---TSAnalyzer。下面主要介绍该…

Adobe:当创意工作遇上生成式AI

放眼全球IT行业&#xff0c;当前最炙手可热的领域是什么&#xff1f;答案显然只有一个&#xff1a;因为ChatGPT而火爆全球的生成式AI&#xff08;Artificial Intelligence Generated Content&#xff0c;简称AIGC&#xff09;&#xff0c;又称人工智能生成内容。那么当创意设计…

再学一下Feign的原理

简介 Feign是Spring Cloud Netflix组件中的一个轻量级Restful的HTTP服务客户端&#xff0c;它简化了服务间调用的方式。 Feign是一个声明式的web service客户端.它的出现使开发web service客户端变得更简单.使用Feign只需要创建一个接口加上对应的注解, 比如FeignClient注解。…

Go分布式爬虫学习笔记(十四)

文章目录14_context为什么需要Context?级联退出Context 的使用方法。context.ValuecontextContext 最佳实践Context 底层原理14_context Never start a goroutine without knowing how it will stop。 如果你不知道协程如何退出&#xff0c;就不要使用它。 为什么需要Context?…

家政服务系统APP小程序需具备哪些功能?

由于工作忙碌或者是懒人经济作祟&#xff0c;现代人对于家政服务的需求直线上升。而且互联网技术深入生活的方方面面&#xff0c;让上门家政服务系统开发成为很多线下家政公司转型互联网的方式&#xff0c;那么开发一款家政服务系统APP小程序需具备哪些功能呢&#xff1f; …

逻辑回归 算法推导与基于Python的实现详解

文章目录1 逻辑回归概述2 逻辑回归公式推导与求解2.1 公式推导2.2公式求解3 基于Python的实现3.1可接收参数3.2 完整代码示例1 逻辑回归概述 逻辑回归&#xff08;Logistic Regression&#xff09;是一种用于分类问题的统计学习方法。它基于线性回归的原理&#xff0c;通过将线…