之前也用过Feign,不过是在SpringCloud体系内用的,需要配合服务发现一起用。
偶然通过一位同事了解到Spring Boot也可以直接整合Feign进行Http远程调用,赶紧试了一把尝尝鲜,果断鸟枪换炮。感谢小伙伴的分享~
话不多说直接show code。
建立工程引入依赖
建立一个SpringBoot应用的过程不再赘述了,基于IDEA创建一个新的工程还是蛮快的。
在Pom.xml中添加如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/io.github.openfeign/feign-okhttp -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>10.2.3</version>
</dependency>
复制代码
由于feign自带的http客户端实现是HttpURLConnection,没有连接池功能,可配置能力也比较差,因此我们使用okhttp作为底层的http客户端的具体实现。
配置OkHttp
编写一个FeignOkHttpConfig配置类,配置OkHttpi实例。
@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignOkHttpConfig {
@Bean
public okhttp3.OkHttpClient okHttpClient(){
return new okhttp3.OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool())
.build();
}
}
复制代码
主要设置了链接超时时间及读写超时时间,这里是笔者随意写的,具体业务中使用需要根据业务特点去灵活调整。
编写FeignClient接口
笔者为了测试方便,直接在博客的某个路径下放置了一个json文件,文件内容如下:
{
"code": "10000",
"desc": "success",
"data": {
"name": "snowalker",
"age": "18"
}
}
复制代码
我们接着编写Feign客户端对此json文件发起调用:
@FeignClient(name = "feignClientProxy",url = "http://wuwenliang.net/samples/")
public interface FeignClientProxy {
@RequestMapping(value = "/snowalker.json", method = RequestMethod.GET)
@ResponseBody
ResponseData<DemoResp> invoke(@RequestParam(value="name") String name);
/**
* 容错处理类,当调用失败时 返回空字符串
*/
@Component
class DefaultFallback implements FeignClientProxy {
@Override
public ResponseData<DemoResp> invoke(@RequestParam(value="snowalker") String name){
return new ResponseData<DemoResp>().setCode("40004").setDesc("服务异常").setData(null);
}
}
}
复制代码
这里主要关注注解 @FeignClient,参数name用以指定bean实例名,url用以指定远程服务调用根路径。
在具体的方法上标注@RequestMapping,指定资源的相对路径以及调用的方法。
编写一个本地测试接口,调用Feign客户端
@Controller
@RequestMapping("/demo")
public class FeignDemoController {
@Autowired
FeignClientProxy feignClientProxy;
@RequestMapping(value = "feign")
@ResponseBody
public String testFeign(@RequestParam(name = "name") String name) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
ResponseData<DemoResp> respResponseBody = feignClientProxy.invoke(name);
return "调用结果:" + objectMapper.writeValueAsString(respResponseBody);
}
}
复制代码
这个代码就很简单了,不需要多解释,就是接收参数name直接透传Feign客户端(通过@Autowired注解注入),发起远程调用,将调用结果(json反序列化后的实体)打印出来。
测试
启动该demo服务,访问FeignDemoController.testFeign的mapping路径:
http://localhost:8080/demo/feign?name=123
复制代码
可以看到如下返回参;
调用结果:{"code":"10000","desc":"success","data":{"name":"snowalker","age":"18"}}
复制代码
具体访问效果截图如下:
可以看到,我们的feign客户端成功的发起了对远程资源的访问。
PS: 本文涉及到的源码已经发布到笔者的github,感兴趣的同学可以自行下载体验。
小结
本文主要是实战,目的为整合纯Spring Boot与Feign,并进行一次尝鲜式的测试。在实战中,需要根据不同的远程接口对Feign客户端做对应的定义,但总的来讲,这种开发方式极大的提升了外部接口的接入速率,对于提升开发效率、增加代码的优雅程度都大有裨益。
立个flag,后面的文章中,我们将对Feign是如何调用远程资源的机理进行深入的分析。毕竟要知其然,还要知其所以然。