【问题标题】:Spring MVC: how to indicate whether a path variable is required or not?Spring MVC:如何指示是否需要路径变量?
【发布时间】:2013-07-23 04:53:56
【问题描述】:

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

感谢您的帮助!

【问题讨论】:

标签: spring spring-mvc path-variables


【解决方案1】:

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

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

【讨论】:

  • 请注意,这需要 Spring 4.1+ 和 Java 1.8。
  • 当您使用"/" 时,您将获得http://.../foo/bar 地址的404 和http://.../foo/bar/ 的响应。我使用空字符串"" 作为第一个值。
  • 请注意,从 Spring 4.3.3 开始,您还可以使用 @PathVariable(required = false),如果变量不存在,则为 null。
  • @NicolaiEhemann,感谢您提供的信息,这是正确的。但这只是行不通的。可能像 @RequestMapping(value = {"foo", "foo/{bar}"})@PathVariable(required = false)
  • 我的评论只是对答案的补充(应该是公认的答案),因为它提供了使 id 可选的替代方法。
【解决方案2】:

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

【讨论】:

  • 特里斯坦,我选择了 VTTom 的帖子作为答案,以使阅读此问题的人受益。你是对的。
  • 有可能,请查看其他一些答案(@curious1 随时接受其他答案之一)。
  • 可以这样使用:@PatchMapping(path = {"/{procurementInitId}/updateLinkedPurchase/{purchaseId}", "/{procurementInitId}/updateLinkedPurchase"}, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public HttpEntity&lt;?&gt; updateLinkedPurchase( @PathVariable(name = "procurementInitId") Integer procurementInitId, @PathVariable(name = "purchaseId", required = false) Integer purchaseId) {
【解决方案3】:

我知道这是一个老问题,但是搜索“可选路径变量”会使这个答案很高,所以我认为值得指出的是,自从 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
  }
}

【讨论】:

  • 任何人都可以验证这个作品吗?当我尝试访问没有 id 的路径时得到 404(Spring MVC 4.1.4,Java 1.8.0_66)。
  • 是的,这将不起作用,因为没有 id 的路径将不匹配并命中此控制器。
  • 感谢您提及 Optional 类的 pkg 名称。
  • 这部分 value={"/", "/{id}"} 使它适用于有和没有 id 的路线
【解决方案4】:

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..

【讨论】:

    【解决方案5】:

    使用 '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;
    

    }

    【讨论】:

      【解决方案6】:

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

      自从Spring MVC 4.3.3介绍Web Improvements

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

      合法且可行。

      【讨论】:

        【解决方案7】:
        @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

        /customer - 现在可以工作了!!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-01-24
          • 2017-06-21
          • 2020-06-12
          • 2015-01-25
          • 1970-01-01
          • 2017-12-28
          • 2011-12-12
          • 2012-08-28
          相关资源
          最近更新 更多