OpenFeign
1.说在前面#
上 一 节 我 们 讲 到 Ribbon 做 了 负 载 均 衡 , 用 Eureka-Client 来 做 服 务 发 现 , 通 过
RestTemplate 来完成服务调用,但是这都不是我们的终极方案,终极方案是使用 OpenFeign
1.OpenFeign 简介#
https://docs.spring.io/spring-cloud-openfeign/docs/2.2.4.RELEASE/reference/html/#spring-cloud-feign
Feign 是声明性(注解)Web 服务客户端。它使编写 Web 服务客户端更加容易。要使用 Feign****,
请创建一个接口并对其进行注解。它具有可插入注解支持,包括 Feign 注解和 JAX-RS 注解。
Feign 还支持可插拔编码器和解码器。Spring Cloud 添加了对 Spring MVC 注解的支持,并
支持使用 HttpMessageConverters,Spring Web 中默认使用的注解。Spring Cloud 集成
了 Ribbon 和 Eureka 以及 Spring Cloud LoadBalancer,以在使用 Feign 时提供负载平衡
的 http 客户端。
Feign 是一个远程调用的组件 (接口,注解) http 调用的
Feign 集成了 ribbon
ribbon 里面集成了 eureka
2.OpenFeign 快速入门#
2.1 使用OpenFeign#
- 使用OpenFeign 创建接口
package com.example.userservice.fegin;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @FeignClient(value = "order-service")
* value 就是提供者的应用名称
*/
@FeignClient(value = "order-service")
public interface UserOrderFeign {
/**
* 你需要调用哪个controller 就写它的方法签名
* 方法签名(就是包含一个方法的所有的属性)
*
* @return
*/
@GetMapping("doOrder")
String doOrder();
}
2.调用接口
package com.example.userservice.controller;
import com.example.userservice.fegin.UserOrderFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
public UserOrderFeign userOrderFeign;
/**
* 总结
* 浏览器(前端)-------> user-service(/userDoOrder)-----RPC(feign)--->order-service(/doOrder)
* feign的默认等待时间时1s
* 超过1s就在直接报错超时
*
* @return
*/
@GetMapping("userDoOrder")
public String userDoOrder() {
System.out.println("有用户进来了");
String s = userOrderFeign.doOrder();
return s;
}
}
- 修改启动类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients // 开启feign的客户端功能 才可以帮助我们发起调用
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
2.2 设置超时设置#
ribbon:
ReadTimeout: 3000 # 给3s超时时间
ConnectTimeout: 3000 # 链接服务的超时时间
2.3 OpenFeign 通过JDK动态代理实现#
/**
* 接口是不能做事情的
* 如果想做事 必须要有对象
* 那么这个接口肯定是被创建出代理对象的
* 动态代理 jdk(java interface 接口 $Proxy ) cglib(subClass 子类)
* jdk动态代理 只要是代理对象调用的方法必须走 java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
*/
4.OpenFeign 调用参数处理(开发重点)#
4.1 说在前面#
Feign 传参确保消费者和提供者的参数列表一致 包括返回值 方法签名要一致
-
通过 URL 传参数,GET 请求,参数列表使用@PathVariable(“”)
-
如果是 GET 请求,每个基本参数必须加@RequestParam(“”)
-
如果是 POST 请求,而且是对象集合等参数,必须加@Requestbody 或者@RequestParam
4.2 参数配置#
- 传参
/**
* @FeignClient(value = "order-service")
* value 就是提供者的应用名称
*/
@FeignClient(value = "order-service")
public interface UserOrderFeign {
/**
* 你需要调用哪个controller 就写它的方法签名
* 方法签名(就是包含一个方法的所有的属性)
*
* @return
*/
@GetMapping("doOrder")
String doOrder();
@GetMapping("testUrl/{name}/and/{age}")
String testUrl(@PathVariable("name") String name, @PathVariable("age") Integer age) ;
@GetMapping("oneParam")
String oneParam(@RequestParam(required = false) String name) ;
@GetMapping("twoParam")
String twoParam(@RequestParam(required = false) String name, @RequestParam(required = false) Integer age);
@PostMapping("oneObj")
String oneObj(@RequestBody Order order) ;
@PostMapping("oneObjOneParam")
String oneObjOneParam(@RequestBody Order order,@RequestParam("name") String name) ;
}
-
Controller
@RestController public class ParamController { @GetMapping("testUrl/{name}/and/{age}") public String testUrl(@PathVariable("name") String name, @PathVariable("age") Integer age) { System.out.println(name + ":" + age); return "ok"; } @GetMapping("oneParam") public String oneParam(@RequestParam(required = false) String name) { System.out.println(name); return "ok"; } @GetMapping("twoParam") public String twoParam(@RequestParam(required = false) String name, @RequestParam(required = false) Integer age) { System.out.println(name); System.out.println(age); return "ok"; } @PostMapping("oneObj") public String oneObj(@RequestBody Order order) { System.out.println(order); return "ok"; } @PostMapping("oneObjOneParam") public String oneObjOneParam(@RequestBody Order order,@RequestParam("name") String name) { System.out.println(name); System.out.println(order); return "ok"; } ////////////////// 单独传递时间对象 @GetMapping("testTime") public String testTime(@RequestParam Date date){ System.out.println(date); return "ok"; } }
-
调用openFegin
@GetMapping("testParam") public String testParam(){ String cxs = userOrderFeign.testUrl("cxs", 18); System.out.println(cxs); String t = userOrderFeign.oneParam("老唐"); System.out.println(t); String lg = userOrderFeign.twoParam("雷哥", 31); System.out.println(lg); Order order = Order.builder() .name("牛排") .price(188D) .time(new Date()) .id(1) .build(); String s = userOrderFeign.oneObj(order); System.out.println(s); String param = userOrderFeign.oneObjOneParam(order, "稽哥"); System.out.println(param); return "ok"; }
4.3 时间日期参数问题#
使用 feign 远程调用时,单独传递 Date 类型,接收方的时间会相差 14 个小时,是因为时区造成
的。
解决办法:
/**
* Sun Mar 20 10:24:13 CST 2022
* Mon Mar 21 00:24:13 CST 2022 +- 14个小时
* 1.不建议单独传递时间参数。bao'guo对象里面
* 2.转成字符串 2022-03-20 10:25:55:213 因为字符串不会改变
* 3.jdk LocalDate 年月日 LocalDateTime 会丢失毫秒
* 4.改feign的源码
*
* @return
*/
5.OpenFeign 总结#
OpenFeign 主要基于接口和注解实现了远程调用
源码总结:面试
- OpenFeign 用过吗?它是如何运作的?
在主启动类上加上@EnableFeignClients 注解后,启动会进行包扫描,把所有加了
@FeignClient(value=”xxx-service”)注解的接口进行创建代理对象通过代理对象,使用
ribbon 做了负载均衡和远程调用
- 如何创建的代理对象?
当 项 目 在 启 动 时 , 先 扫 描 , 然 后 拿 到 标 记 了 @FeignClient 注 解 的 接 口 信 息 , 由
ReflectiveFeign 类的 newInstance 方法创建了代理对象 JDK 代理
- OpenFeign 到底是用什么做的远程调用?
使用的是 HttpURLConnection (
java.net)
- OpenFeign 怎么和 ribbon 整合的?
在代理对象执行调用的时候
6.OpenFeign 日志#
6.1 OpenFeign 的日志功能#
从前面的测试中我们可以看出,没有任何关于远程调用的日志输出,如请头,参数
Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而揭开 Feign 中 Http 请
求的所有细节
6.1.1 OpenFeign 的日志级别
NONE 默认的,不显示日志
BASE 仅记录请求方法,URL ,响应状态码及执行时间
HEADERS 在 BASE 之上增加了请求和响应头的信息
FULL 在 HEADERS 之上增加了请求和响应的正文及无数据
设置日志级别
@Bean
public Logger.Level level(){
return Logger.Level.FULL;
}
开启日志
logging:
level:
com.example.userservice.fegin.UserOrderFeign: debug # 我需要答应这个接口下面的日志
作者:Esofar
出处:https://www.cnblogs.com/firsthelloworld/p/17439940.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)