最近在使用Feign,总结了一下使用经验
普通调用
配置client 接口类NormalFeginClient
@FeignClient(name = "NormalFeignClient", url = "localhost:9004/check")
public interface NormalFeginClient {
@GetMapping("userValidGet")
Response normalGet(@RequestParam("userId") String userId, @RequestParam("userName") String userName);
@GetMapping("userValidGet")
Response mapGet(@HeaderMap Map<String, Object> headerMap, @SpringQueryMap Map<String, Object> requestMap);
@GetMapping("userValidGet")
Response pojoGet(@HeaderMap Map<String, Object> headerMap, @SpringQueryMap User user);
@PostMapping("testAspectUserValidPost")
Response normalPost(@RequestBody Map<String, Object> request);
@PostMapping("testAspectUserValidPost")
Response pojoPost(@HeaderMap Map<String, Object> headerMap, @SpringQueryMap User user);
}
在controller中调用
@GetMapping(value = "/thirdService")
public Response requestThirdService(HttpServletRequest req) {
String message = "test Jpa Message";
String result = "test Jpa Result";
Map<String, Object> headerMap = new HashMap<>();
headerMap.put("a", "A");
headerMap.put("a1", "A1");
Map<String, Object> requestMap = new HashMap<>();
requestMap.put("userId", "A");
requestMap.put("userName", "zero");
User user = new User();
user.setUserId("A");
user.setUserName("zero");
feign.Response requestResult1 = normalFeginClient.normalGet("A", "zero");
feign.Response requestResult2 = normalFeginClient.mapGet(headerMap, requestMap);
feign.Response requestResult3 = normalFeginClient.pojoGet(headerMap, user);
feign.Response requestResult4 = normalFeginClient.normalPost(requestMap);
feign.Response requestResult5 = normalFeginClient.pojoPost(headerMap, user);
System.out.println(FeignUtil.feignResponseBody(requestResult1));
System.out.println(FeignUtil.feignResponseBody(requestResult2));
System.out.println(FeignUtil.feignResponseBody(requestResult3));
System.out.println(FeignUtil.feignResponseBody(requestResult4));
System.out.println(FeignUtil.feignResponseBody(requestResult5));
return Response.ok(message).setData(result);
}
返回结果
{"code":"ok","data":"Hello zero","requestid":"d56b56a443a64b69b2b9cb22a9761532"}
{"timestamp":"2020-04-13T09:52:57.842+0000","status":405,"error":"Method Not Allowed","message":"Request method 'POST' not supported","path":"/check/userValidGet"}
{"timestamp":"2020-04-13T09:52:57.848+0000","status":405,"error":"Method Not Allowed","message":"Request method 'POST' not supported","path":"/check/userValidGet"}
{"code":"ok","data":"Hello null","requestid":"b27fdf522c2943f6b750ecb770db0aa1"}
{"code":"ok","data":"Hello null","requestid":"c50a2333b2ba4840ab77215fa1fc4ae9"}
在上面的调用中我们发现以这种方式调用有很多问题,调用地址无法动态修改,Get只要加上@HeaderMap就会被识别为POST方式调用,为了解决这些问题,有了以下方法
自定义调用
配置client 接口类CustomerFeignClient
注解使用 @RequestLine,参数里应按指定格式
@QueryMap参数定义名称-值对(或POJO)的映射,展开后成为字符串,可以用于Get方式传递参数
@FeignClient(name = "CustomerFeignClient")
public interface CustomerFeignClient {
@RequestLine("GET")
Response get(URI baseUri, @HeaderMap Map<String, Object> headerMap, @QueryMap Map<String, Object> requestMap);
@RequestLine("POST")
Response post(URI baseUri, @HeaderMap Map<String, Object> headerMap, @RequestBody Map<String, Object> request);
}
修改Feign配置
有两点需要注意
- import feign配置类,FeignClientsConfiguration.class,如果没有自定义参数和编解码器就使用FeignClientsConfiguration默认的
- 在CustomerFeignConfig构造函数中用 @Autowired 引入自定义参数和编解码器
package com.mantis.brac.common.feign;
import com.mantis.brac.common.exception.BracBusinessException;
import com.mantis.brac.common.http.RequestEnum;
import feign.Feign;
import feign.Response;
import feign.Target;
import feign.codec.Decoder;
import feign.codec.Encoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
@Component
@Import(FeignClientsConfiguration.class)
public class CustomerFeignConfig {
private CustomerFeignClient bracFeignClient;
private String uri;
private RequestEnum requestType;
private Map<String, Object> header;
private Map<String, Object> request;
/**
* 在构造函数中用 @Autowired 引入自定义参数和编解码器
* @param encoder
* @param decoder
*/
@Autowired
public CustomerFeignConfig(Encoder encoder, Decoder decoder) {
bracFeignClient = Feign.builder().encoder(encoder).decoder(decoder)
.target(Target.EmptyTarget.create(CustomerFeignClient.class));
}
public CustomerFeignConfig get() {
this.setRequestType(RequestEnum.GET);
return this;
}
public CustomerFeignConfig post() {
this.setRequestType(RequestEnum.POST);
return this;
}
/**
* 执行调用方法
*
* @return
*/
public Response execute() {
switch (getRequestType()) {
case GET:
return bracFeignClient.get(findUri(getUri()), getHeader(), getRequest());
case POST:
return bracFeignClient.post(findUri(getUri()), getHeader(), getRequest());
default:
throw new BracBusinessException("请选择调用方式!");
}
}
public String getUri() {
return uri;
}
public CustomerFeignConfig setUri(String uri) {
if (uri == null) {
throw new BracBusinessException("uri == null");
} else {
this.uri = uri;
}
return this;
}
public Map<String, Object> getRequest() {
return request;
}
public CustomerFeignConfig setRequest(Map<String, Object> request) {
this.request = request;
return this;
}
public RequestEnum getRequestType() {
return requestType;
}
public void setRequestType(RequestEnum requestType) {
this.requestType = requestType;
}
public Map<String, Object> getHeader() {
return header;
}
public CustomerFeignConfig setHeader(Map<String, Object> header) {
this.header = header;
return this;
}
/**
* 获取请求URI
*
* @param uri
* @return
*/
private URI findUri(String uri) {
try {
return new URI(uri);
} catch (URISyntaxException e) {
e.printStackTrace();
}
throw new BracBusinessException("获取请求地址失败!");
}
}
在controller中调用
@Autowired
CustomerFeignConfig customerFeignConfig;
@PostMapping(value = "/lookup/customer/thirdService")
public Response postQueryThirdService(HttpServletRequest req) {
String message = "Message";
String result = "Result";
StringBuilder reqJson = JsonUtil.getJson(req);
Map<String, Object> headerMap = new HashMap<>();
headerMap.put("a", "A");
headerMap.put("a1", "A1");
Map<String, Object> requestMap = new HashMap<>();
requestMap.put("userId", "A");
requestMap.put("userName", "zero");
feign.Response requestResult1 = customerFeignConfig.setHeader(headerMap).setUri("http://localhost:9004/check/userValidGet").setRequest(requestMap).get().execute();
feign.Response requestResult2 = customerFeignConfig.setHeader(headerMap).setUri("http://localhost:9004/check/testAspectUserValidPost").setRequest(requestMap).post().execute();
System.out.println(FeignUtil.feignResponseBody(requestResult1));
System.out.println(FeignUtil.feignResponseBody(requestResult2));
return Response.ok(message).setData(result);
}
返回结果
我们可以发现数据请求参数和Header正常传递
返回结果也可以正常拿到
{"code":"ok","data":"Hello zero","requestid":"3afdaf854b0946edb5b035c09198081e"}
{"code":"ok","data":"Hello null","requestid":"6b4ec0b79ab94e67b182ac9fae9adf7c"}
Git地址
git@github.com:A-mantis/brac-project-service.git
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。