互联网大厂技术-HTTP请求-Springboot整合Feign更优雅地实现Http服务调用

news2024/9/20 22:33:57

目录

一、SpringBoot快速整合Feign

1.添加Pom依赖

2.启动类添加注解

3.引用Feign服务

二、为请求添加Header的3种方式

1.添加固定header

2.通过接口签名添加header

3.动态添加header

三、为请求添加超时配置

1.默认超时时间

3.超时异常

4.全局超时配置

5.为单个服务设置超时配置

四、为请求配置客户端负载均衡模式

五、Feign日志

1.日志级别

2.日志配置类

3.配置文件

六、高阶配置

七、Feign与Springboot版本

八、技术问题

no suitable HttpMessageConverter found for response type



本章内容讲解重点目标以及面向用户

本章目标

了解feign的原理

掌握feign的使用

学会feign多种header的设置方式

学会feign日志控制

了解feign高阶配置项

其他开发注意事项

面向用户初、中、高阶的研发同学

很多时候,我们查看一些高阶架构同学在写Http服务调用时,调试跟踪代码时发现就只有接口签名,没有想okhttp那样写一些调用过程的代码,代码看起来风格清爽、优雅并不失逻辑严谨,读完该篇文章,您会掌握其实现方案,并提供demo协助您完成实战,有技术问题可以私信请教;

一、SpringBoot快速整合Feign

1.添加Pom依赖

 <properties>
        <spring-cloud-feign.version>3.1.3</spring-cloud-feign.version>
    </properties>

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.7.10</version>
</parent>
<dependencies>
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
   <version>${spring-cloud-feign.version}</version>
</dependency>
</dependencies>

2.启动类添加注解

@EnableFeignClients

3.引用Feign服务

@RestController
@RequestMapping("/stock")
public class StockController {

    @Autowired
    private LocalFeignService service;

    @GetMapping("/get")
    public String get(){
        service.add("10");
        return "Hello world";
    }
}

二、为请求添加Header的3种方式

1.添加固定header

@RestController
public class HomeController {

    @Resource
    private FeignClientService feignClientService;

    

    @RequestMapping(value = "/add")
    public String add(@RequestBody FeignReq req) {
        return "ok";
    }

   
    @RequestMapping("/test-add")
    public Object testAdd() {
        FeignReq req = new FeignReq();
        req.setId(System.currentTimeMillis());
        return feignClientService.add(req);
    }

}

在@PostMapping注解的headers参数中添加固定的header值,也包括一些从配置文件读取的配置项作为header值

@Component
@FeignClient(name = "feignClientService", url = "http://localhost:8081")
public interface FeignClientService {

    @PostMapping(value = "/add", headers = {"Authorization=myFeignSignToken", "Content-Type=text/plain", "App=${my.name}"})
    public String add(@RequestBody FeignReq req);

}

浏览器访问:http://localhost:8081/test-add

2.通过接口签名添加header

@RestController
public class HomeController {



    @Resource
    private FeignClientService feignClientService;


    @PostMapping(value = "/query")
    public String query(@RequestParam("queryName") String queryName) {

        return queryName + "ok";
    }


    @RequestMapping("/test-query")
    public Object testQuery() {
        Map<String, String> map = new HashMap<>();
        map.put("token", "ikong_token"+System.currentTimeMillis());
        return feignClientService.query("ikong", map);
    }

}

重点是在Map类型的headers,这里通过接口签名的@RequestHeader注解将Map对象转化成请求header

@Component
@FeignClient(name = "feignClientService", url = "http://localhost:8081", configuration = TestRequestInterceptor.class)
public interface FeignClientService {

    @PostMapping(value = "/query")
    public String query(@RequestParam("queryName") String queryName, @RequestHeader Map<String, String> headers);

}

浏览器访问:http://localhost:8081/test-query

3.动态添加header

@RestController
public class HomeController {


    @Resource
    private FeignClientService feignClientService;

    @RequestMapping("/search")
    public Object search(@RequestBody FeignReq req) {
        return "ok";
    }

   
    @RequestMapping("/test-search")
    public Object testSearch() {
        FeignReq req = new FeignReq();
        req.setId(System.currentTimeMillis());
        return feignClientService.search(req);
    }


}

