概述
Spring常见问题解决 - @RequestParam和@PathVarible的区别以及400报错问题
- 一. @RequestParam和@PathVariable的区别
- 二. @RequestParam 的不正确编写导致的400报错
- 2.1 案例复现
- 2.2 原理分析
- 2.3 问题解决
- 2.4 总结
一. @RequestParam和@PathVariable的区别
@RequestParam
:主要用于获取请求体中的参数。(针对请求体)URL
上的参数,?
后面的。@PathVariable
:主要用于获取URL
上的参数,一般结合Mapping
中设置的URL
中的{xxx}
来使用。(针对URL
)
看下第一种@RequestParam
的使用:
@Controller
public class MyController {
@PostMapping("/testRequestParam")
@ResponseBody
public String hello(@RequestParam("name") String name, @RequestParam("age") Integer age) {
return "name: " + name + ",age: " + age;
}
}
访问http://localhost:8080/testRequestParam?name=ljj&age=20:
看下第二种@PathVariable
的使用:
@GetMapping("/testPathVariable/{name}/{age}")
@ResponseBody
public String testPathVariable(@PathVariable("name") String name, @PathVariable("age") Integer age) {
return "name: " + name + ",age: " + age;
}
访问:http://localhost:8080/testPathVariable/ljj/20
从这两个使用案例来看,其实这两个注解的区别就比较明显了。
二. @RequestParam 的不正确编写导致的400报错
在上面的案例中,我们通过URL
携带了两个参数:age
和name
。并且后端能够正常地接收并输出。那么如果我们指携带一个参数,会怎么样呢?
2.1 案例复现
这是典型的一个案例,即我们在代码编写的时候:
- 有时候可能
URL
上携带的参数比较多,但是我们往往忽略了一些参数是否是可选的,导致出现了这样的报错。 - 当然,如果你多传一个参数,是不会有啥影响的,只要后端代码没有指定,就不会接收。
2.2 原理分析
Spring
中对于@RequestParam
注解的解析,是通过RequestParamMethodArgumentResolver
类来完成参数解析的:
public abstract class AbstractNamedValueMethodArgumentResolver implements HandlerMethodArgumentResolver {
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
MethodParameter nestedParameter = parameter.nestedIfOptional();
// ..
// 获取指定参数名称的值
Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
if (arg == null) {
// 如果对应参数的默认值不是空,那么就使用默认值
if (namedValueInfo.defaultValue != null) {
arg = resolveStringValue(namedValueInfo.defaultValue);
}
// 否则,查看这个参数的值是否是必须设置的,如果必须设置,但是没有对应的值,那么按错误处理
else if (namedValueInfo.required && !nestedParameter.isOptional()) {
handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
}
// 如果不是必须的,就按照null来处理
arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
}
else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
arg = resolveStringValue(namedValueInfo.defaultValue);
}
// ..
return arg;
}
}
这里我们可以看出,对于@RequestParam
的使用而言,其值的解析会有这么几个分支处理:
- 如果这个参数对应的值存在,就直接返回。
- 如果这个参数对应的值不存在,那么先看这个参数是否设置了默认值,若有,则返回默认值。
- 如果默认值也没有,那么看这个参数是否是
required
(默认为true
),以及该参数本身是否可选isOptional()
。如果满足这俩条件,但是没有可选的值,就报错。 - 否则按照
null
处理。
那么知道了原理,我们就可以在代码上做出对应的修改了。
2.3 问题解决
解决方案一:我们给对应的参数设置一个defaultValue
默认值。
@PostMapping("/testRequestParam")
@ResponseBody
public String hello(@RequestParam("name") String name,
@RequestParam(value = "age", defaultValue = "33") Integer age) {
return "name: " + name + ",age: " + age;
}
结果:
解决方案二:设置require
为false
。
@PostMapping("/testRequestParam")
@ResponseBody
public String hello(@RequestParam("name") String name,
@RequestParam(value = "age", defaultValue = "10") Integer age) {
return "name: " + name + ",age: " + age;
}
结果:
解决方案三:修改参数类型为 Optional
。
@PostMapping("/testRequestParam")
@ResponseBody
public String hello(@RequestParam("name") String name,
@RequestParam(value = "age") Optional age) {
return "name: " + name + ",age: " + age;
}
结果:
解决方案四:对这个可选参数添加注解@Nullable
。
@PostMapping("/testRequestParam")
@ResponseBody
public String hello(@RequestParam("name") String name,
@RequestParam(value = "age") @Nullable Integer age) {
return "name: " + name + ",age: " + age;
}
结果:
2.4 总结
- 如果希望从
URL
路径上获取参数,请使用@PathVariable
。 - 如果希望从
URL
上携带的参数上获取参数,请使用@RequestParam
。 - 使用
@RequestParam
的时候,请注意对应的参数是否是必传的,如果不是,请加上require=false
,或者其他方式来避免报400
错误(缺少属性值)。
最后
以上就是瘦瘦鼠标为你收集整理的Spring常见问题解决 - @RequestParam和@PathVariable的区别以及400报错问题一. @RequestParam和@PathVariable的区别二. @RequestParam 的不正确编写导致的400报错的全部内容,希望文章能够帮你解决Spring常见问题解决 - @RequestParam和@PathVariable的区别以及400报错问题一. @RequestParam和@PathVariable的区别二. @RequestParam 的不正确编写导致的400报错所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复