将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 {


    private static final Logger LOGGER = LoggerFactory.getLogger(OkHttpRetryInterceptor.class);


    /**
     * 最大重试次数
     */
    private int                 executionCount;


    /**
     * 重试的间隔
     */
    private long                retryInterval;


    OkHttpRetryInterceptor(Builder builder) {
        this.executionCount = builder.executionCount;
        this.retryInterval = builder.retryInterval;
    }


    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response = doRequest(chain, request);
        int retryNum = 0;
        while ((response == null || !response.isSuccessful()) && retryNum <= executionCount) {
            LOGGER.info("intercept Request is not successful - {}", retryNum);
            final long nextInterval = getRetryInterval();
            try {
                LOGGER.info("Wait for {}", nextInterval);
                Thread.sleep(nextInterval);
            } catch (final InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new InterruptedIOException();
            }
            retryNum++;
            // retry the request
            response = doRequest(chain, request);
        }
        return response;
    }


    private Response doRequest(Chain chain, Request request) {
        Response response = null;
        try {
            response = chain.proceed(request);
        } catch (Exception e) {
        }
        return response;
    }


    /**
     * retry间隔时间
     */
    public long getRetryInterval() {
        return this.retryInterval;
    }


    public static final class Builder {


        private int  executionCount;
        private long retryInterval;


        public Builder() {
            executionCount = 3;
            retryInterval = 1000;
        }


        public Builder executionCount(int executionCount) {
            this.executionCount = executionCount;
            return this;
        }


        public Builder retryInterval(long retryInterval) {
            this.retryInterval = retryInterval;
            return this;
        }


        public OkHttpRetryInterceptor build() {
            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 {


    @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() {
    }


    @Bean
    @ConditionalOnMissingBean({ OkHttpClient.class })
    public OkHttpClient okHttpClient() {
        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) {
        if (cachingFactory == null) {
            RibbonClient.Builder builder = RibbonClient.builder();
            builder.delegate(new feign.okhttp.OkHttpClient(this.okHttpClient()));
            return builder.build();
        } else {
            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;
    }


参考博文:
http://okeeper.leanote.com/post/%E4%BD%BF%E7%94%A8Spring-Cloud-Feign%E4%BD%9C%E4%B8%BAHTTP%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%B0%83%E7%94%A8%E8%BF%9C%E7%A8%8BHTTP%E6%9C%8D%E5%8A%A1
https://segmentfault.com/a/1190000009071952 Alan的回答
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中封装HTTP请求可以使用RestTemplate或者Feign来实现。下面分别介绍这两种方式的使用: 1. 使用RestTemplate: RestTemplate是Spring提供的一个HTTP客户端工具,可以发送HTTP请求并处理响应。以下是一个简单的封装示例: ```java import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; public class HttpUtils { private static final RestTemplate restTemplate = new RestTemplate(); public static <T> T sendGetRequest(String url, Class<T> responseType) { HttpHeaders headers = new HttpHeaders(); headers.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE); HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(headers); ResponseEntity<T> responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity, responseType); return responseEntity.getBody(); } public static <T> T sendPostRequest(String url, Object request, Class<T> responseType) { HttpHeaders headers = new HttpHeaders(); headers.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE); headers.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); HttpEntity<Object> entity = new HttpEntity<>(request, headers); ResponseEntity<T> responseEntity = restTemplate.exchange(url, HttpMethod.POST, entity, responseType); return responseEntity.getBody(); } } ``` 上述代码中,我们定义了一个HttpUtils类,提供了sendGetRequest和sendPostRequest两个方法,分别用于发送GET和POST请求,并且可以指定返回结果的类型。 2. 使用FeignFeign是一个声明式的Web服务客户端,可以通过注解方式定义和实现HTTP请求。以下是一个简单的封装示例: 1)首先,在Spring Boot的启动类上添加@EnableFeignClients注解: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableFeignClients public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 2)然后,创建一个Feign客户端接口: ```java import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @FeignClient(name = "example", url = "http://example.com") public interface HttpClient { @GetMapping("/api/get") String get(); @PostMapping("/api/post") String post(@RequestBody Object request); } ``` 在上述代码中,我们使用@FeignClient注解指定了服务名和请求URL。 3)最后,在需要使用HTTP请求的地方注入HttpClient接口并调用相应的方法: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class MyService { private final HttpClient httpClient; @Autowired public MyService(HttpClient httpClient) { this.httpClient = httpClient; } public String doHttpRequest() { String response = httpClient.get(); // 处理响应 return response; } } ``` 在上述代码中,我们通过@Autowired注解将HttpClient接口注入到MyService中,并调用需要的方法来发送HTTP请求。 以上是在Spring Boot中封装HTTP请求的两种常用方式,你可以根据具体需求选择使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值