@FeignClient?實(shí)現(xiàn)簡(jiǎn)便http請(qǐng)求封裝方式
@FeignClient實(shí)現(xiàn)http請(qǐng)求封裝
我們一般在代碼中調(diào)用http請(qǐng)求時(shí),都是封裝了http調(diào)用類,底層自己定義請(qǐng)求頭,在寫的時(shí)候,也是需要對(duì)返回的值進(jìn)行json解析,很不方便。
name
:name屬性會(huì)作為微服務(wù)的名稱,用于服務(wù)發(fā)現(xiàn)url
:host的意思,不用加http://前綴decode404
:當(dāng)發(fā)生http 404錯(cuò)誤時(shí),如果該字段位true,會(huì)調(diào)用decoder進(jìn)行解碼,否則拋出FeignException
使用流程
(1)創(chuàng)建接口類(FeignApi),來統(tǒng)一規(guī)范需要調(diào)用的第三方接口
@FeignClient(name = "aaa", url = "localhost:8080", decode404 = true) public interface FeignApi { ? ? /** ? ? ?* http請(qǐng)求 ? ? ?*/ ? ? @PostMapping("/api/xxxx/baiduaaa") ? ? ResponseResult<ResponseVo> getSomeMoneyForYourSelfAAA(@RequestBody AAAParam param); ? ?? ? ? /** ? ? ?* 模仿上面寫的Get方式請(qǐng)求 ? ? ?*/ ? ? @GetMapping("/api/xxxx/baidubbb") ? ? ResponseResult<ResponseVo> getSomeMoneyForYourSelfBBB(@RequestBody AAAParam param); }
(2)在啟動(dòng)類加上注解,會(huì)去掃包注冊(cè)Bean
@EnableFeignClients(basePackages = {"com.aaa"})
(3)業(yè)務(wù)代碼調(diào)用處:
ResponseResult<ResponseVo> response = pmsFeignApi.getSomeMoneyForYourSelfAAA(param);
將http請(qǐng)求封裝為FeignClient
1.配置攔截器
import java.io.IOException; import java.io.InterruptedIOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; public class OkHttpRetryInterceptor implements Interceptor {undefined ? ? private static final Logger LOGGER = LoggerFactory.getLogger(OkHttpRetryInterceptor.class); ? ? /** ? ? ?* 最大重試次數(shù) ? ? ?*/ ? ? private int ? ? ? ? ? ? ? ? executionCount; ? ? /** ? ? ?* 重試的間隔 ? ? ?*/ ? ? private long ? ? ? ? ? ? ? ?retryInterval; ? ? OkHttpRetryInterceptor(Builder builder) {undefined ? ? ? ? this.executionCount = builder.executionCount; ? ? ? ? this.retryInterval = builder.retryInterval; ? ? } ? ? @Override ? ? public Response intercept(Chain chain) throws IOException {undefined ? ? ? ? Request request = chain.request(); ? ? ? ? Response response = doRequest(chain, request); ? ? ? ? int retryNum = 0; ? ? ? ? while ((response == null || !response.isSuccessful()) && retryNum <= executionCount) {undefined ? ? ? ? ? ? LOGGER.info("intercept Request is not successful - {}", retryNum); ? ? ? ? ? ? final long nextInterval = getRetryInterval(); ? ? ? ? ? ? try {undefined ? ? ? ? ? ? ? ? LOGGER.info("Wait for {}", nextInterval); ? ? ? ? ? ? ? ? Thread.sleep(nextInterval); ? ? ? ? ? ? } catch (final InterruptedException e) {undefined ? ? ? ? ? ? ? ? Thread.currentThread().interrupt(); ? ? ? ? ? ? ? ? throw new InterruptedIOException(); ? ? ? ? ? ? } ? ? ? ? ? ? retryNum++; ? ? ? ? ? ? // retry the request ? ? ? ? ? ? response = doRequest(chain, request); ? ? ? ? } ? ? ? ? return response; ? ? } ? ? private Response doRequest(Chain chain, Request request) {undefined ? ? ? ? Response response = null; ? ? ? ? try {undefined ? ? ? ? ? ? response = chain.proceed(request); ? ? ? ? } catch (Exception e) {undefined ? ? ? ? } ? ? ? ? return response; ? ? } ? ? /** ? ? ?* retry間隔時(shí)間 ? ? ?*/ ? ? public long getRetryInterval() {undefined ? ? ? ? return this.retryInterval; ? ? } ? ? public static final class Builder {undefined ? ? ? ? private int ?executionCount; ? ? ? ? private long retryInterval; ? ? ? ? public Builder() {undefined ? ? ? ? ? ? executionCount = 3; ? ? ? ? ? ? retryInterval = 1000; ? ? ? ? } ? ? ? ? public Builder executionCount(int executionCount) {undefined ? ? ? ? ? ? this.executionCount = executionCount; ? ? ? ? ? ? return this; ? ? ? ? } ? ? ? ? public Builder retryInterval(long retryInterval) {undefined ? ? ? ? ? ? this.retryInterval = retryInterval; ? ? ? ? ? ? return this; ? ? ? ? } ? ? ? ? public OkHttpRetryInterceptor build() {undefined ? ? ? ? ? ? return new OkHttpRetryInterceptor(this); ? ? ? ? } ? ? } }
2.注入feignClient bean
import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.netflix.feign.FeignAutoConfiguration; import org.springframework.cloud.netflix.feign.ribbon.CachingSpringLoadBalancerFactory; import org.springframework.cloud.netflix.feign.ribbon.LoadBalancerFeignClient; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import feign.Client; import feign.Feign; import feign.ribbon.RibbonClient; import okhttp3.ConnectionPool; import okhttp3.OkHttpClient; @Configuration @ConditionalOnMissingBean({ OkHttpClient.class, Client.class }) @ConditionalOnClass(Feign.class) @AutoConfigureBefore(FeignAutoConfiguration.class) public class FeignClientConfig {undefined ? ? @Value("${feign.invoke.http.connectTimeoutMillis:3000}") ? ? private int connectTimeoutMillis; ? ? @Value("${feign.invoke.http.readTimeoutMillis:10000}") ? ? private int readTimeoutMillis; ? ? @Value("${feign.invoke.http.retryExecutionCount:3}") ? ? private int retryExecutionCount; ? ? @Value("${feign.invoke.http.retryInterval:1000}") ? ? private int retryInterval; ? ? public FeignClientConfig() {undefined ? ? } ? ? @Bean ? ? @ConditionalOnMissingBean({ OkHttpClient.class }) ? ? public OkHttpClient okHttpClient() {undefined ? ? ? ? OkHttpRetryInterceptor okHttpRetryInterceptor = new OkHttpRetryInterceptor.Builder().executionCount(retryExecutionCount) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .retryInterval(retryInterval) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .build(); ? ? ? ? return new OkHttpClient.Builder().retryOnConnectionFailure(true) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.addInterceptor(okHttpRetryInterceptor) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.connectionPool(new ConnectionPool()) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.connectTimeout(connectTimeoutMillis, TimeUnit.MILLISECONDS) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.readTimeout(readTimeoutMillis, TimeUnit.MILLISECONDS) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.build(); ? ? } ? ? @Bean ? ? @ConditionalOnMissingBean({ Client.class }) ? ? public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {undefined ? ? ? ? if (cachingFactory == null) {undefined ? ? ? ? ? ? RibbonClient.Builder builder = RibbonClient.builder(); ? ? ? ? ? ? builder.delegate(new feign.okhttp.OkHttpClient(this.okHttpClient())); ? ? ? ? ? ? return builder.build(); ? ? ? ? } else {undefined ? ? ? ? ? ? return new LoadBalancerFeignClient(new feign.okhttp.OkHttpClient(this.okHttpClient()), cachingFactory, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?clientFactory); ? ? ? ? } ? ? } }
3.配置pom引用
?<dependency> ?<groupId>io.github.openfeign</groupId> ?<artifactId>feign-ribbon</artifactId> ?<version>9.0.0</version> ?</dependency>
4.寫feignClient
@FeignClient(name = "xxxApi", url = "${xxx.url}") public interface xxxClient { ? ? ?@RequestMapping(method = RequestMethod.POST) ? ? ?public String createLink(@RequestHeader(name = "accessKey", defaultValue = "xx") String accessKey, ? ? ? ? ?@RequestHeader(name = "accessSecret") String accessSecret, @RequestBody String linkConfig); }
5.寫熔斷器
? ? @Autowired ? ? private xxxClient xxClient; ? ? @HystrixCommand(commandKey = "xxxLink", fallbackMethod = "xxxError", commandProperties = { @HystrixProperty(name = "requestCache.enabled", value = "true"), ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000") }) ? ? public String xxLink(String accessKey, String accessSecret, String linkConfig) { ? ? ? ? LOG.info("[xxLink] ?LinkConfig is {}", linkConfig); ? ? ? ? String resp = xxxClient.createLink(accessKey, accessSecret, linkConfig); ? ? ? ? LOG.info("[xxxLink] response : {}", resp); ? ? ? ? return resp; ? ? }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java實(shí)現(xiàn)裝飾器模式(Decorator Pattern)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)裝飾器模式Decorator Pattern,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-10-10Spring cloud Gateway簡(jiǎn)介及相關(guān)配置方法
這篇文章主要介紹了Spring cloud Gateway簡(jiǎn)介及相關(guān)配置方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04Springboot中的@ComponentScan注解使用解析
這篇文章主要介紹了Springboot中的@ComponentScan注解使用解析,@ComponentScan用于類或接口上主要是指定掃描路徑,spring會(huì)把指定路徑下帶有指定注解的類注冊(cè)到IOC容器中,需要的朋友可以參考下2024-01-01SpringSecurity+jwt+redis基于數(shù)據(jù)庫(kù)登錄認(rèn)證的實(shí)現(xiàn)
本文主要介紹了SpringSecurity+jwt+redis基于數(shù)據(jù)庫(kù)登錄認(rèn)證的實(shí)現(xiàn),其中也涉及到自定義的過濾器和處理器,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09多模塊項(xiàng)目使用枚舉配置spring-cache緩存方案詳解
這篇文章主要為大家介紹了多模塊項(xiàng)目使用枚舉配置spring-cache緩存的方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05