OpenFeign框架原生应用(一)简单示例
SpringCloud OpenFeign![placeholder image](/images/user.png)
admin 发布于:2024-07-26 09:36:31
阅读:loading
通常对于OpenFeign技术的使用都是通过`spring-cloud-starter-openfeign`的方式引用的,需要依赖spring-cloud相关的组件,我个人也是在学习Spring Cloud Alibaba相关技术体系时,总结过两篇关于OpenFeign的应用示例。如果想丝滑的使用OpenFeign而又不想在项目中集成SpringCloud相关技术体系时(企业工作中总会有一些不可与之制约的因素),可以尝试使用OpenFeign的原生应用,仍然是非常丝滑的去使用。本文将使用OpenFeign的原生应用实现接口的调用示例。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.7.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.7.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.7.18</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.13.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.9</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>${feign.version}</version>
<exclusions>
<exclusion>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>${feign.version}</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<version>${feign.version}</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-spring4</artifactId>
<version>13.2.1</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-slf4j</artifactId>
<version>${feign.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.8.0</version>
</dependency>
特别说明:
(1)截至当前(2024-07)OpenFeign最新版本为13.3,所以本次使用最新版本进行实践,group id为io.github.openfeign;
(2)整体上feign-spring的版本只有最新版13.3,该版本基于JDK17编译,不支持JDK8,需使用feign-spring4依赖,后者是支持JDK8和Spring4.X的版本13.2.1;
(3)本次使用的SpringBoot版本为当前最新2.X的版本,引入的logback与feign-slf4j的13.3版本依赖的logback版本冲突,故排除feign-slf4j对logback的依赖,使用SpringBoot框架的依赖;
(4)最新版feign-okhttp依赖的okhttp版本为4.1X的版本,版本太高,jar包中不完全是class文件,无法正常使用,所以使用支持JDK8的版本,降级到可使用的最高版本3.14.9;
(5)feign-form-spring同样的道理,降级使用到可用的最新版本3.8.0;
PS:小小的坐标依赖,如果想要非常合理的依赖,其内部还是有很大的学问的。
(1)定义基于Apache的HttpClient配置类,声明连接池的配置、超时的参数等;
(2)定义基于Okhttp的HttpClient配置类,声明链接参数信息、超时的参数等;
(3)定义参数传递的编码、解码和错误处理类,选用按照Spring MVC的规范调用,集成Spring提供的组件实现;
(4)定义Controller接口,提供一些测试的接口生产者;
PS:Apache与Okhttp的底层框架是二选一的,一般在实际中选定一个组件来使用。
本次提供一些简单点的基础示例,主要是使用OpenFeign的原生调用API的演示,包含构造接口的代理实现过程和Spring MVC规范的接口传参数,有:@RequestParam、@RequestBody、@PathVariable、@RequestPart等;同时示例包含@GetMapping、@PostMapping、@PutMapping等请求方式,参考代码如下:
import ...;
/**
* 简单Api测试
* @author chendd
*/
@RestController
@RequestMapping(value = "/api/simple" , consumes = MediaType.ALL_VALUE , produces = MediaType.APPLICATION_JSON_VALUE)
public class SimpleApiController {
@GetMapping(value = "/hello")
public String hello() {
return "world";
}
@GetMapping(value = "/hello/{name}")
public String hello(@PathVariable String name) {
return "hello:" + name;
}
@PostMapping(value = "/hello/{id}")
public Triple<String , String , String> hello(@PathVariable String id ,
@RequestParam("name") String name ,
String website) {
return Triple.of(id , name , website);
}
@PutMapping(value = "/hello")
public Point hello(@RequestBody Point param) {
return param;
}
}
import ...;
/**
* 简单的接口调用
* @author chendd
*/
public interface SimpleHttpClient {
/**
* 无参数
*/
@GetMapping(value = "/api/simple/hello" , produces = MediaType.APPLICATION_JSON_VALUE)
String sayHello();
/**
* 1个参数
*/
@GetMapping(value = "/api/simple/hello/{name}")
String sayHello(@PathVariable("name") String name);
/**
* 3个参数【拼接在URL上传递的参数】
*/
@PostMapping(value = "/api/simple/hello/{id}")
String sayHello(@PathVariable("id") String id , @RequestParam("name") String name , @RequestParam("website") String website);
/**
* 3个参数【拼接在URL上传递的参数】
*/
@PutMapping(value = "/api/simple/hello")
String sayHello(@RequestBody Point param);
}
import ...;
/**
* 接口测试【简单】
* @author chendd
*/
@RunWith(JUnit4.class)
public class SimpleHttpClientTest {
private SimpleHttpClient httpClient;
@Before
public void init() {
ObjectMapper objectMapper = new ObjectMapper();
final Feign.Builder builder = new Feign.Builder()
.contract(new SpringContract())
//.client(new OkHttpClient(OkHttpClientConfig.getHttpClient()))
.client(new ApacheHttpClient(HttpClientConfig.getHttpClient()))
.encoder(new HttpFeignFormEncoder(objectMapper))
.decoder(new HttpFeignFormDecoder(objectMapper))
.errorDecoder(new HttpFeignFormError())
.logger(new Slf4jLogger())
.logLevel(Logger.Level.FULL);
httpClient = builder.target(SimpleHttpClient.class, "http://127.0.0.1:8080");
}
@Test
public void hello0ArgsTest() {
System.out.println("===调用无参数返回String接口===");
httpClient.sayHello();
}
@Test
public void hello1ArgsTest() {
System.out.println("===调用@PathVariable参数返回String接口===");
httpClient.sayHello("chendd");
}
@Test
public void hello3ArgsTest() {
System.out.println("===调用@PathVariable、@RequestParam===");
httpClient.sayHello("88911" , "陈冬冬" , "https://www.chendd.cn");
}
@Test
public void helloBodyArgsTest() {
System.out.println("===调用@RequestBody接口===");
httpClient.sayHello(new Point(88911 , 36));
}
}
特别说明
(1)init方法是测试接口方法的前置方法,提供了Feigin接口的初始化过程,包含各个参数的处理方式及测试接口的代理类实现;
(2)当前测试类提供的接口测试均为简单的接口,包含常规的多种参数传递和接口响应结果;
(3)示例中包含了使用slf4j来输出日志,并且设置了接口传输过程中的日志信息;
(4)未设置拦截器的其它功能点;
项目运行需要先使启动server,运行接口服务端,而后运行接口的Junit客户端,参考如下图所示:
(1)OpenFeign接口中的Spring MVC风格的调用并不是完全与Spring MVC的请求调用一致,反而更加严谨和规范,需要注意更多的细节规范;
(2)理论上@GetMapping是不支持@RequestBody传递参数的,许多浏览器也不支持,关键是Okhttp框架也不支持,源码中存在对此种传参数传输的校验,抛出异常;而Apache的HttpClient表示支持;
(3)本篇是常规基础接口的调用演示,下一篇是对于OpenFeign的进阶演示,包含了文件上传和下载的参数传递方式;
(4)源码工程下载:《源码下载.zip》;
点赞