声明式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

猜你喜欢

转载自www.cnblogs.com/xc-xinxue/p/12455436.html