文章目录
背景
写这篇源于最近自己写服务端遇到的。在提供给外部两个接口时,联调出现了问题。报错:
” HTTP request parse error,Content type’application/json;charset=UTF-8’ not supported”
然后我寻思应该是数据格式出了问题,沟通后,web端提供的不是json格式的字符串数据,而我后台接口定义的是:
consumes = “application/json;charset=UTF-8”
所以注定错误。于是我又增加了一个不同方法名,但接口一样的,设置为:
consumes = “application/x-www-form-urlencoded;charset=UTF-8”
结果本以为好了,还是报同样的错误,然后我就来精神了,仔细研究了一下,本篇做一下回顾总结吧算是。
先说解决
问题源于 我虽然改了接收类型,但是我仍然是用 注解@RequestBody 去接收的 !!! 所以去掉这个注解就可以了。
之前有根据资料试过去掉 @RequestBody 替换为 @RequestParam 的,但是不行,会报这个错:
Required DeviceActiveInfoVO parameter ‘deviceActiveInfoVO’ is not present
替换成 @PathVariable 会报这个错:
Missing URI template variable ‘deviceActiveInfoVO’ for method parameter of type DeviceActiveInfoVO
(忽略这波沙雕操作,单纯为了看看报错是嘛玩意)
正文
1. 了解注解@RequestBody、@RequestParam 、@PathVariable
首先,以上前三个注解都是与Spring MVC Controller 接收参数直接相关的。
1.1 @RequestBody
该注解用于接收前端传递给后端的json字符串格式的数据(注意前端数据采用的是Body请求体传递)。我们也知道经常在提交数据的时候会用到请求体,即使用POST提交方式时。例子如下:
(代码中AllocationDefineVO 为实体类)
@PostMapping("/add")
public ResponseBean add(@RequestBody @Validated AllocationDefineVO allocationDefineVO) throws BusinessException {
if (allocationDefineVO == null) {
throw new BusinessException(BusinessCodeEnum.PARAMETER_ERROR, "录入新规则数据不能为空!");
}
allocationDefineService.add(allocationDefineVO);
return ResponseBean.success();
}
当后端参数是一个对象,且以@RequestBody修饰,(如上代码),那么在前端传递json参数时,要注意以下几点:
- 后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值符合实体类的对应属性的类型要求时(或可转换为对应实体类属性),会调用实体类的setter方法将值赋给该属性。
- json字符串中,如果value为”“的话,后端对应属性如果是String类型的,那么接受到的就是””,如果是后端属性的类型是Integer、Double等类型,那么接收到的就是null。
- json字符串中,如果value为null的话,后端对应收到的就是null
- 如果某个参数没有value的话,在传json字符串给后端时,要么干脆就不把该字段写到json字符串中;要么写value时, 必须有值,null 或””都行。如果有key但value什么也没有,直接就不符合json格式是会报错的。
1.2 @RequestParam
@RequestParam:将请求参数绑定/映射到你控制器的方法参数上(是springmvc中接收普通参数的注解)
它的语法:
语法:@RequestParam(value=”参数名”,required=”true/false”,defaultValue=””)
value:参数名
required:是否包含该参数,默认为true,表示该请求路径中必须包含该参数,如果不包含就报错。
defaultValue:默认参数值,如果设置了该值,required=true将失效,自动为false,如果没有传该参数,就使用默认值
① 提问, 假设我要传多个参数时具体怎么使用? 来看例子:
@GetMapping("/getCodeInfo")
public ResponseBean getCodeInfo(
@RequestParam(value = "sn") String sn,
@RequestParam(value = "type") String type,
@RequestParam(value = "name") String name
) throws BusinessException {
DeviceInfoVO deviceInfoVO = deviceInfoService.getCodeInfo(sn, type, name);
return ResponseBean.success(deviceInfoVO);
}
多个参数,使用逗号隔开就可以。
② 提问,那假设我不使用该注解@RequestParam 可以吗?
可以,当然可以。但是有前提。 请注意以下几个区别:
a. 不加@RequestParam前端的参数名需要和后端控制器的变量名保持一致才能生效
b. 不加@RequestParam参数为非必传,加@RequestParam写法参数为必传。但@RequestParam可以通过@RequestParam(required = false)设置为非必传。
c. @RequestParam可以通过@RequestParam(“id”)或者@RequestParam(value = “id”)指定传入的参数名。
d. @RequestParam可以通过@RequestParam(defaultValue = “0”)指定参数默认值
e. 如果接口除了前端调用还有后端RPC调用,则不能省略@RequestParam,否则RPC会找不到参数报错
f. 访问时:
不加@RequestParam注解:url可带参数也可不带参数,输入 localhost:8080/getCodeInfo 以及 localhost:8080/getCodeInfo?sn=xxx 方法都能执行
加@RequestParam注解:url必须带有参数。也就是说你直接输入localhost:8080/getCodeInfo 会报错,不会执行方法。只能输入localhost:8080/getCodeInfo?sn=xxx 才能执行相应的方法
1.3 @PathVariable
顾名思义,该注解作用是:映射URL绑定的占位符,也就是@RequestMapping中定义的占位符中的参数(例如:/test/{id})。 带占位符的URL是 Spring3.0 新增的功能,URL中的 {xxx} 占位符可以通过 @PathVariable(“xxx”) 绑定到操作方法的入参中。
举个例子:
@GetMapping("/detail/{id}")
public ResponseBean detail(@PathVariable String id) throws BusinessException {
DeviceInfoVO deviceInfoVO = deviceInfoService.detail(id);
return ResponseBean.success(deviceInfoVO);
}
例子中该注解可以拿到前端传来的参数id。
1.4 @RequestBody 和 @RequestParam 配合使用
直接上例子:
@GetMapping("/findLogList")
public ResponseBean<PageVO<LogVO>> findLogList(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize") Integer pageSize,
@RequestBody LogVO logVO) {
PageVO<LogVO> logList = logService.findLogList(pageNum, pageSize, logVO);
return ResponseBean.success(logList);
}
@RequestBody 也可以不加。(@RequestBody加了接收请求体中的json数据;不加注解接收URL中的数据并组装为对象)
1.5 @RequestBody 和 @PathVariable 结合使用
例子:
@PostMapping("/update/{id}")
public ResponseBean update(@PathVariable String id,
@RequestBody @Validated DeviceInfoVO deviceInfoVO)
throws BusinessException {
return ResponseBean.success();
}
前端传来要更改的记录id和要提交的form表单。
注:回到原先问题背景,是因为@RequestBody注解不能接收参数类型为
application/x-www-form-urlencoded;charset=UTF-8
的数据,然后有看到一篇可以自定义参数解析器,以使得@RequestBody注解能够接收该类型的数据的方法,传送门:
SpringBoot自定义参数解析器,使被@RequestBody标注的参数能额外接收Content-Type为application/x-www-form-urlencoded的请求
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/157236.html