1.環境信息
spring-boot : 2.2.1.RELEASE
spring-cloud : Hoxton.SR1
2.feign get接口傳封裝類參數時,需要添加RequestBody server端才能獲取到參數,測試如下:
3.這樣對前端來說不是太友好,前端需要get傳json
4.解決方法:
新增 feignConfig文件:
/**
* Copyright (c) 2020 CQLIVING, Inc. All rights reserved.
* This software is the confidential and proprietary information of
* CQLIVING, Inc. You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the
* license agreement you entered into with CQLIVING.
*/
package com.leo.api.handler;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.Request;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* Title: feign請求頭轉發策略
* <p>Description:</p>
* Copyright (c) CQLIVING 2020
* @author liuzongyang on 2020年1月10日
*/
@Slf4j
@AllArgsConstructor
public class FeignConfigInterceptor implements RequestInterceptor {
private final ObjectMapper objectMapper;
@Override
public void apply(RequestTemplate requestTemplate) {
// get封裝參數修復
if ("GET".equals(requestTemplate.method()) && (requestTemplate.requestBody().asBytes() != null)) {
try {
Request.Body body = requestTemplate.requestBody();
JsonNode jsonNode = objectMapper.readTree(body.asBytes());
requestTemplate.body(Request.Body.empty());
Map<String, Collection<String>> queries = new HashMap<>();
// 構建 Map
buildQuery(jsonNode, "", queries);
// queries 就是 POJO 解析爲 Map 後的數據
requestTemplate.queries(queries);
} catch (IOException e) {
log.debug("get參數轉換失敗:{}", e);
}
}
// 請求頭修復
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
assert attributes != null;
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
requestTemplate.header(name, values);
}
}
}
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 (CollectionUtils.isEmpty(values)) {
values = new ArrayList<>();
queries.put(path, values);
}
values.add(jsonNode.asText());
return;
}
if (jsonNode.isArray()) {
// 如果是數組節點
Iterator<JsonNode> elements = jsonNode.elements();
while (elements.hasNext()) {
buildQuery(elements.next(), path, queries);
}
} else {
Iterator<Map.Entry<String, JsonNode>> fields = jsonNode.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> entry = fields.next();
if (StringUtils.hasText(path)) {
buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
} else {
// 根節點
buildQuery(entry.getValue(), entry.getKey(), queries);
}
}
}
}
}
feignClient:
/**
* Copyright (c) 2020 CQLIVING, Inc. All rights reserved.
* This software is the confidential and proprietary information of
* CQLIVING, Inc. You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the
* license agreement you entered into with CQLIVING.
*/
package com.leo.api.feign;
import org.springframework.cloud.openfeign.FeignClient;
import com.leo.api.SdkTest;
import com.leo.api.handler.FeignConfigInterceptor;
/**
* Title:sdktest
* <p>Description:</p>
* Copyright (c) CQLIVING 2020
* @author liuzongyang on 2020年1月10日
*/
@FeignClient(name = "leo-cloud", url = "${leo-cloud-url:}", path = "test", configuration = FeignConfigInterceptor.class)
public interface SdkFeign extends SdkTest{
}