⭐ 全栈开发攻城狮、全网11W+粉丝、2022博客之星后端领域Top1、专家博主。
🎓擅长 指导毕设 | 论文指导 | 系统开发 | 毕业答辩 | 系统讲解等。已指导100+位同学顺利毕业
✈️个人公众号:乡下小哥编程。回复 Java全套视频教程 或 前端全套视频教程 即可获取 300G+ 教程资料,以及大量毕设项目源码。
🐬专注干货知识分享、项目实战案例开发分享
🚪 传送门:[Github毕设源码仓库](https://github.com/zhengyuzh)
报错及解决方法【微服务实战使用】
出错代码
@RequestMapping(value = "/user/queryUserInfo", method = RequestMethod.POST)
UserDTO queryUserInfoMethod(@RequestParam String userId); 远程调用其它服务
这个方法是 Feign Client(远程调用其他微服务) 的接口定义,但用法上有问题:
在 Feign 或 Spring Cloud OpenFeign 里,如果要调用 POST 接口传递参数,不能直接用 @RequestParam
,尤其是对象或复杂参数,一般需要用 @RequestBody
或者指定明确的 @RequestParam("xxx")
。
正确写法示例
假设被调用的服务(UserService
)接口是这样的:
@PostMapping("/user/queryUserInfo")
public UserDTO queryUserInfo(@RequestParam("userId") String userId) {
// 查询用户逻辑
}
那么 Feign Client 需要显式声明 value
:
@FeignClient(name = "user-service")
public interface UserClient {
@PostMapping("/user/queryUserInfo")
UserDTO queryUserInfoMethod(@RequestParam("userId") String userId);
}
这里:
-
@RequestParam("userId")
必须写明参数名,否则会出现你之前遇到的
RequestParam.value() was empty
的错误。 -
Feign 在拼装请求时会把
userId
作为 URL Query 或 Form 参数传过去。
如果参数是对象(DTO),改用 @RequestBody
假如请求参数比较多,用一个请求 DTO:
@Data
public class UserRequest {
private String userId;
private String extraParam;
}
服务端接口:
@PostMapping("/user/queryUserInfo")
public UserDTO queryUserInfo(@RequestBody UserRequest request) {
// 查询用户逻辑
}
Feign Client:
@FeignClient(name = "user-service")
public interface UserClient {
@PostMapping("/user/queryUserInfo")
UserDTO queryUserInfoMethod(@RequestBody UserRequest request);
}
注意事项
-
如果 Feign 请求是
POST
,而参数只是简单的String
,默认走application/x-www-form-urlencoded
,所以@RequestParam("xxx")
必须有值。 -
如果传递 JSON,需要
@RequestBody
,并且被调用方也要对应接收 JSON。 -
确保调用方和被调用方接口签名一致(参数名、注解一致),否则可能 400/415 错误。
其它情况会出现?
常见原因
-
你的方法参数没写
value
,比如:@GetMapping("/test") public String test(@RequestParam String name) { return name; }
如果编译时没加上
-parameters
参数,Spring 拿不到name
这个参数名,就会报错。 -
使用了老版本 Spring(或没有开启参数名保留),参数名无法自动推断。
-
@RequestParam
写成了空值:@RequestParam("") String name
这种直接就是非法的。
解决办法
根据具体情况选择:
方案 1:显式指定参数名
@GetMapping("/test")
public String test(@RequestParam("name") String name) {
return name;
}
方案 2:开启编译参数保留(推荐)
在项目的 pom.xml
里配置,保证参数名能被反射获取:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
这样即使不写 value
,也能用方法参数名作为请求参数名:
@GetMapping("/test")
public String test(@RequestParam String name) { // 自动绑定 name
return name;
}
方案 3:如果参数不是必须的,可以去掉 @RequestParam
比如:
@GetMapping("/test")
public String test(String name) {
return name;
}
Spring 会自动按请求参数名去绑定。
建议
-
对外接口的参数,最好写清楚
@RequestParam("xxx")
,避免依赖编译器参数。 -
如果项目统一使用简洁写法(省略参数名),记得在 Maven 或 Gradle 中加
-parameters
,否则打包后生产环境会出错。