41

我正在做一个 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。

感谢帮助!

4

7 回答 7

61

VTTom的解决方案是对的,只需将“value”变量更改为数组并列出所有 url 可能性:value={"/", "/{id}"}

@RequestMapping(method=GET, value={"/", "/{id}"})
public void get(@PathVariable Optional<Integer> id) {
  if (id.isPresent()) {
    id.get()   //returns the id
  }
}
于 2015-12-18T13:39:41.870 回答
42

没有办法让它成为可选的,但是您可以创建两个方法,一个具有@RequestMapping({"customer"})注释,另一个具有注释,@RequestMapping({"customer/{id}"})然后在每个方法中相应地采取行动。

于 2013-07-23T22:07:28.590 回答
34

我知道这是一个老问题,但是搜索“可选路径变量”会使这个答案很高,所以我认为值得指出的是,自从 Spring 4.1 使用 Java 1.8 以来,这可以使用 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
  }
}
于 2015-08-27T19:00:14.973 回答
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..

于 2016-01-08T06:27:03.407 回答
0

使用 'Optional'(@PathVariable Optional id) 或 Map (@PathVariable Map pathVariables) 存在问题,如果您尝试通过调用控制器方法创建 HATEOAS 链接,它将失败,因为 Spring-hateoas 似乎是 pre java8 并且不支持“可选”。它也无法使用 @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;

}

于 2016-10-25T14:57:13.707 回答
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 都已映射并且可以工作。

/客户/123

/客户/1000

/客户 - 现在工作!

于 2021-07-30T14:04:24.020 回答
0

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

由于Spring MVC 4.3.3引入了Web 改进

@PathVariable(required = false) //true is default value

是合法的和可能的。

于 2021-02-05T00:40:02.607 回答