Spring MVC:如何指示是否需要路径变量?

时间:2013-07-23 21:53:53

标签: spring spring-mvc path-variables

我正在做一个Spring网站。对于控制器方法,我能够使用RequestParam来指示是否需要参数。例如:

@RequestMapping({"customer"}) 
public String surveys(HttpServletRequest request, 
@RequestParam(value="id", required = false) Long id,            
Map<String, Object> map)

我想使用PathVariable,如下所示:

@RequestMapping({"customer/{id}"}) 
public String surveys(HttpServletRequest request, 
@PathVariable("id") Long id,            
Map<String, Object> map) 

如何指示是否需要路径变量?我需要使它成为可选项,因为在创建新对象时,在保存之前没有可用的关联ID。

感谢您的帮助!

7 个答案:

答案 0 :(得分:50)

VTTom`s解决方案是正确的,只需改变&#34;价值&#34;变量到数组并列出所有网址的可能性:value = {&#34; /&#34;,&#34; / {id}&#34;}

@RequestMapping(method=GET, value={"/", "/{id}"})
public void get(@PathVariable Optional<Integer> id) {
  if (id.isPresent()) {
    id.get()   //returns the id
  }
}

答案 1 :(得分:37)

无法使其成为可选项,但您可以创建两个方法,其中一个方法具有@RequestMapping({"customer"})注释,另一个方法具有@RequestMapping({"customer/{id}"}),然后在每个方法中相应地执行操作。

答案 2 :(得分:29)

我知道这是一个老问题,但是搜索“可选路径变量”会让这个答案很高,所以我认为值得指出的是,自从使用Java 1.8的Spring 4.1以来,这可以使用java.util.Optional类

一个例子就是(请注意,值必须列出所有需要匹配的潜在路由,即使用id路径变量而不使用。道具指向@ martin-cmarko以指出它)

@RequestMapping(method=GET, value={"/", "/{id}"})
public void get(@PathVariable Optional<Integer> id) {
  if (id.isPresent()) {
    id.get()   //returns the id
  }
}

答案 3 :(得分:3)

VTToms回答不起作用,因为没有路径中的id它将不匹配(即找不到相应的HandlerMapping),因此控制器不会被命中。相反,你可以做 -

@RequestMapping({"customer/{id}","customer"}) 
public String surveys(HttpServletRequest request, @PathVariable Map<String, String> pathVariablesMap, Map<String, Object> map) {
    if (pathVariablesMap.containsKey("id")) {
        //corresponds to path "customer/{id}"
    }
    else {
        //corresponds to path "customer"
    }
}

你也可以使用其他人提到过的java.util.Optional,但它需要Spring 4.1+和Java 1.8 ..

答案 4 :(得分:0)

使用&#39; Optional&#39;(@ PathVariable Optional id)或Map(@PathVariable Map pathVariables)时出现问题,如果您尝试通过调用控制器方法创建HATEOAS链接,则会失败因为Spring-hateoas似乎是pre-java8并且不支持&#39; Optional&#39;。它也无法使用@PathVariable Map注释调用任何方法。

这是一个演示Map

失败的示例
   @RequestMapping(value={"/subs","/masterclient/{masterclient}/subs"}, method = RequestMethod.GET)
   public List<Jobs>  getJobListTest(
         @PathVariable  Map<String, String> pathVariables,
         @RequestParam(value="count", required = false, defaultValue = defaultCount) int count) 
   {

      if (pathVariables.containsKey("masterclient")) 
      {
         System.out.println("Master Client = " + pathVariables.get("masterclient"));
      } 
      else 
      {
         System.out.println("No Master Client");
      }




  //Add a Link to the self here.
  List list = new ArrayList<Jobs>();
  list.add(linkTo(methodOn(ControllerJobs.class).getJobListTest(pathVariables, count)).withSelfRel());

  return list;

}

答案 5 :(得分:0)

我知道这是一个老问题,但由于没有一个答案提供一些更新的信息,而且当我路过这个时,我想添加我的贡献:

自从 Spring MVC 4.3.3 引入 Web Improvements

{{1}}

合法且可行。

答案 6 :(得分:0)

@RequestMapping(path = {"/customer", "/customer/{id}"})
public String getCustomerById(@PathVariable("id") Optional<Long> id) 
        throws RecordNotFoundException 
{
    if(id.isPresent()) {
        //get specific customer
    } else {
        //get all customer or any thing you want
    }
}
<块引用>

现在所有的 URL 都被映射并且可以工作了。

<块引用>

/customer/123

<块引用>

/customer/1000

<块引用>

/customer - 现在开始工作!!