SpringCloud Alibaba实战和源码(8)OpenFeign使用

1、 使用Feign实现远程HTTP调用

1.1、常见HTTP客户端

  • HttpClient

    HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 Http 协 议的客户端编程工具包,并且它支持 HTTP 协议最新版本和建议。HttpClient 相比传统 JDK 自带的 URLConnection,提升了易用性和灵活性,使客户端发送 HTTP 请求变得容易,提高了开发的效率。

  • Okhttp

    一个处理网络请求的开源项目,是安卓端最火的轻量级框架,由 Square 公司贡献,用于替代 HttpUrlConnection 和 Apache HttpClient。OkHttp 拥有简洁的 API、高效的性能,并支持多种协议 (HTTP/2 和 SPDY)。

  • HttpURLConnection

    HttpURLConnection 是 Java 的标准类,它继承自 URLConnection,可用于向指定网站发送 GET 请求、 POST 请求。HttpURLConnection 使用比较复杂,不像 HttpClient 那样容易使用。

  • RestTemplate

    RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率。

1.2、什么是Fegin

Feign是Netflix开源的声明式HTTP客户端

1.3、优点

Feign可以做到使用 HTTP 请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方 ,更感知不到这是个 HTTP 请求。

【Fegin和OpenFeign的区别:Spring Cloud openfeign对Feign进行了 增强,使其支持Spring MVC注解,另外还整合了Ribbon和Eureka,从而使得Feign的使用更加方便 】

1.4、重构以前的代码:

三板斧:

  1. 引入依赖

     <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
    
  2. 写启动注解

    image.png

  3. 增加配置

    暂时没有配置
    
  4. 进行改造

增加一个feign,他也是基于ribbon进行操作的,所以以前我们学的ribbon在这里也适用

@FeignClient(name = "msb-stock")
public interface StockFeignClient {@GetMapping("/stock/reduce/{productId}")String reduce(@PathVariable Integer productId);
}
@Slf4j
@RestController
public class OrderController {@Autowiredprivate StockFeignClient stockFeignClient;@GetMapping("/order/create")public String createOrder(Integer productId,Integer userId){String reduce = stockFeignClient.reduce(productId);log.info("减库存成功:{}",reduce);return "下单成功";}
}

在这里插入图片描述
在这里插入图片描述

我们在这里看一下我们启动了两个微服务,他们都发起了调用,也就feign后台实现了负载均衡。我们可以看一下他的继承关系,我们发现fegin里面有依赖了ribbon,所以他除了增强了我们springmvc注解,同时也整合我们的ribbon

image.png

2、Feign的组成

接口作用默认值
Feign.BuilderFeign的入口Feign.Builder
ClientFeign底层用什么去请求和Ribbon配合时:LoadBalancerFeignClient<br />不和Ribbon配合时:Feign.Client.Default
Contract契约,注解支持SpringMVC Contract
Encoder解码器,用于将独享转换成HTTP请求消息体SpringEncoder
Decoder编码器,将相应消息体转成对象ResponseEntityDecoder
Logger日志管理器Slf4jLogger
RequestInterceptor用于为每个请求添加通用逻辑(拦截器,例子:比如想给每个请求都带上heared)

Feign.Client.Default 利用的是我们默认的HttpURLConnection,他是没有连接池的。也没有资源管理这个概念,性能不是很好,

image.png

3、细粒度配置自定义

3.1、代码方式-指定日志级别

feign默认是不打印任何日志的,但是我们希望打印一些日志信息。比如调用的时间。

Feign设置方式就不同的,他有四个级别如下:

级别打印日志内容
NONE(默认值)不记录任何日志
BASIC仅记录请求方法、URL、响应状态代码以及执行时间
HEADERS记录BASIC级别的基础上,记录请求和响应的header
FULL记录请求和响应的header、body和元数据
1.1 指定springboot日志

Feign日志是基于Spring boot的日志所以先设置SpringBoot日志:

logging:level:com.msb: debug
1.2 创建配置类

BASIC使用于生产环境 FULL适用于开发环境

创建配置类UserFeignConfiguration ,注意这里并没有增加@Configuration

//这里不能增加@Configuration,如果添加了就会变为全局配置文件。
public class StockFeignConfiguration {@Beanpublic Logger.Level level(){return Logger.Level.FULL;}
}

