1.概述
在本文中,我们将学习如何在Spring中将路径变量(PathVariable)设为可选。
首先,我们将描述Spring MVC如何在控制器方法中绑定@PathVariable
参数。
然后,我们将展示在不同的Spring版本中将路径变量(PathVariable)设置为可选的不同方法。
2.如何绑定@PathVariable参数
默认情况下,Spring MVC将尝试将控制器方法中用@PathVariable
注解的所有参数与URI模板中的相应变量绑定。
如果Spring MVC失败,它将不会将我们的请求传递给该处理程序方法。会直接抛出异常。
比如,我们尝试将路径变量id设置为可选:
@RequestMapping(value = { "/opv","/opv/{id}" }, method = RequestMethod.GET)
@ResponseBody
public String optionalPath(@PathVariable(name = "id") Integer id){
if(id == null){
return "OptionalPathVariable id not set";
}
return "OptionalPathVariable id =" + id;
}
在上面的代码中,我们假定optionalPath方法可以同时向/opv
和/opv/{id}
提供请求。
Spring尝试将id
参数绑定到id路径变量。
然后我们用curl来测试一下:
# curl http://localhost:8080/opv/123
OptionalPathVariable id =123%
# curl http://localhost:8080/opv/
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 500 Missing URI template variable 'id' for method parameter of type Integer</title>
</head>
<body><h2>HTTP ERROR 500 Missing URI template variable 'id' for method parameter of type Integer</h2>
<table>
<tr><th>URI:</th><td>/opv/</td></tr>
<tr><th>STATUS:</th><td>500</td></tr>
<tr><th>MESSAGE:</th><td>Missing URI template variable 'id' for method parameter of type Integer</td></tr>
<tr><th>SERVLET:</th><td>mvc</td></tr>
</table>
<hr><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.4.24.v20191120</a><hr/>
</body>
</html>
当我们向/opv
发送请求时,Spring将返回状态代码500。我们来确认一下debug日志:
21:51:26.050 [qtp1329572464-17] WARN o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.bind.MissingPathVariableException: Missing URI template variable 'id' for method parameter of type Integer]
这是因为缺少id,Spring无法为id路径变量设置值。
因此,我们需要一些方法来告诉Spring 如果没有相应的path变量,则忽略绑定特定的*@PathVariable*参数。
3.设置路径变量为可选
3.1. 使用required属性
从Spring 4.3.3开始,@PathVariable
注解定义了required属性,来告诉Spring这个路径变量是否是必须的。
required属性的默认值为true。
下面我们来修改一下之前的代码:
@RequestMapping(value = { "/opv","/opv/{id}" }, method = RequestMethod.GET)
@ResponseBody
public String optionalPath(@PathVariable(name = "id",required = false) Integer id){
logger.info("optional Path Variable");
if(id == null){
return "OptionalPathVariable id not set";
}
return "OptionalPathVariable id =" + id;
}
我们简单的测试一下
# curl http://localhost:8080/opv/
OptionalPathVariable id not set%
由于required属性为了false,如果没有在请求中发送id路径变量,Spring不会抛出异常。
3.2. 使用Optional类型参数
从Spring 4.1开始, 我们还可以使用JDK 8的Optional类提供了另一种使路径变量设置为可选:
@RequestMapping(value = { "/opv2","/opv2/{id}" }, method = RequestMethod.GET)
@ResponseBody
public String optionalPath2(@PathVariable Optional<Integer> id){
logger.info("optional Path Variable");
if(id.isPresent()){
return "OptionalPathVariable id not set";
} else {
return "OptionalPathVariable id =" + id.get();
}
}
Spring创建Optional <Integer>
实例,以保存id的值。
如果存在id,则包装其值,否则,将包装null值。
然后,我们可以使用Optional的isPresent()
, get()
或orElse()
方法来处理该值。
最后, 我们简单的测试一下:
# curl http://localhost:8080/opv2/
OptionalPathVariable id not set%
# curl http://localhost:8080/opv2/123
OptionalPathVariable id =123%
3.3 使用Map作为参数
从Spring 3.2开始,定义可选路径变量的另一种方法是定义@PathVariable
参数类型为Map
:
@RequestMapping(value = { "/opv3","/opv3/{id}" }, method = RequestMethod.GET)
@ResponseBody
public String optionalPath3(@PathVariable Map<String, String> pvMap){
logger.info("optional Path Variable");
String id = pvMap.get("id");
if(id == null){
return "OptionalPathVariable id not set";
}
return "OptionalPathVariable id =" + id;
}
使用Map <String,String>
收集URI中的所有路径变量作为键/值对。
然后,我们可以使用get()
方法获取特定的路径变量。
需要注意的是,由于Spring将路径变量的值提取为String,如果需要Integer的话,我们还需要使用Integer.valueOf()
方法将其转换为Integer。
最后, 我们简单的测试一下:
# curl http://localhost:8080/opv3/
OptionalPathVariable id not set%
# curl http://localhost:8080/opv3/213
OptionalPathVariable id =213%
3.4 使用两个处理方法
如果使用的Spring版本比较老,还可以将optionalPath处理方法分为两个方法。
第一个处理方法将处理对/pv4/ {id}的请求:
@RequestMapping(value = {"/opv4/{id}" }, method = RequestMethod.GET)
@ResponseBody
public String optionalPath4(@PathVariable Integer id){
return "OptionalPathVariable id =" + id;
}
第二个处理方法将处理对/pv4的请求:
@RequestMapping(value = { "/opv4" }, method = RequestMethod.GET)
@ResponseBody
public String optionalPath4(){
return "OptionalPathVariable id not set";
}
最后, 我们简单的测试一下:
# curl http://localhost:8080/opv4
OptionalPathVariable id not set%
# curl http://localhost:8080/opv4/123
OptionalPathVariable id =123%
4. 结论
在本文,我们讨论了如何在不同的Spring版本和不同方法设置路径变量为可选。
与往常一样,可以在GitHub上找到示例实现。