Spring MVC中的@RequestParam处理可选参数


185

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方法...映射”异常。


2
阅读本文:codeflex.co/…–
ybonda

Answers:


224

你需要给required = falsename,并password请求参数也是如此。这是因为,当您仅提供logout参数时,它实际上是预期的name并且password仍然是必需的。

当您刚刚给定时它就起作用了namepassword因为logout这不是必需的参数,这要归功于required = falsefor logout


167

Spring 4.1.1现在开始,您现在已经完全支持Java 8 Optional原始票证),因此在您的示例中,两个请求都将通过您的单个映射端点进行,只要您required=false用Optional 替换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 {...}

2
@VibhavChaddha,您可以使用类似以下的方法:if(idOfUser.isPresent()){System.out.println(“ idOfUser:” + idOfUser.get()); }
Cassio Seffrin

10
Intellij警告:“ Optional <Long>”用作参数“ requestedTimelineStart”的类型...(Strg + F1)检查信息:报告对java.util.Optional <T>,java.util.OptionalDouble,java的任何使用。 util.OptionalInt,java.util.OptionalLong或com.google.common.base。可选作为字段或参数的类型。可选的目的是为库方法返回类型提供一种有限的机制,该机制需要一种明确的方式来表示“无结果”。如果该类需要是可序列化的,则使用类型为java.util.Optional的字段也是有问题的,而java.util.Optional不是。
PeMa

我相信这应该是Java 8的新正确答案。
java-addict301

40

创建2个处理案例的方法。您可以指示@RequestMapping注释在映射请求时考虑某些参数。这样,您可以很好地将其分为2种方法。

@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 {...}

1
当有人同时将注销,名称和密码传递到URL时会发生什么?只是阅读文档,它说!myParam style expressions indicate that the * specified parameter is not supposed to be present in the request.必须尝试。
环形承载者

2
它将找到最佳匹配,它可能会尝试使用handleLoginelse,它将给出一个异常,指出找不到映射。
M. Deinum '16

3
请注意,从安全角度来看,注销仅应接受POST请求,因此应该有2种方法,因此保持其URL相同就没有任何意义。
FlasH从Ru
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.