@Component
@FeignClient(name = "feignClientService", url = "http://localhost:8081", configuration = TestRequestInterceptor.class)
public interface FeignClientService {


    @PostMapping("/search")
    public String search(@RequestBody FeignReq req);

}

通过FeignClient注解注入configuration = TestRequestInterceptor.class,在TestRequestInterceptor实现header动态添加能力


public class TestRequestInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        template.header(HttpHeaders.AUTHORIZATION, createApiSign());
    }

    /**
     * 创建接口签名
     *
     * @return
     */
    private String createApiSign() {
        return UUID.randomUUID().toString();
    }

}

浏览器访问:http://localhost:8081/test-search

三、为请求添加超时配置

1.默认超时时间

connectiontimeout : 10s,readtimeout : 60s

  public static class Options {
 
    private final int connectTimeoutMillis;
    private final int readTimeoutMillis;
 
    public Options(int connectTimeoutMillis, int readTimeoutMillis) {
      this.connectTimeoutMillis = connectTimeoutMillis;
      this.readTimeoutMillis = readTimeoutMillis;
    }
 
    public Options() {
      this(10 * 1000, 60 * 1000);
    }
 
    /**
     * Defaults to 10 seconds. {@code 0} implies no timeout.
     *
     * @see java.net.HttpURLConnection#getConnectTimeout()
     */
    public int connectTimeoutMillis() {
      return connectTimeoutMillis;
    }
 
    /**
     * Defaults to 60 seconds. {@code 0} implies no timeout.
     *
     * @see java.net.HttpURLConnection#getReadTimeout()
     */
    public int readTimeoutMillis() {
      return readTimeoutMillis;
    }
  }

3.超时异常

exception:feign.RetryableException: connect timed out executing POST http://xxx.ik.com/your/api

4.全局超时配置

feign.client.config.default.connectTimeout=5000
feign.client.config.default.readTimeout=5000

5.为单个服务设置超时配置

feign.client.config.yourService.connectTimeout=5
feign.client.config.yourService.readTimeout=5

四、为请求配置客户端负载均衡模式

五、Feign日志

feign的日志是建立在 debug日志模式的基础上的,不管是全局配置还是局部配置,代码配置还是属性配置,都需要先把日志模式调成debug模式:(下面与调用FeignClientService接口的日志模式为例)

1.日志级别

OpenFeign的日志级别有

  • NONE: 默认的,不显示任何日志。

  • BASIC: 仅记录请求方法、URL、响应状态码以及执行时间。

  • HEADERS:除了BASIC 中自定义的信息外,还有请求和响应的信息头。

  • FULL: 除了HEADERS中定义的信息外, 还有请求和响应的正文以及元数据。

2.日志配置类

@Configuration
public class OpenFeignLogConfig {
  @Bean
  Logger.Level feignLoggerLevel(){
    return Logger.Level.FULL;
  }
}

3.配置文件

logging:
  level:
  *[feign日志以什么级别监控哪个接口]:
  com.ik.ikong.service.FeignClientService: debug

六、高阶配置

七、Feign与Springboot版本

版本对照关系如下,详情也可以点击这里的链接在官网查看最新版本兼容关系

八、技术问题

在调用接口时候idea报错

no suitable HttpMessageConverter found for response type

解决过程

1.放开日志

@Configuration
public class FeignConfiguration {

    @Bean
    public feign.Logger logger() {
        return new Slf4jLogger();
    }
    @Bean
    public Logger.Level level() {
        return Logger.Level.FULL;
    }
}
logging:
  level:
    feign.Logger: debug

日志详细

从放开的日志来看,接口返回的head里:content-type: text/html; charset=UTF-8

虽然我在接口签名上增加了produces、consumes

@PostMapping(value = "/xxxxx/your/api", produces = "application/json;charset=utf-8", consumes = "application/json;charset=utf-8")

可以看到毫无效果,仍旧异常:no suitable HttpMessageConverter found for response type

猜想原生的http返回值只对application/json类型做了泛型的反序列化处理,是对接口返回的content-type: text/html;并不能进行json反序列化处理,遂增加该类型的json反序列化处理;

@Bean
    public HttpMessageConverters customConverters() {
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_HTML,MediaType.APPLICATION_JSON));
        return new HttpMessageConverters(false, Arrays.asList(mappingJackson2HttpMessageConverter, new StringHttpMessageConverter()));
    }

重点在mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_HTML,MediaType.APPLICATION_JSON));

最后成功完成增加content-type: text/html的json反序列化;

参考:Spring Cloud

Feign实现服务间的Http调用。_feign http调用_半命i的博客-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux:安装jdk

一、tar压缩包形式安装jdk&#xff1a; 1、安装到/opt目录下&#xff0c;如下图所示&#xff0c;先将tar.gz压缩包移动到/opt目录下&#xff0c;然后解压出来&#xff0c;命令依次是&#xff1a; tar -zxvf jdk-8u151-linux-x64.tar.gz 2、解压缩完毕后&#xff0c;我们使用ls命…

ArrayList继承了AbstractList,已经间接实现了List接口,那么为什么ArrayList还要显式实现List接口呢

这是因为,通过显式实现接口,ArrayList可以确保: 它实际上已经完整实现了List接口所规定的所有方法。 更明确地告诉其他程序员:这个类的目的是完整实现List接口。 如果ArrayList仅仅继承AbstractList,而未显式实现List接口,那么其他程序员在阅读代码时,无法立即确定这个类是否完…

STM32单片机(三)第二节:GPIO输出练习3(蜂鸣器)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

VTK 三维移动旋转工具 ,移动工具 旋转工具 三维旋转工具

前言&#xff1a;本文为该系列的第一篇建立3D交互窗口&#xff0c;​ 基于VTK&QT&#xff0c;建立3D交互窗口&#xff1b; 基本信息 开发平台&#xff1a;VS&QT 版 本&#xff1a;VS2017 & QT5.15.2 & VTK9.0.3 功能&#xff1a; 选中控件 移动 旋转 …

卷积神经网络的三大特性

卷积神经网络&#xff08;CNN&#xff09;的三大特性是&#xff1a; Sparse Interaction&#xff08;稀疏交互&#xff09;&#xff1a;稀疏交互是指在卷积神经网络中&#xff0c;每个神经元仅与输入数据的局部区域进行交互。这意味着神经元只对输入数据的一小部分感知&#xf…

Qt自定义控件(数字框与拖拽条互动)

一、效果 自定义红色区域组件&#xff0c;做到数字与拖拽条相互影响。 二、实现 输入合适的名字 打开自定义组件ui 选择合适的组件进行布局 将两个空间的信号和值进行绑定 新增自定义函数并实现 #include "smallwidget.h" #include "ui_smallwidget.h"sma…

从架构角度看网络安全:数字化时代企业如何构建防御体系?

导语 | 数字化时代&#xff0c;网络安全已经成为企业发展的重中之重&#xff0c;通过体系化的安全建设&#xff0c;企业可以从容应对愈加复杂的网络安全挑战。今天&#xff0c;我们特邀了腾讯云 TVP、赛博英杰科技董事长 谭晓生老师&#xff0c;他将从资深技术专家视角解读如何…

vscode vue-helper插件导致vscode 自动换行快捷键失效

vue-helper插件&#xff1a;代码提示&#xff0c;点击文件路径快速跳转。 vue-helper导致vscode功能异常&#xff1a;自动换行的快捷键&#xff08;alt Z&#xff09;失效了。 因为我平时看代码的时候喜欢 换行和不换行之间来回切换&#xff0c;所以这个alt Z 我是经常用的。…

URL缩短服务:复杂问题的简洁解决方案

项目简介&#xff1a;TinyURL是一项在线服务&#xff0c;允许用户将长网址缩短为简洁的短网址&#xff0c;以便于分享和使用。这种服务尤其适用于社交媒体和电子邮件&#xff0c;因为这些平台对链接长度可能有限制。TinyURL的使用非常简单&#xff0c;只需在它的网站上输入长网…

