在平常的開發中,當遇到一個請求須要傳遞多個參數時,咱們習慣將參數封裝到一個POJO對象中,已提升程序的可讀性和簡化編寫。可是在使用SpringCloud時,Feign對SpringMVC註解支持並不完善,其中一點就是,當發送的GET請求攜帶多個參數時,不能使用POJO來封裝參數,這個就比較蛋疼了。一種使之支持GET請求POJO傳遞參數的方法以下:html
添加Maven依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-httpclient</artifactId> <version>8.15.1</version> </dependency> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-hystrix</artifactId> <version>10.2.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency>
application.yml
feign: hystrix: enabled: true httpclient: enabled: true okhttp: enabled: true
添加對GET請求的攔截器
import com.alibaba.fastjson.JSON; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import feign.RequestInterceptor; import feign.RequestTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.io.IOException; import java.util.*; /** * 攔截Fegin的get請求,使之支持get請求pojo傳參 */ @Component public class FeignRequestInterceptor implements RequestInterceptor { private static final Logger log = LoggerFactory.getLogger(FeignRequestInterceptor.class); @Resource private ObjectMapper objectMapper; @Override public void apply(RequestTemplate template) { if (HttpMethod.GET.name().equals(template.method()) && null != template.body()) { try { JsonNode jsonNode = objectMapper.readTree(template.body()); template.body(null); Map<String, Collection<String>> queries = new HashMap<>(); buildQuery(jsonNode, "", queries); template.queries(queries); } catch (IOException e) { log.error("【攔截GET請求POJO方式】-出錯了:{}", JSON.toJSONString(e)); throw new RuntimeException(); } } } private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) { // 葉子節點 if (!jsonNode.isContainerNode()) { if (jsonNode.isNull()) { return; } Collection<String> values = queries.get(path); if (null == values) { values = new ArrayList<>(); queries.put(path, values); } values.add(jsonNode.asText()); return; } // 數組節點 if (jsonNode.isArray()) { Iterator<JsonNode> it = jsonNode.elements(); while (it.hasNext()) { buildQuery(it.next(), path, queries); } } else { Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields(); while (it.hasNext()) { Map.Entry<String, JsonNode> entry = it.next(); if (StringUtils.hasText(path)) { buildQuery(entry.getValue(), path + "." + entry.getKey(), queries); } else { // 根節點 buildQuery(entry.getValue(), entry.getKey(), queries); } } } } }
其餘
此時你的應用程序就能夠經過POJO封裝參數向其餘服務發起調用了。可是若是你請求的Content-Type是application/json的,那麼你要須要指定請求的consumes爲 consumes = MediaType.APPLICATION_JSON_VALUE
。java
原文出處:https://www.cnblogs.com/QullLee/p/10682719.htmlgit