我们可以从请求中获取查询参数,表单参数甚至文件, 事实上,这两种URL设计都是可以的:@RequestParam 和 @PathVariable
都能够完成类似的功能
——因为本质上,它们都是用户的输入,只不过输入的部分不同,一个在URL路径部分,另一个在参数部分。
-
通过 @PathVariable,例如/blogs/1
-
通过 @RequestParam,例如blogs?blogId=1
-
根据不同应用场景来选择使用:
- 当URL指向的是某一具体业务资源(或资源列表),使用 @PathVariable
- 当URL需要对资源或者资源列表进行过滤,筛选时,使用 @RequestParam
参数的属性值
- name (指定请求参数名称)
- 在变量名称和参数名称都相同的情况则不需制定。但有时我们希望这些不同。或者,如果我们不使用Spring Boot,我们可能需要进行特殊的编译时配置,否则参数名称实际上不会在编译后的字节码中
@GetMapping("/user/play")
@ResponseBody
public String toLoanInfo(@RequestParam(name = "id") String userId, @RequestParam name){
return "play: " + userId + name;
}
- value
- @RequestParam(value =“id”)等同于 @RequestParam(“id”)
- required
- 一旦我们在方法中定义了@RequestParam变量,如果访问的uri中不带有相应的参数,就会抛出异常——这是显然的,Spring尝试帮我们进行绑定,然而没有成功。但有的时候,参数确实不一定永远都存在,这时我们可以通过定义required属性,我们可以将@RequestParam的required设置为false ,默认为true(必选):
@GetMapping("/user/play")
@ResponseBody
public String toLoanInfo(@RequestParam(required = false) String id){
return "play: " + id;
}
- defaultValue
- 在参数不存在的情况下,可能希望变量有一个默认值
@RequestParam(value = "id", required = false, defaultValue = "0")
注意:在使@PathVariable成为可选时我们应该小心,以避免路径冲突。
在 SpringBoot 的Thymeleaf表达式中,使用@PathVariable需要符合其URL风格
<!-- Restful Style 需要 + 号拼接,路径后的斜杠不能忽略 -->
<a th:href="@{'/user/play/'+拼接的参数}">跳转</a>
<!-- Normal Style -->
<a th:href="@{/user/play(id="id",name="name")}">跳转</a>
而 @PathVariable 中使用required=false 还需要注意的是:当参数不存在时,需要配置多个uri映射,避免404
@GetMapping({"/user/play/{productType}","/user/play/"})
public String toLoanInfo(@PathVariable(required = false) Integer productType){
return "play";
}
拓展
URI编码
RFC3986文档规定,Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符。US-ASCII字符集中没有对应的可打印字符:Url中只允许使用可打印字符。US-ASCII码中的10-7F字节全都表示控制字符,这些字符都不能直接出现在Url中。同时,对于80-FF字节(ISO-8859-1),由于已经超出了US-ACII定义的字节范围,因此也不可以放在Url中。
保留字符:Url可以划分成若干个组件,协议、主机、路径等。有一些字符(😕?#[]@)是用作分隔不同组件的。例如:冒号用于分隔协议和主机,/用于分隔主机和路径,?用于分隔路径和查询参数,等等。还有一些字符(!$&’()*+,;=)用于在每个组件中起到分隔作用的,如=用于表示查询参数中的键值对,&符号用于分隔查询多个键值对。当组件中的普通数据包含这些特殊字符时,需要对其进行编码。RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ]
感兴趣可以做个测试:@PathVariable 和 @RequestParam 两种注解的编码问题
@PathVariable 从路径中获取是不用编码解码的,而 @RequestParam 会进行编码解码。这种特性很少有人注意到