【 Android11 WiFi开发 一 】WiFi列表获取与展示

前言 最近在Android11上开发了WiFi相关功能&#xff0c;涉及到WiFi列表的获取、连接有密码的WiFi、连接已保存的WiFi、忘记连接的WiFi、添加其他WiFi。涉及到的知识点较多作以分篇记录&#xff0c;本篇将介绍WiFi列表的获取与展示。 说明 下面梳理下WiFi列表获取流程&#xff1…

白嫖的text2video模型ZeroScope_v2

ZeroScope是一种基于ModelScope的视频生成模型&#xff0c;可以通过文本生成16:9的高质量视频。 Zeroscape 是一种基于 Transformer 架构的语言生成模型&#xff0c;其中包括了多种不同的变体和版本。其中&#xff0c;zeroscape_v2 是一种较新的模型&#xff0c;相较于之前的版…

浅谈电气火灾监控系统在高层建筑的应用

摘要&#xff1a;通过介绍上海某高层建筑电气火灾监控系统设计情况&#xff0c;对电气火灾监控系统工作特点和具体设计内容进行说明&#xff0c;同时提出一些设 计过程中需注意的事项&#xff0c;供业内人士借鉴&#xff0c;以期增进对电气火灾监控系统设计的重视&#xff0c;…

【vim】Linux种的vim

:q quit (close window) :w save (“write”) :wq save and quit :e {name of file} open file for editing :ls show open buffers :help {topic} open help :help :w opens help for the :w command:help w opens help for the w movement <ESC>进入vim模式 &l…

Python如何调用C库(Windows Linux)

软硬件环境 ubuntu 18.04 64bitwindows 10 64bitPython 3.8GCC 4.9visual studio 前言 在做 python 开发中&#xff0c;经常会碰到&#xff0c;需要通过调用 C 的一个动态链接库来获取相应的值。本文详细讲解了 Windows 和 Linux 2个平台上的不同实现。 linux版的动态库 写个简…

搬运/移植Anaconda配置的项目注意事项

从旧电脑上将项目搬运至新电脑时&#xff0c;搬运项目的时候&#xff0c;将原项目的环境也拷贝过去了&#xff0c;发现出现了问题&#xff0c;使用pip进行安装库的时候&#xff0c;怎么都用不了。错误内容为&#xff1a; Fatal error in launcher: Unable to create process us…

【算法与数据结构】541、LeetCode反转字符串 II

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题自己写了一个swap函数&#xff0c;用来反转字符串&#xff0c;也可以用库函数reverse。然后是用in…

一文学会使用键盘控制moveit2机械臂模型

文章目录 前言一、官方样例实现软件版本bug修复运行测试 二、gp110机械臂控制文件添加文件修改编译工程运行测试 总结 前言 在之前文章的基础上相信大家已经学会了如何搭建一个机械臂模型&#xff0c;那么我们如何对其进行控制呢&#xff0c;上网检索了一下没找到能清晰指导实…

3.2 Java标识符

3.2 Java标识符 关键字&#xff0c;Java中一些预先设定好的单词被称为关键字常用关键字如下图所示 图中的关键字都是Java预先设定好的&#xff0c;在平时应用中不能用这些关键词作为名字来使用。因为Java已经赋予这些关键字一些意义不能直接使用&#xff0c;这些关键词是Java中…

真实遇到Redis双写一致性问题

今天工作中接到一个bug&#xff0c;产品那边描述&#xff0c; 在后台添加一个供应商后前台无法展示。 是个例还是全部&#xff1f;他说应该是个例。 开始分析。。。。。。。 首先数据库查询可以查出新添加的这个供应商的&#xff0c;说明添加成功的&#xff0c;唯一的问题肯定…

Baltamatica 北太天元 —— 基于模拟退火算法的旅行商问题

文章目录 北太天元&#xff08;Baltamatica&#xff09;简介Baltamatica 复现基于Matlab的旅行商问题问题描述模拟退火算法Metropolis准则算法流程图&#xff1a; Demo1&#xff1a;只考虑累计距离&#xff0c;通过模拟退火算法求解最短路径matlab代码&#xff1a;Baltam代码&a…