@FeignClient实现http请求封装
我们一般在代码中调用http请求时,都是封装了http调用类,底层自己定义请求头,在写的时候,也是需要对返回的值进行json解析,很不方便。
-
name
:name属性会作为微服务的名称,用于服务发现 -
url
:host的意思,不用加http://前缀 -
decode404
:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
使用流程
(1)创建接口类(FeignApi),来统一规范需要调用的第三方接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@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
1
|
@EnableFeignClients (basePackages = { "com.aaa" }) |
(3)业务代码调用处:
1
|
ResponseResult<ResponseVo> response = pmsFeignApi.getSomeMoneyForYourSelfAAA(param); |
将http请求封装为FeignClient
1.配置拦截器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
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引用
1
2
3
4
5
|
< dependency > < groupId >io.github.openfeign</ groupId > < artifactId >feign-ribbon</ artifactId > < version >9.0.0</ version > </ dependency > |
4.写feignClient
1
2
3
4
5
6
|
@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.写熔断器
1
2
3
4
5
6
7
8
9
10
|
@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; } |
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/qq_40555976/article/details/123005668