使用Spring 3.0,我可以创建一个可选的路径变量吗?

Sha*_*mik 175 rest spring

使用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();
}
Run Code Online (Sandbox Code Playgroud)

在这里,我想/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();
}
Run Code Online (Sandbox Code Playgroud)

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

ear*_*las 183

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

@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();
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上并不是因为在填充可选组件时路径不会那么复杂.如果您有多个或最多两个可选路径元素,您应该认真考虑将其中一些转换为请求参数. (7认同)
  • @Shamik:在我看来,这是一个令人信服的理由*不*使用路径变量.组合增殖很快就会失控. (5认同)
  • 请考虑更新您的答案,而不是在较新版本的Spring中创建两个控制器方法,我们可以只使用带有两个值的@RequestMapping,如下所示:http://stackoverflow.com/questions/17821731/spring-mvc-how-to指明是否需要路径变量 (2认同)

Ani*_*kur 106

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

@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"
    }       
}
Run Code Online (Sandbox Code Playgroud)

  • 这是有效的,从Spring 4.3.3开始,你也可以使用`@PathVariable(required = false)`并且如果变量不存在则得到null. (12认同)
  • 是的,如果您只有``/ json/{type}"`并且类型不存在则不会被命中(正如我的链接答案所示)但是这里你有`value = {"/ json/{type}","/json"}`.因此,如果任何一个匹配控制器方法将被命中. (4认同)

小智 74

众所周知,您还可以使用@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();
    }
}
Run Code Online (Sandbox Code Playgroud)


Mal*_*k13 23

你可以使用:

@RequestParam(value="somvalue",required=false)
Run Code Online (Sandbox Code Playgroud)

对于可选参数而不是pathVariable

  • 没错,但这不是问题所在.使用*request*参数确实在问题中提到*"一个明显的解决方法"*,但问题本身是关于*path*参数.这不是可选路径参数的解决方案. (22认同)
  • PathVariable和RequestParam是不同的. (9认同)
  • 目前使用此方法进行spring 3.1项目,并且文档说它适用于2.5+,因此它绝对适用于Spring 3.编辑:[来源](http://static.springsource.org/spring/docs/3.0 .X/API /组织/ springframework的/网络/结合/注解/ RequestParam.html). (5认同)

wil*_*oop 9

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));
}
Run Code Online (Sandbox Code Playgroud)

反应性

@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));
}
Run Code Online (Sandbox Code Playgroud)


rog*_*ack 7

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();
  }
Run Code Online (Sandbox Code Playgroud)