SpringCloud如何利用Feign訪問外部http請求
Feign訪問外部http請求
大家好,目前接手了一個項目,具體的邏輯并不復雜,主要是一個"中間商"角色, 比如客戶端通過我訪問高德地圖API,就不需要帶秘鑰,直接帶高德API所需的入?yún)⒑蛈rl后綴,就可以訪問。
目前遇到這樣一個問題,項目架構(gòu)師要求所有的項目自己寫的htttpClintUtils或者其他工具,需要替換到feign的形式來完成調(diào)用,但是,目前這個項目訪問外部的http接口很多,比如,提供的高德服務(wù)就有10多種,一共有大幾十類型,這樣的話,如果按照以前的方式,一個接口指定一個高德子服務(wù),那豈不是要累死 = =!
累死人的寫法:(僅參考)
@FeignClient(value = "test",url = "http://ip:port")
public interface TestFeign {
? ? /**
? ? ?* @return 高德服務(wù)接口
? ? ?* @description 訪問高德地理編碼服務(wù)
? ? ?*/
? ? @PostMapping(value = "/Amap/geo")
? ? Object geo(@RequestBody GeoEntity entity);
?
? ? /**
? ? ?* @return 高德服務(wù)接口
? ? ?* @description 訪問高德逆地理編碼服務(wù)
? ? ?*/
? ? @PostMapping(value = "/Amap/regeo")
? ? Object regeo(@RequestBody RegeoEntity entity);??
? ? .........
? ? ...........
}然后如果我除了高德服務(wù)還有其他外部服務(wù),并且其他外部服務(wù)下的子接口,不一定就兩個,那這樣寫的話,要頭大死,并且這樣的寫法,在服務(wù)的內(nèi)部,不能做秘鑰和權(quán)限的動態(tài)配置,只能在url上做指定,比較笨拙,所以就需要一種可以靈活訪問外部httpClient的Feign接口,只需要我指定一個url,指定下提交的post數(shù)據(jù),就可以得到返回結(jié)果,豈不是美滋滋?
話不多說,先上pom.xml
?<dependency> ? ? ? ? ? ? <groupId>org.springframework.cloud</groupId> ? ? ? ? ? ? <artifactId>spring-cloud-starter-openfeign</artifactId> ? ? ? ? ? ? <version>2.0.1.RELEASE</version> ? ? ? ? </dependency> ? ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.springframework.cloud</groupId> ? ? ? ? ? ? <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> ? ? ? ? ? ? <version>2.0.1.RELEASE</version> ? ? ? ? </dependency> ? ? ? ? ? <!-- 引入 httpclient --> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.apache.httpcomponents</groupId> ? ? ? ? ? ? <artifactId>httpclient</artifactId> ? ? ? ? </dependency> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>com.netflix.feign</groupId> ? ? ? ? ? ? <artifactId>feign-httpclient</artifactId> ? ? ? ? ? ? <version>8.18.0</version> ? ? ? ? </dependency>
前兩個是feign和服務(wù)降級用到的包,后兩個是用Apache Http替換原生的feign-http-client用來提供連接池等功能。
bootstap.yml 部分配置
feign: ? httpclient: ? ? enabled: true ? hystrix: ? ? enabled: true hystrix: ? command: ? ? default: ? ? ? execution: ? ? ? ? isolation: ? ? ? ? ? thread: ? ? ? ? ? ? timeoutInMilliseconds: 3000 ?#降級超時時間,我設(shè)置為3秒。 feign.retry默認超時時間是5s.
設(shè)置了個降級超時時間,還有啟動了feign訪問外部httpClient配置和服務(wù)降級配置。
在spingbootApplication啟動類上增加注解
@EnableFeignClients @EnableHystrix
代碼部分:
public interface HttpRequestFeign {?
? ? @RequestLine("GET")
? ? String sendGetRequest(URI baseUri);
?
? ? @RequestLine("POST")
? ? String sendPostRequest(URI baseUri, Map map);
}調(diào)用部分,這里我在我的BaseController構(gòu)造注解,其他服務(wù)Controller繼承,提供調(diào)用能力:
?@Autowired
? ? public BaseController(Decoder decoder, Encoder encoder) {
? ? ? ? httpRequestFeign = Feign.builder().encoder(encoder).decoder(decoder)
? ? ? ? ? ? ? ? .target(Target.EmptyTarget.create(HttpRequestFeign.class));?
? ? }
?protected String httpPostSend( String url, Map map) {
? ? ? ? String response = "";
? ? ? ? try {
? ? ? ? ? ? response = httpRequestFeign.sendPostRequest(new URI(url), map);
? ? ? ? ? ? logger.info("調(diào)用外部服務(wù)返回的數(shù)據(jù)為->{}", response);
? ? ? ? ? ? // 這里改成重試的超時異常
? ? ? ? } catch (RetryableException a) {
? ? ? ? ? ? logger.error("調(diào)用外部服超時錯誤->{}", response);
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? logger.error("調(diào)用外部服異常錯誤->{}", response);
? ? ? ? }
? ? ? ? return response;
? ? }這里只列舉了Post的,Get方式,就不用了攜帶map參數(shù)了。
然后在你的Controller層增加降級@HystrixCommand注解,并指定降級方法:
?@HystrixCommand(fallbackMethod = "fallback")
?@PostMapping(value = "/1_0_0/{subServer}", produces = "application/json;charset=UTF-8")
?public Object send(@RequestBody Map<String, Object> map, @PathVariable String subServer) {
?
.......................
....................?
?
?private Object fallback(Map<String, String> map, String subserver, Throwable e) {
? ? ? ? logger.error("xxx服務(wù)發(fā)生問題,入?yún)?{},地址:{}", map, subserver);
? ? ? ? return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), ERROR_MSG + e.toString());
? ? }在send方法里可以自行進行拼接url,而Map就是傳遞給第三方服務(wù)的數(shù)據(jù)。
FeignClient外部http請求
springboot 4.0.0
pom.xml 引入openfeign 2.0.2
<dependencyManagement> ?? ??? ?<dependencies> ?? ??? ??? ?<dependency> ?? ??? ??? ??? ?<groupId>org.springframework.cloud</groupId> ?? ??? ??? ??? ?<artifactId>spring-cloud-openfeign</artifactId> ?? ??? ??? ??? ?<version>2.0.2.BUILD-SNAPSHOT</version> ?? ??? ??? ??? ?<type>pom</type> ?? ??? ??? ??? ?<scope>import</scope> ?? ??? ??? ?</dependency> ?? ??? ?</dependencies> ?? ?</dependencyManagement> ?? ?<dependencies> <!--外部http請求 FeignClient--> ?? ??? ?<dependency> ?? ??? ??? ?<groupId>org.springframework.cloud</groupId> ?? ??? ??? ?<artifactId>spring-cloud-starter-openfeign</artifactId> ?? ??? ?</dependency> </dependencies> <repositories> ?? ??? ?<!--外部http請求 FeignClient--> ?? ??? ?<repository> ?? ??? ??? ?<id>spring-snapshots</id> ?? ??? ??? ?<name>Spring Snapshots</name> ?? ??? ??? ?<url>https://repo.spring.io/libs-snapshot</url> ?? ??? ??? ?<snapshots> ?? ??? ??? ??? ?<enabled>true</enabled> ?? ??? ??? ?</snapshots> ?? ??? ?</repository> ?? ?</repositories>
啟動類 添加注解@EnableFeignClients
@SpringBootApplication
@MapperScan("com.sichuang.repository.dao")//將項目中對應的mapper類的路徑加進來就可以了
@ServletComponentScan
@EnableFeignClients
public class RepositoryApplication extends SpringBootServletInitializer{
?? ?public static void main(String[] args) {
?? ??? ?SpringApplication.run(RepositoryApplication.class, args);
?? ?}
?? ?@Override
?? ?protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
?? ??? ?// TODO Auto-generated method stub
// ? ? ?return super.configure(builder);
?? ??? ?return builder.sources(RepositoryApplication.class);
?? ?}
}外部接口類。調(diào)用方式同service
@RequestParam 參數(shù)注解
produces = MediaType.APPLICATION_JSON_UTF8_VALUE 返回json參數(shù)
package com.sichuang.repository.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
/**
?* 對接接口
?*
?* @author xs
?* @date 2018/10/8 9:08
?*/
@FeignClient(url = "${url}", name = "Ewaytec2001API")
public interface Ewaytec2001API {
? ? /**
? ? ?*/
? ? @GetMapping(value = "${url}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
? ? String getEmployeeInfo(@RequestParam("id") int id, @RequestParam("sign") String sign);
}以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java之Springcloud Gateway內(nèi)置路由案例講解
這篇文章主要介紹了Java之Springcloud Gateway內(nèi)置路由案例講解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08
Java多線程 Callable、Future 和FutureTask
這篇文章主要介紹Java多線程中的 Callable、Future 以及FutureTask,下面文章圍繞Java多線程的相關(guān)資料展開全文詳細內(nèi)容,需要的朋友可以參考一下2021-10-10
Java ArrayList集合詳解(Java動態(tài)數(shù)組)
這篇文章主要介紹了Java ArrayList集合詳解(Java動態(tài)數(shù)組),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
Java實現(xiàn)Excel文件轉(zhuǎn)PDF(無水印無限制)
這篇文章主要為大家詳細介紹了如何利用Java語言實現(xiàn)Excel文件轉(zhuǎn)PDF的效果,并可以無水印、無限制。文中的示例代碼講解詳細,需要的可以參考一下2022-06-06

