@RequestLine的使用及配置
@RequestLine与其它请求不同,只需要简单写请求方式和路径就能达到请求其它服务的目的。
@FeignClient(value = "feign-server",configuration = FeignConfig.class) //需要一个配置文件
public interface TestService {
@RequestLine("POST /feign/test") //对应请求方式和路径
String feign(@RequestBody UserDO userDO);
}
@EnableFeignClients
@SpringBootConfiguration
public class FeignConfig {
@Bean
public Contract contract(){
return new feign.Contract.Default();
}
}
自定义配置feignClient并使用@RequestLine问题
之前在项目里请求三方服务时,使用的是restTemplate,其在组装参数上略显麻烦,其实我们可以使用openFeign自动的组件去请求三方服务,实现更加优雅
步骤
依赖导入这些就不说了,直接进入正题
1. 定义请求接口
其写法和@FeignClient类似,但要使用来自于openFeign的核心注解@RequestLine,而不是来自MVC的注解@PostMapping、@GetMapping。
public interface DhlApi {
@RequestLine("GET {url}")
@Headers({
"Content-Type: application/json",
})
DhlActiveQueryResponse queryTrack(@Param("url") String url);
}
2. 定义配置文件,配置请求接口
@Configuration
public class TestFeignConfig {
// 获取配置文件,自己用的是apollo
@ApolloJsonValue("${test.api}")
private TestISVInfo testIsvInfo;
@Bean
public TestISVInfo testIsvApi() throws Exception {
return Feign.builder()
.client(client())
.encoder(new FastJsonEncoder())
.decoder(new FastJsonDecoder())
// 连接超时30秒,读取超时60秒
.options(new Request.Options(30 * 1000, 60 * 1000))
// 配置日志
.logger(new Slf4jLogger(TestFeignConfig.class))
// 发生IO异常重试5次,每次重试最小间隔100ms,最大间隔1s,随着重试次数递增
.retryer(new Retryer.Default())
.logLevel(Logger.Level.FULL)
// 注册feign
.target(TestIsv.class, testIsvInfo.getDomainUrl());
}
private Client client() throws Exception {
// 信任策略,设置为无条件信任
TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
// 设置ssl配置,由于我们采用无条件信任,所以也不需要加载证书
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
// 使用NoopHostnameVerifier关闭ssl的校验
SSLConnectionSocketFactory sslScoketFactory = new SSLConnectionSocketFactory(sslContext,
NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> socketFactoryRegistry =
RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", sslScoketFactory)
.register("http", new PlainConnectionSocketFactory())
.build();
PoolingHttpClientConnectionManager connectionManager =
new PoolingHttpClientConnectionManager(socketFactoryRegistry);
CloseableHttpClient httpClient = HttpClients
.custom()
.setMaxConnTotal(20)
.setMaxConnPerRoute(20)
.setSSLSocketFactory(sslScoketFactory)
.evictExpiredConnections()
.evictIdleConnections(20, TimeUnit.SECONDS)
.setConnectionManager(connectionManager).build();
return new ApacheHttpClient(httpClient);
}
}
结束!就这么简单。
为什么用的是@RequestLine
这和open-feign的Contract设计有关系,Contract是一个注解解析接口,它决定了接口可以使用什么注解转换到http请求。open-feign在使用@FeignClient的情况下,使用的是SpringMvcContract,它使得被@FeignClient修饰的接口,可以使用@GetMapping,@PostMapping等Spring Mvc注解。
如果我们要使用@RequestLine,则需要替换open-Feign的MVC解析器,像这样
// 在feign上写上配置
@FeignClient(name = "test-center", configuration = TestFeignConfig .class)
// 配置类
@Configuration
public class TestFeignConfig {
// 配置feign的注释解析器为feign默认解析器而不是mvc解析器
@Bean
public Contract feignContract() {
return new feign.Contract.Default();
}
}
如果我们不单独配置,则会使用FeignClientsConfiguration中默认配置的SpringMvcContract。
@Bean
@ConditionalOnMissingBean
public Contract feignContract(ConversionService feignConversionService) {
return new SpringMvcContract(this.parameterProcessors, feignConversionService);
}
那为什么我们通过@Bean形式注册的feign客户端就能直接使用@RequestLine呢。因为@Bean形式注册的feign客户端不会使用这个配置,而是使用open-feign的默认Contract
打开这个类,我们可以看到它的描述,它的作用可以分为两个:
- 定义哪些注解在feign接口上是有校的
- 定义接口的动作
它的processAnnotationOnMethod(MethodMetadata,Annotation, Method)方法,作用就是解析在feign接口上的注解,并转化为发送http请求需要的数据。
方法代码:
该类的该方法,只会处理@Body、@RequestLine和@Header 3个注解,如果不是的话,会直接跳过。 针对@RequestLIne:
获取RequstLine的value,使用正则表达式判断值是否是“GET xxxx”这类的形式,不是就报错。解析到之后,获得方法和uri设置进RequestTemplate中针对@Body
将@Body中的值塞到RequestTemplate的body中针对@Headers
获取@Header中的值,进行解析,并放入RequestTemplate的Header中
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。