写这篇源于最近自己写服务端遇到的。在提供给外部两个接口时,联调出现了问题。报错:
" 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
(忽略这波沙雕操作,单纯为了看看报错是嘛玩意)
首先,以上前三个注解都是与Spring MVC Controller 接收参数直接相关的。
该注解用于接收前端传递给后端的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参数时,要注意以下几点:
@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 才能执行相应的方法
顾名思义,该注解作用是:映射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。
直接上例子:
@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中的数据并组装为对象)
例子:
@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的请求