一、前言
@PathVariable是Spring MVC中的一个非常重要的注解,作用在于将URL中的模板变量(即路径变量)绑定到控制器方法的参数上。这一功能特别适用于处理RESTful风格的请求,使得开发者能够直接从URL中提取参数值,并将其传递给方法进行处理。通过使用@PathVariable注解,可以设计出更加灵活和动态的URL映射,同时简化参数传递的过程,提高代码的可读性和可维护性。
二、实战案例
1.基本使用
为使映射正确工作,捕获 URI 变量 {id} 的名称必须与 @PathVariable 成员参数id 相同。
package com.example.springbootdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test/{id}")
public String test(@PathVariable Long id) {
return "test->" + id;
}
}
程序测试:
如果将参数名修改如下:@PathVariable Long key的话,由于URL路径中的变量和参数的变量不一致就会导致异常。
package com.example.springbootdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test/{id}")
public String test(@PathVariable Long key) {
return "test->" + key;
}
}
程序运行:
所以,在这种情况下你参数的名称要与模板中的一样。
2.不同参数名
我们可以通过将参数传递给 @PathVariable 注解,显式访问捕获 URI 变量。我们在@PathVariable注解中指明参数名称。
package com.example.springbootdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test/{id}")
public String test(@PathVariable("id") Long key) {
return "test->" + key;
}
}
程序运行:
通过指明路径参数名,这样就不会报错了。
3.类级别的路径变量
下面的示例展示了如何使用 @PathVariable 在类和方法级别访问URI 变量。
package com.example.springbootdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test/{type}")
public class TestController {
@GetMapping("/{id}")
public String test(@PathVariable Integer type, @PathVariable("id") Long key) {
return "type=>" + type + ",key=>" + key;
}
}
程序运行:
这里的路径变量type与参数名一致所以不用指定名称。
4.多个URI变量
你也可以定义多个 @PathVariable 注解来访问捕获的 URI 变量。
package com.example.springbootdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test/{type}/{id}")
public String test(@PathVariable Integer type, @PathVariable("id") Long key) {
return "type=>" + type + ",key=>" + key;
}
}
程序运行:
只要你想,只要不超过GET请求大小限制,你可以设置N多的路径参数。
5.Map接收路径变量
@PathVariable注解还支持Map类型
package com.example.springbootdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class TestController {
@GetMapping("/test/{type}/{id}")
public String test(@PathVariable Map<String, String> map) {
Integer type = Integer.valueOf(map.get("type"));
Integer id = Integer.valueOf(map.get("id"));
return "type=>" + type + ",id=>" + id;
}
}
程序运行:
6.正则路径变量
package com.example.springbootdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test/{name:[a-z]+}")
public String test(@PathVariable String name) {
return name;
}
}
程序运行:
该路径将只会匹配最后的name为a~z组合的字符。
7.可选的路径变量
默认情况下@PathVariable路径变量是必须,否则服务端将MethodArgumentTypeMismatchException异常。我们除了可以通过设置PathVariable注解的required属性为false外,还可以通过Optional类型接收值,如下示例:
package com.example.springbootdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
@RestController
public class TestController {
@GetMapping({"/test/{id}", "/tests/"})
public Long test(@PathVariable Optional<Long> id) {
return id.orElseGet(() -> -1L);
}
}
匹配两个路径,没有id则返回-1。
程序运行: