解決Feign調(diào)用的GET參數(shù)傳遞的問題
需求
? 在消費(fèi)方服務(wù)通過GET方式,訪問服務(wù)提供方的接口,需要傳遞多參數(shù),拆分成多個參數(shù)的方式訪問,不太適合用在該場景,需要改造成合適的方式調(diào)用服務(wù)方的接口
思考
拆分成多個參數(shù)時,若GET請求的參數(shù)超過3個及以上時,便不適用該種方式請求服務(wù),因?yàn)檫@樣傳遞參數(shù)過于臃腫,可讀性也比較差;
若改造成POST請求的方式,雖然解決參數(shù)過多的問題,但是也帶來了其他的開銷,參數(shù)被放到了body里面,然后請求到服務(wù)方提供的接口,服務(wù)方的接口也改造成了POST方式,改變了原來的GET方式調(diào)用的初衷,不太友好;
? 可以在消費(fèi)方調(diào)用Feign接口時,參數(shù)封裝到body中,在組裝Feign接口請求時,將body里面的參數(shù)取出來,轉(zhuǎn)換為GET方式請求的參數(shù),請求body的參數(shù),然后發(fā)起請求,實(shí)現(xiàn)了GET方式訪問服務(wù)方提供的接口;
以下是這三種調(diào)用方式的具體實(shí)現(xiàn),可以根據(jù)適合自己的業(yè)務(wù)場景去使用,選擇不同的方式請求調(diào)用:
GET方式請求①
請求DTO對象:
package com.springcloud.pojo;?
import java.util.Date;??
public class Requets01DTO {?
? ? private Date startTime;?
? ? private Date endTime;?
? ? private String message;
?
? ? @Override
? ? public String toString() {
? ? ? ? return "Requets01DTO{" +
? ? ? ? ? ? ? ? "startTime=" + startTime +
? ? ? ? ? ? ? ? ", endTime=" + endTime +
? ? ? ? ? ? ? ? ", message='" + message + '\'' +
? ? ? ? ? ? ? ? '}';
? ? }
?
? ? public Date getStartTime() {
? ? ? ? return startTime;
? ? }
?
? ? public void setStartTime(Date startTime) {
? ? ? ? this.startTime = startTime;
? ? }
?
? ? public Date getEndTime() {
? ? ? ? return endTime;
? ? }
?
? ? public void setEndTime(Date endTime) {
? ? ? ? this.endTime = endTime;
? ? }
?
? ? public String getMessage() {
? ? ? ? return message;
? ? }
?
? ? public void setMessage(String message) {
? ? ? ? this.message = message;
? ? }
}消費(fèi)方的請求:
? ? @Autowired
? ? GetClient01 getClient01;
?
? ? @GetMapping("/request/get/01")
? ? public String requestGetOne(Requets01DTO requets01DTO) {
? ? ? ? return getClient01.queryDataByGetRequest(requets01DTO.getStartTime(), requets01DTO.getEndTime(), requets01DTO.getMessage());
? ? }Feign接口:
package com.springcloud.service;?
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;?
import java.util.Date;
?
@FeignClient(value = "provider-8762", contextId = "GetClient01")
public interface GetClient01 {
?
? ? /**
? ? ?* GET方式請求①
? ? ?*
? ? ?* @param startTime
? ? ?* @param endTime
? ? ?* @param message
? ? ?* @return
? ? ?*/
? ? @GetMapping("/get/01")
? ? String queryDataByGetRequest(@RequestParam("startTime") Date startTime, @RequestParam("endTime") Date endTime,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@RequestParam("message") String message);
}服務(wù)提供方:
@RestController
public class RequestProviderController {
?
? ? @GetMapping("/get/01")
? ? public String queryDataByGetRequest(@RequestParam("startTime") Date startTime, @RequestParam("endTime") Date endTime,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @RequestParam("message") String message) {
? ? ? ? Requets01DTO requets01DTO = new Requets01DTO();
? ? ? ? requets01DTO.setStartTime(startTime);
? ? ? ? requets01DTO.setEndTime(endTime);
? ? ? ? requets01DTO.setMessage(message);
? ? ? ? return requets01DTO.toString();
? ? }
}請求結(jié)果截圖:

