Spring MVC 中的@RequestParam 处理可选参数
Posted
技术标签:
【中文标题】Spring MVC 中的@RequestParam 处理可选参数【英文标题】:@RequestParam in Spring MVC handling optional parameters 【发布时间】:2014-04-17 21:30:57 【问题描述】:Spring 控制器是否可以同时处理这两种请求?
1)http://localhost:8080/submit/id/ID123432?logout=true
2)http://localhost:8080/submit/id/ID123432?name=sam&password=543432
如果我定义一个这样的控制器:
@RequestMapping (value = "/submit/id/id", method = RequestMethod.GET,
produces="text/xml")
public String showLoginWindow(@PathVariable("id") String id,
@RequestParam(value = "logout", required = false) String logout,
@RequestParam("name") String username,
@RequestParam("password") String password,
@ModelAttribute("submitModel") SubmitModel model,
BindingResult errors) throws LoginException ...
不接受带有“注销”的 HTTP 请求。
如果我定义两个控制器来分别处理每个请求,Spring 会报错“已经有 'Controller' bean 方法 ... 映射”。
【问题讨论】:
阅读这篇文章:codeflex.co/… 【参考方案1】:您还需要为name
和password
请求参数提供required = false
。这是因为,当您只提供 logout
参数时,它实际上期望 name
和 password
以及它们仍然是强制性的。
当您只提供 name
和 password
时它起作用了,因为 logout
不是强制性参数,这要归功于 required = false
已经为 logout
提供。
【讨论】:
【参考方案2】:创建 2 个处理案例的方法。您可以指示@RequestMapping
注释在映射请求时考虑某些参数。这样你就可以很好地把它分成两种方法。
@RequestMapping (value="/submit/id/id", method=RequestMethod.GET,
produces="text/xml", params="logout")
public String handleLogout(@PathVariable("id") String id,
@RequestParam("logout") String logout) ...
@RequestMapping (value="/submit/id/id", method=RequestMethod.GET,
produces="text/xml", params="name", "password")
public String handleLogin(@PathVariable("id") String id, @RequestParam("name")
String username, @RequestParam("password") String password,
@ModelAttribute("submitModel") SubmitModel model, BindingResult errors)
throws LoginException ...
【讨论】:
当有人将注销、名称和密码都传递给 URL 时会发生什么?只需阅读文档,它说!myParam style expressions indicate that the * specified parameter is not supposed to be present in the request.
必须尝试。
它会找到最好的匹配,它可能会尝试使用handleLogin
,否则它会给出一个异常,指出找不到映射。
请注意:从安全角度来看,注销应该只接受 POST 请求,因此应该有 2 种方法,保持它们的 URL 相同没有任何意义那么。【参考方案3】:
作为Spring 4.1.1
的一部分,您现在可以完全支持Java 8 Optional
(original ticket),因此在您的示例中,只要您将required=false
替换为 Optional for,两个请求都将通过您的单个映射端点您的 3 参数注销、名称、密码:
@RequestMapping (value = "/submit/id/id", method = RequestMethod.GET,
produces="text/xml")
public String showLoginWindow(@PathVariable("id") String id,
@RequestParam(value = "logout") Optional<String> logout,
@RequestParam("name") Optional<String> username,
@RequestParam("password") Optional<String> password,
@ModelAttribute("submitModel") SubmitModel model,
BindingResult errors) throws LoginException ...
【讨论】:
@VibhavChaddha 你可以使用这样的东西: if (idOfUser.isPresent()) System.out.println("idOfUser: "+ idOfUser.get()); Intellij 警告:'OptionalOptional
作为参数而不是null
检查要清楚得多。是的,参数可以是null
本身,但返回的Optional
值也可以是null
。尤其是在这种情况下,当 Spring 将其包装在 Optional 中时在内部处理空参数时。【参考方案4】:
如果有人正在寻找使用Pojo
映射可选参数,也可以像下面这样进行。
@RequestMapping (value = "/submit/id/id", method = RequestMethod.GET,
produces="text/xml")
public String showLoginWindow(@PathVariable("id") String id,
LoginRequest loginRequest,
@ModelAttribute("submitModel") SubmitModel model,
BindingResult errors) throws LoginException ...
@Data
@NoArgsConstructor
//@AllArgsConstructor - Don't use this
public class LoginRequest
private Optional<String> logout = Optional.empty();
private Optional<String> username = Optional.empty();
private Optional<String> password = Optional.empty();
注意:不要在POJO
上使用@AllArgsConstructor
,否则会将字段初始化为空。
【讨论】:
以上是关于Spring MVC 中的@RequestParam 处理可选参数的主要内容,如果未能解决你的问题,请参考以下文章
spring3 mvc的service如何在类中的中的怎么样使用