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; } }
·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
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(); } }
通过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; }
Feign中的其他配置也是通过Feign.builder()之后的对象进行设置的。
设置自定义编码解码器,如代码所示:
Feign.builder().encoder(new JacksonEncoder()).decoder(new JacksonDecoder())
设置日志信息:
设置超时时间:
设置请求拦截器:
设置调用客户端组件:
设置重试机制:
11