Spring Web MVC:对请求参数和路径变量使用相同的请求映射

Posted

技术标签:

【中文标题】Spring Web MVC:对请求参数和路径变量使用相同的请求映射【英文标题】:Spring Web MVC: Use same request mapping for request parameter and path variable 【发布时间】:2011-02-14 06:51:50 【问题描述】:

有没有办法表示我的 Spring Web MVC 控制器方法应该通过将 ID 作为 URI 路径的一部分提交的请求来匹配...

@RequestMapping(method=RequestMethod.GET, value="campaigns/id")
public String getCampaignDetails(Model model, @PathVariable("id") Long id) 

...或者如果客户端将 ID 作为 HTTP 请求参数以样式发送...

@RequestMapping(method=RequestMethod.GET, value="campaigns")
public String getCampaignDetails(Model model, @RequestParam("id") Long id) 

在我看来,这似乎是一个非常常见的现实世界 URL 方案,我不想添加重复的代码,但我还没有找到答案。任何建议都非常受欢迎。

编辑:事实证明,目前似乎(使用 Spring MVC 没有办法实现这一点,请参阅 Javi 答案中的讨论。

【问题讨论】:

【参考方案1】:

您可以为同一个函数设置映射 url 并将 id 设置为可选。

@RequestMapping(method=RequestMethod.GET, value="/campaigns","/campaigns/id")
public String getCampaignDetails(Model model,
     @RequestParam(value="id", required=false) Long id,
     @PathVariable("id") Long id2)


虽然在不发送 id 时它也会映射,但你可以在方法内部控制它。

编辑:之前的解决方案不起作用,因为在没有null 时,@PathVariable 未设置为 null,并且它无法映射 URL(感谢 ngeek)。我认为唯一可能的解决方案是创建两个方法,每个方法都映射到其@MappingRequest,并在其中一个调用另一个函数或重定向到另一个 URL(重定向:或转发:Spring 前缀)。我知道这个解决方案不是您想要的,但认为这是您能做的最好的。实际上,您不是在复制代码,而是在创建另一个函数来处理另一个 URL。

【讨论】:

不幸的是,这不起作用,因为路径变量无法解析。我还通过添加方法参数(@PathVariable("id") Long id2)尝试了一个变体,但是您不能将路径变量设为可选,因此这个建议的解决方案不起作用。还有其他推荐吗? @ngeek 我没有意识到@PathVariable 不能设置为空,谢谢。我也忘了写@PathVariable,所以我编辑了我的答案来添加它,我认为你不能避免有两种我认为的方法:(。 感谢您回到您的提议 Javi。当然,我已经委托了相同的内部方法以避免重复代码。我仍然认为 Spring MVC 注释应该提供一种方法来通过内在方法将多个 URL 定义映射到同一个方法,就像 Rails 或 Grails 中的路由器已经允许的那样。无论如何感谢您的帮助。 这个例子让我有点困惑,因为我添加了一个 id2。其他对此感到困惑的人可能会很高兴知道这是有效的:@PathVariable @RequestParam(value = "id", required = false) Long id, @OutfastSource @PathVariable 在我这样做时似乎被忽略了。对我有用的是@Javi 在@PathVariable 中对required = false 的回答,自Spring MVC 4.3.3 起支持。【参考方案2】:

如果您仍想坚持使用 PathVariable 方法并且遇到 400 句语法不正确的错误,请遵循此方法-

 @RequestMapping(method=RequestMethod.GET, value="campaigns/id","campaigns")
                         public String getCampaignDetails(Model model,
                         @PathVariable Map<String, String> pathVariables) 
   

     System.out.println(pathVariables.get("id"));

   

【讨论】:

【参考方案3】:

@RequestMapping 注解现在支持设置path 属性,而不是namevalue。使用path,可以实现本题想要的映射:

@RequestMapping(method=RequestMethod.GET, path="campaigns/id")
public String getCampaignDetails(Model model, @PathVariable("id") Long id) 

@RequestMapping(method=RequestMethod.GET, value="campaigns")
public String getCampaignDetails(Model model, @RequestParam("id") Long id) 

【讨论】:

以上是关于Spring Web MVC:对请求参数和路径变量使用相同的请求映射的主要内容,如果未能解决你的问题,请参考以下文章

spring mvc 坑之PUT方法接收不到请求参数

使用请求参数将javascript变量传递给spring MVC控制器

spring 请求参数和路径变量

Spring MVC 的请求参数获取的几种方法

Spring MVC 接收请求参数所有方式总结!

Spring Mvc详解