更改请求feign的配置文件。

1.3 将配置类引入

image.png

3.2、属性方式-指定日志级别

feign.client.config.<feignName>.loggerLevel:full

logging:level:com.msb: debug
feign:client:config:msb-stock:loggerLevel: full

4、全局配置自定义

1、代码配置

  • 方式一:让父子上下文ComponentScan重叠(强烈不建议使用)

    @Configuration
    public class StockFeignConfiguration {/*** 日志级别* 通过源码可以看到日志等级有 4 种,分别是:* NONE:不输出日志。* BASIC:只输出请求方法的 URL 和响应的状态码以及接口执行的时间。* HEADERS:将 BASIC 信息和请求头信息输出。* FULL:输出完整的请求信息。*/@Beanpublic Logger.Level level(){return Logger.Level.FULL;}
    }
    
  • 方式二【唯一正确的途径】:
    EnableFeignClients(defaultConfiguration=xxx.class)

    image.png

image.png

2、属性配置

logging:level:com.msb: debug
feign:client:config:default:loggerLevel: full

5、 支持的配置项

5.1、契约配置

Spring Cloud 在 Feign 的基础上做了扩展,可以让 Feign 支持 Spring MVC 的注解来调用。原生的 Feign 是不支持 Spring MVC 注解的,如果你想在 Spring Cloud 中使用原生的注解方式来定义客户端也是 可以的,通过配置契约来改变这个配置,Spring Cloud 中默认的是 SpringMvcContract。

1.1代码方式
    /*** 修改契约配置,这里仅仅支持Feign原生注解* 这里是一个扩展点,如果我们想支持其他的注解,可以更改Contract的实现类。* @return*/@Beanpublic Contract feignContract(){return new Contract.Default();}

注意:这里修改了契约配置之后,我们就只能用Fegin的原生注解

image.png

1.2 属性方式

image.png

5.2、编解码

Feign 中提供了自定义的编码解码器设置,同时也提供了多种编码器的实现,比如 Gson、Jaxb、Jackson。 我们可以用不同的编码解码器来处理数据的传输。。

扩展点:Encoder & Decoder

默认我们使用:SpringEncoder和SpringDecoder

package feign.codec;
public interface Encoder {void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException;
}
package feign.codec;
public interface Decoder {Object decode(Response response, Type type) throws IOException, DecodeException, FeignException;
}
2.1 代码方式
@Bean
public Decoder decoder(){return new CustomDecoder();
}
@Bean
public Encoder encoder(){return new CustomEncoder();
}
2.2 属性方式
feign:client:config:#想要调用的微服务的名称msb-user:encoder: com.xxx.CustomDecoderdecoder: com.xxx..CustomEncoder

5.3、拦截器

通常我们调用的接口都是有权限控制的,很多时候可能认证的值是通过参数去传递的,还有就是通过请求头 去传递认证信息,比如 Basic 认证方式。

3.1 扩展点:
package feign;public interface RequestInterceptor {void apply(RequestTemplate template);
}
3.2 使用场景
  1. 统一添加 header 信息;
  2. 对 body 中的信息做修改或替换;
3.3 自定义逻辑
package com.msb.order.interceptor;import feign.RequestInterceptor;
import feign.RequestTemplate;public class FeignAuthRequestInterceptor implements RequestInterceptor {private String tokenId;public FeignAuthRequestInterceptor(String tokenId) {this.tokenId = tokenId;}@Overridepublic void apply(RequestTemplate template) {template.header("Authorization",tokenId);}
}
package com.msb.order.configuration;import com.msb.order.interceptor.FeignAuthRequestInterceptor;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FeignConfig {@Value("${feign.tokenId}")private String tokenId;/*** 自定义拦截器* @return*/@Beanpublic FeignAuthRequestInterceptor feignAuthRequestInterceptor(){return new FeignAuthRequestInterceptor(tokenId);}
}
feign:tokenId: d874528b-a9d9-46df-ad90-b92f87ccc557

在msb-stock项目中增加springmvc中的拦截器

拦截器代码:

package com.msb.stock.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {boolean flag = true;// 逻辑认证String authorization = request.getHeader("Authorization");log.info("获取的认证信息 Authorization:{}",authorization);if(StringUtils.hasText(authorization)){return true;}return false;}
}

