PathVariable与RequestParam

我们可以从请求中获取查询参数,表单参数甚至文件, 事实上,这两种URL设计都是可以的:@RequestParam@PathVariable

都能够完成类似的功能
——因为本质上,它们都是用户的输入,只不过输入的部分不同,一个在URL路径部分,另一个在参数部分。

  • 通过 @PathVariable,例如/blogs/1

  • 通过 @RequestParam,例如blogs?blogId=1

  • 根据不同应用场景来选择使用:

    • URL指向的是某一具体业务资源(或资源列表),使用 @PathVariable
    • URL需要对资源或者资源列表进行过滤,筛选时,使用 @RequestParam

参数的属性值

  1. name (指定请求参数名称)
    • 在变量名称和参数名称都相同的情况则不需制定。但有时我们希望这些不同。或者,如果我们不使用Spring Boot,我们可能需要进行特殊的编译时配置,否则参数名称实际上不会在编译后的字节码中
    @GetMapping("/user/play")
    @ResponseBody
    public String toLoanInfo(@RequestParam(name = "id") String userId, @RequestParam name){

        return "play: " + userId + name;
    }
  1. value
    • @RequestParam(value =“id”)等同于 @RequestParam(“id”)
  2. required
    • 一旦我们在方法中定义了@RequestParam变量,如果访问的uri中不带有相应的参数,就会抛出异常——这是显然的,Spring尝试帮我们进行绑定,然而没有成功。但有的时候,参数确实不一定永远都存在,这时我们可以通过定义required属性,我们可以将@RequestParam的required设置为false ,默认为true(必选):
    @GetMapping("/user/play")
    @ResponseBody
    public String toLoanInfo(@RequestParam(required = false) String id){

        return "play: " + id;
    }
  1. defaultValue
    • 在参数不存在的情况下,可能希望变量有一个默认值
@RequestParam(value = "id", required = false, defaultValue = "0")

注意:在使@PathVariable成为可选时我们应该小心,以避免路径冲突。

SpringBootThymeleaf表达式中,使用@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 会进行编码解码。这种特性很少有人注意到

WRITTEN BY:    Richard

I'm discombobulated !