环境
- spring-cloud-dependencies(Finchley.RELEASE)
- spring-cloud-starter-openfeign
解决方法
方法一, 将一个复杂的参数转换成多个参数(不推荐)
import feign.QueryMap;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
@FeignClient(value = "feign-demo")
public interface FeignService {
@GetMapping("/getByParams")
Object getByParams3(@RequestParam("name") String name,
@RequestParam("id") Long id,
@RequestParam("date") String date);
@GetMapping("/getByParams")
Object getByParams4(@RequestParam Map<String, Object> map);
@GetMapping("/getByParams")
Object getByParams5(@QueryMap Map<String, Object> map);
}
方法二, get请求+RequestBody注解(不推荐)
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "feign-demo")
public interface FeignService {
@GetMapping("/getByParams")
Object getByParams(@RequestBody ParamDTO paramDTO);
}
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.util.*;
@Component
public class FeignRequestInterceptor implements RequestInterceptor {
@Autowired
private ObjectMapper objectMapper;
@Override
public void apply(RequestTemplate requestTemplate) {
if (requestTemplate.method().equals("GET") && requestTemplate.body() != null) {
try {
JsonNode node = objectMapper.readTree(requestTemplate.body());
requestTemplate.body(null);
Map<String, Collection<String>> queries = new HashMap<>();
buildQuery(node, "", queries);
requestTemplate.queries(queries);
} catch (IOException e) {
e.printStackTrace();
}
}
}
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);
}
}
}
}
}
方法三, 使用okhttp替换feign默认的client(jdk底层的HttpURLConnection)(推荐)
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
feign:
httpclient:
enabled: false
okhttp:
enabled: true
import feign.QueryMap;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
@FeignClient(value = "feign-demo")
public interface FeignService {
@GetMapping("/getByParams")
Object getByParams6(ParamDTO paramDTO);
}
小技巧
控制台如何打印feign的日志?
logging:
level:
cn.springcloud.book.FeignService: debug
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}