增加类配置:

package com.msb.user.interceptor;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {@Overrideprotected void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new AuthInterceptor());}

5.4、Client 设置

Feign 中默认使用 JDK 原生的 URLConnection 发送 HTTP 请求,我们可以集成别的组件来替换掉 URLConnection,比如 Apache HttpClient,OkHttp。

4.1 扩展点

Feign发起调用真正执行逻辑:feign.Client#execute (扩展点)

public interface Client {Response execute(Request request, Options options) throws IOException;}
4.2 配置Apache HttpClient
  1. 引入依赖

    <dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
    </dependency>
    
  2. 修改yml配置

    开启feign ,这里可以不用配置,可以参考源码分析

    feign:httpclient:#使用apache httpclient做请求,而不是jdk的HttpUrlConnectionenabled: true# feign最大链接数 默认200max-connections: 200#feign 单个路径的最大连接数  默认 50max-connections-per-route: 50
    
  3. 源码分析 FeignAutoConfiguration

    image.png

此时默认增加一个ApacheHttpCient实现类

image.png

4.3 设置OkHttp
  1. 引入依赖

    <dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId>
    </dependency>
    
  2. 增加配置

    feign:okhttp:enabled: true#线程池可以使用httpclient的配置   httpclient:max-connections: 200max-connections-per-route: 50
    

image.png

3、源码分析 FeignAutoConfiguration

image.png

5.5、超时配置

通过 Options 可以配置连接超时时间和读取超时时间,Options 的第一个参数是连接的超时时间(ms), 默认值是 10s;第二个是请求处理的超时时间(ms),默认值是 60s。

Request.Options

image.png

5.1 代码配置
@Bean
public Request.Options options(){return new Request.Options(2000,50000);
}

msb-stock改造

@GetMapping("query")
public User queryInfo(User user){try {Thread.sleep(10*1000);} catch (InterruptedException e) {e.printStackTrace();}return user;
}

image.png

6、推荐配置方式

  • 尽量使用属性配置,属性方式实现不了的情况下再考虑用代码配置
  • 在同一个微服务内尽量保持单一性,比如统一使用属性配置,不要两种方式混用,增加定位代码的复杂性

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3.28学习总结

java 封装 封装体现了java的面向对象的特点,用户不用知道程序是如何运行的,只用按照所给的格式输入参数,便可得到对应的结果. 一个完整的封装需要每个实例变量都用private来修饰并拥有相应的public getter和setter方法. 代码 public class girl {private int age;public st…

爬取豆瓣电影分类排行榜中的电影详情数据

进入界面&#xff0c;右键打开检测&#xff0c;选择网络 然后网页滚动条拉倒最下面使其刷出新的数据&#xff0c;然后查看数据包 编写代码 import requests import jsonif __name__ __main__:get_url https://movie.douban.com/j/chart/top_listheaders {User-Agent:Mozil…

每日一题 --- 快乐数[力扣][Go]

快乐数 题目&#xff1a;202. 快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到…

云原生应用(5)之Dockerfile精讲及新型容器镜像构建技术

一、容器与容器镜像之间的关系 说到Docker管理的容器不得不说容器镜像&#xff0c;主要因为容器镜像是容器模板&#xff0c;通过容器镜像我们才能快速创建容器。 如下图所示&#xff1a; Docker Daemon通过容器镜像创建容器。 二、容器镜像分类 操作系统类 CentOS Ubuntu 在…

OSCP靶场--GLPI

OSCP靶场–GLPI 考点(CVE-2022-35914 php执行函数绕过ssh端口转发jetty xml RCE) 1.nmap扫描(ssh端口转发) ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.194.242 -sV -sC --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-03-26 22:22 EDT Nmap…

游戏本笔记本更换@添加内存条实操示例@DDR5内存条

文章目录 添加内存条的意义准备工具设备拔出电源适配器并关机&#x1f47a;样机 内存条上的金手指安装过程Notes 安装后开机初次开机速度屏幕显示分辨率和闪烁问题检查安装后的效果 添加内存条的意义 参考双通道内存DDR5多通道内存-CSDN博客 准备工具 准备一个质量差不多的螺…

go面向对象

继承 封装 多态 定义结构体 //定义老师的结构体 type Teacher struct {Name stringAge intSchool string }func main() {var t1 Teacherfmt.Println(t1)t1.Name "tom"t1.Age 20t1.School "school"fmt.Println(t1) } 结构体实例的创建 package ma…

c++ 有名对象和匿名对象

c 有名对象和匿名对象 有名对象就是有名字的对象&#xff0c;匿名对象就是没有名字的对象。 #define _CRT_SECURE_NO_WARNINGS 1 using namespace std; #include<iostream> class score { public:score(){math 100;chinese 100;english 100;}score(int _math, int _…

spring-boot-devtools配置和原理

一、前言 昨天&#xff0c;一个同事Eclipse在启动SpringBoot项目时一直不停地加载&#xff0c;后来发现是因为spring-boot-devtools造成的问题&#xff0c;因为我们把日志输出的目录设置在当前项目里&#xff08;~/mnt/logs/&#xff0c;这样设置是因为mac电脑没有根目录权限&…

MySQL进阶之(六)索引的使用与设计原则

六、索引的使用与设计原则 6.1 索引的声明与使用6.1.1 索引的分类01、普通索引02、唯一性索引03、主键索引04、单列索引05、多列索引&#xff08;组合索引、联合索引&#xff09;06、全文索引07、空间索引 6.2 创建索引6.2.1 创建表时创建索引01、创建普通索引02、创建唯一索引…

Java毕业设计-基于springboot开发的疫情防控期间外出务工人员信息管理系统-毕业论文+答辩PPT(附源代码+演示视频)

文章目录 前言一、毕设成果演示&#xff08;源代码在文末&#xff09;二、毕设摘要展示1、开发说明2、需求分析3、系统功能结构 三、系统实现展示1、系统功能模块2、后台登录2.1管理员功能2.2用户功能2.3采集员功能2.4分析员功能 四、毕设内容和源代码获取总结 Java毕业设计-基…

外包干了4年,技术退步明显。。。。

说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入上海某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&a…

在Linux上使用nginx反向代理部署Docker网站

在政务云上部署Web环境&#xff0c;为了保证服务器安全&#xff0c;甲方只开放一个端口且只允许使用https协议进行访问&#xff0c;经过思考&#xff0c;决定使用docker部署网站&#xff0c;使用nginx反向代理&#xff0c;通过不同的二级域名访问不同的端口。 1 使用docker部署…

vue基础——java程序员版(总集)

前言&#xff1a; ​ 这是一个java程序员的vue学习记录。 ​ vue是前端的主流框架&#xff0c;按照如今的就业形式作为后端开发的java程序员也是要有所了解的&#xff0c;下面是本人的vue学习记录&#xff0c;包括vue2的基本使用以及引入element-ui&#xff0c;使用的开发工具…

三位数组合-第12届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第42讲。 三位数组合&#…

方格分割(蓝桥杯)

文章目录 方格分割题目描述答案&#xff1a;509思路dfs 方格分割 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 6x6的方格&#xff0c;沿着格子的边线剪开成两部分。 要求这两部分的形状完全相同。 如下就是三…

HTTP状态 405 - 方法不允许

方法有问题。 用Post发的请求&#xff0c;然后用Put接收的。 大家也可以看看是不是有这种问题 <body><h1>HTTP状态 405 - 方法不允许</h1><hr class"line" /><p><b>类型</b> 状态报告</p><p><b>消息…

Python程序设计 循环结构(二)

1.斐波那契数列 编写一个能计算斐波那契数列中第x个数的小程序。斐波那契数列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又称黄金分割数列、 因数学家莱昂纳多斐波那契&#xff08;Leonardoda Fibonacci&#xff09;以兔子繁殖为例子而引入&#xff0c;故又称为…

Redis入门到实战-第二十弹

Redis实战热身Time series篇 完整命令参考官网 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的&#xff08;采用BSD许可证&#xff09;&#xff0c;用作数据库、缓存、消息代…

MTransE阅读笔记

Multilingual Knowledge Graph Embeddings for Cross-lingual Knowledge Alignment 用于交叉知识对齐的多语言知识图谱嵌入(MTransE) Abstract 最近的许多工作已经证明了知识图谱嵌入在完成单语知识图谱方面的好处。由于相关的知识库是用几种不同的语言构建的&#xff0c;因…