@FeignClient 实现简便http请求封装方式
时间:2023-01-04 09:37:24|栏目:JAVA代码|点击: 次
@FeignClient实现http请求封装
我们一般在代码中调用http请求时,都是封装了http调用类,底层自己定义请求头,在写的时候,也是需要对返回的值进行json解析,很不方便。
name
:name属性会作为微服务的名称,用于服务发现url
:host的意思,不用加http://前缀decode404
:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
使用流程
(1)创建接口类(FeignApi),来统一规范需要调用的第三方接口
@FeignClient(name = "aaa", url = "localhost:8080", decode404 = true) public interface FeignApi { /** * http请求 */ @PostMapping("/api/xxxx/baiduaaa") ResponseResult<ResponseVo> getSomeMoneyForYourSelfAAA(@RequestBody AAAParam param); /** * 模仿上面写的Get方式请求 */ @GetMapping("/api/xxxx/baidubbb") ResponseResult<ResponseVo> getSomeMoneyForYourSelfBBB(@RequestBody AAAParam param); }
(2)在启动类加上注解,会去扫包注册Bean
@EnableFeignClients(basePackages = {"com.aaa"})
(3)业务代码调用处:
ResponseResult<ResponseVo> response = pmsFeignApi.getSomeMoneyForYourSelfAAA(param);
将http请求封装为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); /** * 最大重试次数 */ 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间隔时间 */ 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; }