zoukankan      html  css  js  c++  java
  • 声明式REST客户端Feign(一)

    JAVA项目中接口调用怎么做?

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

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

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

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

    上面介绍的是最常见的几种调用接口的方法,我们下面要介绍的方法比上面的更简单, 方便, 它就是Feign。


    1.使用Feign调用服务接口

    Feign是一个声明式的REST客户端,它能让REST调用更加简单。Feign提供了Http请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。

    而Feign则会完全代理Http请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Spring Cloud对Feign进行了封装,使其支持SpringMVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。

    1.1 在Spring Cloud中集成Feign

    简单,加入Feign的依赖,如代码所示:

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>

    在启动类上加@EnableFeignClients注解,如果你的Feign接口定义跟你的启动类不在一个包名下,还需要指定扫描的包名@EnableFeignClients(basePackages=”com.fangjia.api.client"”)

    1.2 使用Feign调用接口

    定义一个Feign的客户端,以接口形式存在,代码如下:

    //标识当前是一个Feign的客户端,value属性是对应的服务名称,也就是你需要调用哪个服务中的接口,path就是接口中URI统一的前缀
    @FeignClient(value="fsh-house",path="/house")
    public interface HouseRemoteClient {
    //定义方法时直接复制接口的定义即可
        @GetMapping("/hello")
        String hello();
    }

    定义方法时直接复制接口的定义即可,当然还有一种做法,就是将接口单独抽出来定义,然后在Controller中实现接口。在调用的客户端中也实现了接口,从而达到接口共用的目的。

    这里的做法是不公用的,单独创建一个API Client的公共项目,基于约定的模式,每写一个接口就要对应写一个调用的Client,后面打成公共的jar,这样无论是哪个项目需要调用接口,引入公共接口SDKjar即可,不用重新定义一遍了。

    定义之后可以直接通过注入HouseRemoteClient来调用,对于开发人员来说就像调用本地方法一样。

    接下来改造之前fangjia-fsh-substitution-service中调用hello接口的调用方法,代码如下:

    @Autowired
        private HouseRemoteClient houseRemoteClient;
        
        @GetMapping("/callHello")
        public String callHello() {
            //return restTemplate.getForObject("http://fsh-house/house/hello", String.class);
    //String result=restTemplate.getForObject("http://fsh-house/house/hello", String.class);
            String result=houseRemoteClient.hello();
            System.out.println("调用结果:"+result);
            return result;
        }

    通过跟注释掉的代码相比可以发现,我们的调用方式变得越来越简单了,从最开始的指定地址,到后面通过Eureka中的服务名称来调用,到现在直接通过定义接口来调用。


    2. 自定义Feign的配置

    2.1 日志配置

    有时候我们遇到bug,比如接口调用失败了、参数没收到等问题,或者想看看调用性能,就需要配置Feign的日志了,以此让Feign把请求信息输出来。

    定义一个配置类,代码如下:

    @Configuration
    public class FeignConfiguration {
    /**
     * 日志级别
     * @return
     */
        @Bean
        Logger.Level feignLoggerLevel(){
            return Logger.Level.FULL;
        }
    }
    通过源码可以看到日志登记有4种,分别是:

    ·NONE:不输出日志

    ·BASIC:只输出请求方法的URL和响应的状态码以及接口执行的时间

    ·HEADERS:将BASIC信息和请求头信息输出

    ·FULL:输出完整的请求信息

    配置类建好后,我们需要在Feign Client中的@FeignClient注解中指定使用的配置类,如代码所示:

    @FeignClient(value="fsh-house",path="/house",configuration=FeignConfiguration.class)
    public interface HouseRemoteClient{
    //...
    }

    在配置文件中执行Client的日志级别才能正常输出日志,格式是”logging.level.client类地址=级别”。如代码所示:

    logging.level.com.fangjia.api.client.fsh.house.HouseRemoteClient=DEBUG
    最好后通过Feign调用我们的hello接口,就可以看出控制台会输出的调用信息了。


    2.2 契约配置

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

    @Configuration
    public class FeignConfiguration {
        
        @Bean
        public Contract feignContract() {
            return new feign.Contract.Default();
        }
    }

    当你配置使用默认的契约后,之前定义的Client就用不了,之前上面的注解是Spring MVC的注解。


    2.3 Basic认证配置

    通常我们调用的接口都是有权限控制的,很多时候可能认证的值是通过参数去传递的,还有就是通过请求头去传递认证信息,比如Basic认证方式。在Feign中我们可以直接配置Basic认证,如代码所示:

    @Configuration
    public class FeignConfiguration {
        
        @Bean
        public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
            return new BasicAuthRequestInterceptor("user", "password");
        }
    }

    或者你可以自定义属于自己的认证方式,其实就是自定义一个请求拦截器。在请求之前做认证操作,然后往请求头中设置认证之后的信息。通过实现RequestInterceptor接口来自定义认证方式,如代码所示:

    public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
    
        @Override
        public void apply(RequestTemplate template) {
            //业务逻辑
        }
    }
    然后

    我们将配置改成自定义的就可以了,这样当Feign去请求接口的时候,每次请求之前都会进入FeignBasicAuthRequestInterceptor的apply方法中,在其里面就可以做属于你的逻辑了,如代码所示:

    @Configuration
    public class FeignConfiguration{
        @Bean
        public FeignBasicAuthRequestInterceptor basicAuthRequestInterceptor(){
            return new FeignBasicAuthRequestInterceptor();
        } 
    }
    2.4 超时时间配置

    通过Options可以配置连接超时时间和读取超时时间,如代码所示:

    @Configuration
    public class FeignConfiguration{
        @Bean
        public Request.Options options(){
        return new Request.Options(5000,10000);
    }
    }

    2.5 客户端组件配置

    Feign中默认使用HttpClient来进行接口调用,我们可以集成别的组件来替换掉HttpClient,比如OkHttp。

    配置OkHttp只需要加入OkHttp的依赖,如代码所示:

    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-okhttp</artifactId>
        <version>10.8</version>
    </dependency>

    然后修改配置,将Feign的HttpClient禁用,启用OkHttp,配置如下:

    #feign使用okhttp
    feign.httpclient.enabled=false
    feign.okhttp.enabled=true

    2.6 GZIP压缩配置

    我们可以配置GZIP来压缩数据:

    feign.compression.request.enabled=true

    feign.compression.response.enabled=true

    还可以配置压缩的类型、最小压缩值的标准:

    feign.compression.request.mime-types=text/xml,application/xml,application/json

    feign.compression.request.min-request-size=2048

    2.7 编码器解码器配置

    配置编码解码器只需要在Feign的配置类中注册Decoder和Encoder这两个类即可,如代码所示:

    @Bean
    public Decoder decoder(){
        return new MyDecoder();
    }
    
    @Bean
    public Encoder encoder(){
        return new MyEncoder();
    }


    3.脱离Spring Cloud使用Feign

    在Spring Cloud中通过集成Feign可以用很简单的方式调用其他服务提供的接口, 这 是因为Spring Cloud在底层做了很多工作, 比如支持Spring MVC注解、集成Eureka和 Ribbon。如果你目前还没用到Spring Cloud, 但是想用Feign来代替之前的接口调用方式, 这节内容将进行原生Feign框架的单独使用。

    3.1 原生注解方式

    Feign的GitHub地址:https://github.com/OpenFeign/feign

    原生的Feign是不支持Spring MVC注解的,其用的是@RequestLine注解

    3.2 构建Feign对象

    Feign通过builder模式来构建接口代理对象,可以设置解码编码器、设置日志等信息。

    我们可以写一个通用的工具类来构件对象,只要传入一个定义好的接口和URL,就可以获取这个接口的代理对象,通过代理对象调用接口中的方法即可实现远程调用。代码如下:

    public class RestApiCallUtils {
    /**
     * 获取API接口代理对象
     * @param apiType 接口类
     * @param url API地址
     * @return
     */
        public static<T> T getRestClient(Class<T> apiType,String url) {
            return Feign.builder().target(apiType,url);
        }
    }

    基于原生的调用方式来改造之前的callHello接口,首先定义一个调用的接口,如代码所示:

    //Feign原生注解定义客户端
    interface HelloRemote{
        @RequestLine("GET/house/hello")
        String hello();
    }

    改造之前的callHello接口,如代码所示:

    //Feign原生方式调用接口
    @GetMapping("/callHello")
    public String callHello(){
        HelloRemote helloRemote=Feign.builder().target(HelloRemote.class,"http://localhost:8081");
        System.out.println("调用结果"+helloRemote.hello()):
        return result;
    }
    3.3 其他配置

    Feign中的其他配置也是通过Feign.builder()之后的对象进行设置的。

    设置自定义编码解码器,如代码所示:

    Feign.builder().encoder(new JacksonEncoder()).decoder(new JacksonDecoder())

    设置日志信息:

    设置超时时间:

    设置请求拦截器:

    设置调用客户端组件:

    设置重试机制:


    11

  • 相关阅读:
    TCP和UDP协议?
    了解浏览器缓存机制吗?
    关于预检请求?
    cookie可设置哪些属性?httponly?
    http和https?
    vue自定义组件?
    实现页面回退刷新?
    vue3.0的更新和defineProperty优化?
    vue的seo问题?
    vuex组成和原理?
  • 原文地址:https://www.cnblogs.com/xc-xinxue/p/12455436.html
Copyright © 2011-2022 走看看