本文目录
一、背景描述
二、代码错误
三、错误的原因
四、解决方案
4.1 方案1:POST请求 + 注解
4.2 方案2:GET请求 + @SpringQueryMap注释
4.3 方案3:GET请求 + @RequestParam("xxx")注解
一、背景描述
公司制作的智能家居系统改为微服务框架,各微服务之前相互调用。
今天在做测试的时候,后台系统报了一个Caused by: java.lang.IllegalArgumentException: method GET must not have a request body出了问题,然后检查了从前到后的所有请求链路。通过Debug调试,页面请求可以输入serviceA,参数也可以携带到方法中,一步一步向下。当发现serviceB通过feignclient被调用时,报告了这种异常。
二、代码错误以下两个接口是Servicea通过FiegnClient调用ServiceB的接口(FeignClient调用的接口)
第一个ServiceB接口的代码
/** * 根据主机sn查询远程运维记录 * @param distanceMaintainRecordQuery * @return*/@GetMapping("/client/v1.0/distanceMaintain/pageMaintain")PageResult<DistanceMaintainRecordBO> pageMaintain(DistanceMaintainRecordQuery distanceMaintainRecordQuery);
第二个ServiceB接口的代码
/*** 查询屏保详情** @param id* @return*/@GetMapping("/client/v1.0/screenSaver/info")CommResponse<ScreenSaverBO> info(Integer id);
三、错误的原因报告这种异常的原因是,该接口的请求模式是GET请求,接受的参数是一个对象(包括多个参数),而通过FeignClient调用的GET请求模式无法分析对象,因此,使用上述代码会报Causeded by: java.lang.IllegalArgumentException: method GET must not have a request body错了。
事实上,FeignClient支持对象传输,但它必须以Map的形式,而且不是空的。它与Spring的机制不兼容,因此不能使用。
而spring 2.1cloud.x版本提供了@SpringQueryMap注释,可以传输对象参数,框架自动分析,可惜是2.1.0后版本。
通过FeignClient调用上述第二个接口GET请求只传输一个参数,也不支持。报错信息与第一种情况完全相同。
四、解决方案4.1 方案1:POST请求 + 注解将ServiceB接口的请求方式改为POST,并在接受的参数前添加@requestBody注释。更正后的代码如下:
/** * 根据主机sn查询远程运维记录 * @param distanceMaintainRecordQuery * @return*/@PostMapping("/client/v1.0/distanceMaintain/pageMaintain")PageResult<DistanceMaintainRecordBO> pageMaintain(@RequestBody DistanceMaintainRecordQuery distanceMaintainRecordQuery);
4.2 方案2:GET请求 + @SpringQueryMap注释/** * 根据主机sn查询远程运维记录 * @param distanceMaintainRecordQuery * @return */@GetMapping("/client/v1.0/distanceMaintain/pageMaintain")PageResult<DistanceMaintainRecordBO> pageMaintain(@SpringQueryMap DistanceMaintainRecordQuery distanceMaintainRecordQuery);
使用方案2时,一定要注意Spring Cloud版,2.1.x以下不支持哦,只有2.1.只有x以上版本才能分析参数。
4.3 方案3:GET请求 + @RequestParam("xxx")注解/*** 查询屏保详情** @param id* @return*/@GetMapping("/client/v1.0/screenSaver/info")CommResponse<ScreenSaverBO> info(@RequestParam("id") Integer id);
需要注意的是:
1、spring 当FeignClient用于cloud项目时,GET请求模式无法分析对象参数
2、spring 当FeignClient用于cloud项目时,GET请求有时无法分析单个参数值
扩展:如何使用Feign构造多参数的请求:如何使用Feign构造多参数的请求 | 周立的博客 - 关注Spring Cloud、Docker