【问题标题】:With Spring can I make an optional path variable?使用 Spring,我可以创建一个可选的路径变量吗?
【发布时间】:2011-06-21 16:54:37
【问题描述】:

在 Spring 3.0 中,我可以有一个可选的路径变量吗?

例如

@RequestMapping(value = "/json/{type}", method = RequestMethod.GET)
public @ResponseBody TestBean testAjax(
        HttpServletRequest req,
        @PathVariable String type,
        @RequestParam("track") String track) {
    return new TestBean();
}

在这里我希望/json/abc/json 调用相同的方法。
一种明显的解决方法是将type 声明为请求参数:

@RequestMapping(value = "/json", method = RequestMethod.GET)
public @ResponseBody TestBean testAjax(
        HttpServletRequest req,
        @RequestParam(value = "type", required = false) String type,
        @RequestParam("track") String track) {
    return new TestBean();
}

然后/json?type=abc&track=aa/json?track=rr 将起作用

【问题讨论】:

    标签: spring rest


    【解决方案1】:

    感谢保罗·沃德里普 在我的情况下,我使用 required。

    @RequestMapping(value={ "/calificacion-usuario/{idUsuario}/{annio}/{mes}", "/calificacion-usuario/{idUsuario}" }, method=RequestMethod.GET)
    public List<Calificacion> getCalificacionByUsuario(@PathVariable String idUsuario
            , @PathVariable(required = false) Integer annio
            , @PathVariable(required = false) Integer mes) throws Exception {
        return repositoryCalificacion.findCalificacionByName(idUsuario, annio, mes);
    }
    

    【讨论】:

      【解决方案2】:

      这是直接来自 baeldung 参考页面的答案:- https://www.baeldung.com/spring-optional-path-variables

      【讨论】:

        【解决方案3】:

        Nicolai Ehmann 的评论和 wildloop 的回答的简化示例(适用于 Spring 4.3.3+),基本上你现在可以使用required = false

          @RequestMapping(value = {"/json/{type}", "/json" }, method = RequestMethod.GET)
          public @ResponseBody TestBean testAjax(@PathVariable(required = false) String type) {
            if (type != null) {
              // ...
            }
            return new TestBean();
          }
        

        【讨论】:

          【解决方案4】:

          Spring 5 / Spring Boot 2 示例:

          阻塞

          @GetMapping({"/dto-blocking/{type}", "/dto-blocking"})
          public ResponseEntity<Dto> getDtoBlocking(
                  @PathVariable(name = "type", required = false) String type) {
              if (StringUtils.isEmpty(type)) {
                  type = "default";
              }
              return ResponseEntity.ok().body(dtoBlockingRepo.findByType(type));
          }
          

          反应性

          @GetMapping({"/dto-reactive/{type}", "/dto-reactive"})
          public Mono<ResponseEntity<Dto>> getDtoReactive(
                  @PathVariable(name = "type", required = false) String type) {
              if (StringUtils.isEmpty(type)) {
                  type = "default";
              }
              return dtoReactiveRepo.findByType(type).map(dto -> ResponseEntity.ok().body(dto));
          }
          

          【讨论】:

            【解决方案5】:

            你不能有可选的路径变量,但你可以有两个调用相同服务代码的控制器方法:

            @RequestMapping(value = "/json/{type}", method = RequestMethod.GET)
            public @ResponseBody TestBean typedTestBean(
                    HttpServletRequest req,
                    @PathVariable String type,
                    @RequestParam("track") String track) {
                return getTestBean(type);
            }
            
            @RequestMapping(value = "/json", method = RequestMethod.GET)
            public @ResponseBody TestBean testBean(
                    HttpServletRequest req,
                    @RequestParam("track") String track) {
                return getTestBean();
            }
            

            【讨论】:

            • @Shamik:在我看来,这是使用路径变量的一个令人信服的理由。组合增殖很快就会失控。
            • 实际上不是因为路径不能那么复杂,同时被可选组件填充。如果您有超过一个或最多两个可选路径元素,您应该认真考虑将其中一些转换为请求参数。
            • 对于某些人来说,让第二个控制器方法调用第一个控制器方法也可以工作,例如,如果可以通过其他方式提供不同的参数
            • 请考虑更新您的答案,而不是在较新版本的 Spring 中创建两个控制器方法,我们可以只使用 @RequestMapping 和两个值,如:stackoverflow.com/questions/17821731/…
            • omg 您希望如何维护这些端点?如果我们有 5 个而不是只有一个路径变量,请为我计算一下,你会做多少个端点?请帮我一个忙,将@PathVariable 替换为@RequestParam
            【解决方案6】:

            如果您使用 Spring 4.1 和 Java 8,则可以使用 @RequestParam@PathVariable@RequestHeader@MatrixVariable 在 Spring MVC 中支持的 java.util.Optional -

            @RequestMapping(value = {"/json/{type}", "/json" }, method = RequestMethod.GET)
            public @ResponseBody TestBean typedTestBean(
                @PathVariable Optional<String> type,
                @RequestParam("track") String track) {      
                if (type.isPresent()) {
                    //type.get() will return type value
                    //corresponds to path "/json/{type}"
                } else {
                    //corresponds to path "/json"
                }       
            }
            

            【讨论】:

            • 你确定这行得通吗?您自己的回答 here 表明如果路径中不存在 {type},则不会命中控制器。我认为 PathVariable Map 会是更好的方法,或者使用单独的控制器。
            • 是的,如果您只有"/json/{type}" 并且类型不存在,它将不会被击中(正如我的链接答案所暗示的那样),但在这里您有value = {"/json/{type}", "/json" }。因此,如果任何一个匹配控制器方法都会被命中。
            • 是否有可能相同的值等,类型也是RequestParam和RequestParam?
            • 它可以工作,但无论如何控制器的函数不会被调用,因为它需要一个参数
            • 这行得通,从 Spring 4.3.3 开始,您还可以使用 @PathVariable(required = false),如果变量不存在,则为 null。
            【解决方案7】:
            $.ajax({
                        type : 'GET',
                        url : '${pageContext.request.contextPath}/order/lastOrder',
                        data : {partyId : partyId, orderId :orderId},
                        success : function(data, textStatus, jqXHR) });
            
            @RequestMapping(value = "/lastOrder", method=RequestMethod.GET)
            public @ResponseBody OrderBean lastOrderDetail(@RequestParam(value="partyId") Long partyId,@RequestParam(value="orderId",required=false) Long orderId,Model m ) {}
            

            【讨论】:

            • 您可能想在答案中编辑一些文本,解释为什么您认为这有助于解决手头的问题(4 年后)。
            【解决方案8】:

            众所周知,您还可以使用 @PathVariable 注释注入路径变量的 Map。我不确定这个功能在 Spring 3.0 中是否可用,或者是否是后来添加的,但这里有另一种解决示例的方法:

            @RequestMapping(value={ "/json/{type}", "/json" }, method=RequestMethod.GET)
            public @ResponseBody TestBean typedTestBean(
                @PathVariable Map<String, String> pathVariables,
                @RequestParam("track") String track) {
            
                if (pathVariables.containsKey("type")) {
                    return new TestBean(pathVariables.get("type"));
                } else {
                    return new TestBean();
                }
            }
            

            【讨论】:

            • 我一直在使用它。当我想要一种方法来处理不同的 uri 类型时,这很方便,例如:{ "/json/{type}","/json/{type}/{ xyz}","/json/{type}/{abc}", "/json/{type}/{abc}/{something}","/json" }
            【解决方案9】:

            检查此Spring 3 WebMVC - Optional Path Variables。它显示了一篇关于对 AntPathMatcher 进行扩展以启用可选路径变量的文章,并且可能会有所帮助。所有致 Sebastian Herold 发表文章。

            【讨论】:

              【解决方案10】:

              你可以使用:

              @RequestParam(value="somvalue",required=false)
              

              用于可选参数而不是路径变量

              【讨论】:

              • 这似乎是特定于版本的。春季 3 不行。
              • 目前在 spring 3.1 项目中使用这种方法,文档说它适用于 2.5+,所以它绝对适用于 Spring 3。编辑:source
              • 是的,但这不是问题所在。问题中确实提到了使用 request 参数作为“一个明显的解决方法”,但问题本身是关于 path 参数的。这不是可选路径参数的解决方案。
              • PathVariable 和 RequestParam 不同。
              猜你喜欢
              • 2018-01-31
              • 2020-05-31
              • 1970-01-01
              • 2021-05-09
              • 2016-03-30
              • 2011-12-12
              • 1970-01-01
              • 2023-03-08
              • 1970-01-01
              相关资源
              最近更新 更多