GET方式請求②
Feign調(diào)用的請求改為POST方式
消費(fèi)方的請求:
? ? @Autowired
? ? GetClient02 getClient02;
?
? ? @GetMapping("/request/get/02")
? ? public String requestGetTwo(Requets01DTO requets01DTO) {
? ? ? ? return getClient02.queryDataByGetRequest(requets01DTO);
? ? }Feign接口:
package com.springcloud.service;?
import com.springcloud.pojo.Requets01DTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
?
@FeignClient(value = "provider-8762", contextId = "GetClient02")
public interface GetClient02 {?
?
? ? /**
? ? ?* GET方式請求②(Feign調(diào)用的請求改為POST方式)
? ? ?*
? ? ?* @param requets01DTO
? ? ?* @return
? ? ?*/
? ? @PostMapping("/post/02")
? ? String queryDataByGetRequest(Requets01DTO requets01DTO);
}服務(wù)提供方:
? ? @PostMapping("/post/02")
? ? public String queryDataByGetRequest(@RequestBody Requets01DTO requets01DTO) {
? ? ? ? return requets01DTO.toString();
? ? }請求結(jié)果截圖:

GET方式請求③
組裝Feign接口請求時,將body里面的參數(shù)取出來,轉(zhuǎn)換為GET方式請求的參數(shù)
添加Feign請求的配置類:
package com.springcloud.config;?
import com.alibaba.fastjson.JSON;
import feign.Request;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
?
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.util.*;
?
@Configuration
public class FeignConfiguration implements RequestInterceptor {
?
? ? @Override
? ? public void apply(RequestTemplate requestTemplate) {
? ? ? ? ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
? ? ? ? HttpServletRequest request = attributes.getRequest();
?
? ? ? ? //填充get中的body數(shù)據(jù)轉(zhuǎn)化成query數(shù)據(jù)
? ? ? ? if (requestTemplate.method().equals(HttpMethod.GET.name()) && Objects.nonNull(requestTemplate.body())) {
? ? ? ? ? ? String json = requestTemplate.requestBody().asString();
? ? ? ? ? ? Map<String, Object> map = JSON.parseObject(json);
? ? ? ? ? ? Set<String> set = map.keySet();
? ? ? ? ? ? Iterator<String> it = set.iterator();
? ? ? ? ? ? while (it.hasNext()) {
? ? ? ? ? ? ? ? String key = it.next();
? ? ? ? ? ? ? ? Object values = map.get(key);
? ? ? ? ? ? ? ? if (Objects.nonNull(values)) {
? ? ? ? ? ? ? ? ? ? // 將body的參數(shù)寫入queries
? ? ? ? ? ? ? ? ? ? requestTemplate.query(key, values.toString());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
?
? ? ? ? ? ? try{
? ? ? ? ? ? ? ? Class requestClass = requestTemplate.getClass();
? ? ? ? ? ? ? ? Field field = requestClass.getDeclaredField("body");
? ? ? ? ? ? ? ? field.setAccessible(true);
? ? ? ? ? ? ? ? //修改body為空。
? ? ? ? ? ? ? ? field.set(requestTemplate, Request.Body.empty());
? ? ? ? ? ? } catch (Exception ex) {
? ? ? ? ? ? ? ? System.out.println(ex.fillInStackTrace());
? ? ? ? ? ? }?
? ? ? ? }
?
? ? ? ? Enumeration<String> headerNames = request.getHeaderNames();
? ? ? ? if (headerNames != null) {
? ? ? ? ? ? while (headerNames.hasMoreElements()) {
? ? ? ? ? ? ? ? String name = headerNames.nextElement();
? ? ? ? ? ? ? ? String values = request.getHeader(name);
? ? ? ? ? ? ? ? // 跳過 content-length
? ? ? ? ? ? ? ? if (name.equals("content-length")){
? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? requestTemplate.header(name, values);
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? System.out.println(String.format("feign interceptor error header:%s", requestTemplate));
? ? ? ? }
? ? }
}添加fastJson的maven依賴:
<!-- JSON 解析器和生成器 --> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>com.alibaba</groupId> ? ? ? ? ? ? <artifactId>fastjson</artifactId> ? ? ? ? ? ? <version>1.2.74</version> ? ? ? ? </dependency>
消費(fèi)方的請求:
? ? @Autowired
? ? GetClient03 getClient03;
?
? ? @GetMapping("/request/get/03")
? ? public String requestGetThree(Requets01DTO requets01DTO) {
? ? ? ? return getClient03.queryDataByGetRequest(requets01DTO);
? ? }Feign接口:
package com.springcloud.service;?
import com.springcloud.config.FeignConfiguration;
import com.springcloud.pojo.Requets01DTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
?
@FeignClient(value = "provider-8762", contextId = "GetClient03", configuration = FeignConfiguration.class)
public interface GetClient03 {
?
? ? /**
? ? ?* GET方式請求③(組裝Feign接口請求時,將body里面的參數(shù)取出來,轉(zhuǎn)換為GET方式請求的參數(shù))
? ? ?*
? ? ?* @param requets01DTO
? ? ?* @return
? ? ?*/
? ? @GetMapping("/get/03")
? ? String queryDataByGetRequest(Requets01DTO requets01DTO);
}服務(wù)提供方:
? ? @GetMapping("/get/03")
? ? public String queryDataByGetRequest03(Requets01DTO requets01DTO) {
? ? ? ? return requets01DTO.toString();
? ? }請求結(jié)果截圖:

Feign調(diào)用傳遞的GET參數(shù)日期,要指定jsonFormat注解,body轉(zhuǎn)GET參數(shù)時,日期參數(shù)會變?yōu)樽址?,需要指定日期格?/p>
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;**結(jié)果截圖:**

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java JDK動態(tài)代理(AOP)用法及實(shí)現(xiàn)原理詳解
在本篇文章了小編給大家整理的是一篇關(guān)于Java JDK動態(tài)代理(AOP)用法及實(shí)現(xiàn)原理詳解內(nèi)容,有需要的朋友們可以參考學(xué)習(xí)下。2020-10-10
MySQL查詢字段實(shí)現(xiàn)字符串分割split功能的示例代碼
本文主要介紹了MySQL查詢字段實(shí)現(xiàn)字符串分割split功能的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01
通過實(shí)例了解cookie機(jī)制特性及使用方法
這篇文章主要介紹了通過實(shí)例了解cookie機(jī)制特性及使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09
Java實(shí)現(xiàn)讀取鍵盤輸入保存到txt文件,再統(tǒng)計(jì)并輸出每個單詞出現(xiàn)次數(shù)的方法
這篇文章主要介紹了Java實(shí)現(xiàn)讀取鍵盤輸入保存到txt文件,再統(tǒng)計(jì)并輸出每個單詞出現(xiàn)次數(shù)的方法,涉及java文件I/O操作及字符串遍歷、運(yùn)算實(shí)現(xiàn)統(tǒng)計(jì)功能相關(guān)技巧,需要的朋友可以參考下2017-07-07
Java求10到100000之間的水仙花數(shù)算法示例
這篇文章主要介紹了Java求10到100000之間的水仙花數(shù)算法,結(jié)合實(shí)例形式分析了水仙花數(shù)的概念及相應(yīng)的java算法實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-10-10
解決 IDEA 創(chuàng)建 Gradle 項(xiàng)目沒有src目錄問題
這篇文章主要介紹了解決 IDEA 創(chuàng)建 Gradle 項(xiàng)目沒有src目錄問題,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2018-06-06
解決mapper.xml中resultType映射類型的問題
這篇文章主要介紹了解決mapper.xml中resultType映射類型的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06
Spring Cloud實(shí)現(xiàn)提供API給客戶端的方法詳解
這篇文章主要給大家介紹了關(guān)于Spring Cloud實(shí)現(xiàn)提供API給客戶端的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01

