使用过 微服务 的架构,遇到最常见的场景一般都是服务之间的相互调用,而使用 Spring -Cloud微服务架构的框架一般使用feign进行调用,下面就是feign调用参数声明的标准写法描述,如果使用方式不当或者不正确,或多或少会出现如下类似问题:
- 问题一:
Caused by: java .lang.Illegal State Exception: Method has too many Body parameters - 问题二:
request Param.value() was empty on parameter 0
feign生产者提供方法参数声明
- 场景GET/POST简单参数传递
key/value 类型,则无需为该参数设置 @ Request Param 注解,多个参数同样如此
@RequestMapping(value = "/hello",method = RequestMethod.GET)
BetaDto hello2(@RequestParam("name") String name,@RequestParam("name1") String name1);
- 场景POST复杂类型传递,需要接受对象进行传递
需要接受复杂数据格式类型,如 Json 对象参数显示的指定@RequestBody注解
@PostMapping("/app/goods/goodsSalesAndStockUpdate")
String goodsSalesAndStockUpdate(@RequestBody List<GoodCountDto> goodCountDto);
实际中方式1和方式2能满足99%的业务创建需求,二区说下区别:
- 使用@RequestBody的用于Post请求
- 使用@RequestParam用于URL多个个参数值传递,用于Get请
- 如果如果请求的参数值过长,使用Post请求方式
扩展,复杂方式调用Post请求Feign提供者
有一个场景是A服务调用B服务接口,B服务接口的申明如下:
@PostMapping("/payOrder")
public String payOrder(HttpServletResponse response, @DecryptParam String parameters, HttpServletRequest request){
//........
String osType = request.get header ("osType");
String osVersion = request.getHeader("osVersion");
payRequest.setOsType(osType);
payRequest.setOsVersion(osVersion);
return ...
}
一般我们调用Feign声明的方法如下:
@PostMapping("/app/pay/payOrder")
String payOrder(@RequestParam("parameters") String parameters);
这样就有一个问题,生产者中的header接受不到,数据传输就会有问题。如何解决了?那就是使用MultiValueMap,光使用他也不行,如果生产者返回信息在Response的header中的,又得使用feign.Response来接受返回值。所以Feign正确的申请方式如下:
@PostMapping("/app/pay/payOrder")
feign.Response payOrder(@RequestParam("parameters") String parameters, @RequestHeader MultiValueMap<String, String> headers);
业务中MultiValueMap的使用如下:
MultiValueMap<String, String> headers = new HttpHeaders();
headers.add("key", SecretText[0]);
headers.add("PAY_TOKEN", token);
Response response = vipClient.payOrder(SecretText[1], headers);
LinkedList list = (LinkedList) response.headers().get("code");
int code = Integer.valueOf((String) list.get(0)).intValue();
if (code == 1) {
String responseMsg = response.body().toString();
String message = JSONUtil.parseObj(responseMsg).getStr("message");
throw new BusinessException(message);
}
支持Feign调用参数之间的传输几种方式解释完毕!
调用不难,基础很重要!