SpringBoot2.x直接整合Feign实现远程接口调用[尝鲜]

3,674 阅读3分钟

之前也用过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是如何调用远程资源的机理进行深入的分析。毕竟要知其然,还要知其所以然。