如果找不到,@ PathVariable可以返回null吗?

时间:2011-03-30 23:44:25

标签: java spring-3 spring-annotations path-variables

如果路径变量不在url中,是否可以使@PathVariable返回null?否则我需要做两个处理程序。一个用于/simple,另一个用于/simple/{game},但两者都做同样的事情,如果没有定义游戏我从列表中选择第一个但是如果有游戏参数定义则我使用它。

@RequestMapping(value = {"/simple", "/simple/{game}"}, method = RequestMethod.GET)
public ModelAndView gameHandler(@PathVariable("example") String example,
            HttpServletRequest request) {

这是我在尝试打开页面/simple时得到的结果:

  

引起:java.lang.IllegalStateException:在@RequestMapping中找不到@PathVariable [example]

6 个答案:

答案 0 :(得分:30)

它们不能是可选的,不是。如果需要,您需要两种方法来处理它们。

这反映了路径变量的本质 - 它们对于它们是无效的。 REST样式的URL始终需要完整的URL路径。如果您有可选组件,请考虑将其作为请求参数(即使用@RequestParam)。这更适合于可选参数。

答案 1 :(得分:26)

正如其他人已经提到的那样,当你明确提到路径参数时,你不能指望它们为null。但是,您可以执行以下操作作为解决方法 -

@RequestMapping(value = {"/simple", "/simple/{game}"}, method = RequestMethod.GET)
public ModelAndView gameHandler(@PathVariable Map<String, String> pathVariablesMap,
            HttpServletRequest request) {
    if (pathVariablesMap.containsKey("game")) {
        //corresponds to path "/simple/{game}"
    } else {
        //corresponds to path "/simple"
    }           
}

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

@RequestMapping(value = {"/simple", "/simple/{game}"}, method = RequestMethod.GET)
public ModelAndView gameHandler(@PathVariable Optional<String> game,
            HttpServletRequest request) {
    if (game.isPresent()) {
        //game.get()
        //corresponds to path "/simple/{game}"
    } else {
        //corresponds to path "/simple"
    }           
}

答案 2 :(得分:19)

你总是可以这样做:

@RequestMapping(value = "/simple", method = RequestMethod.GET)
public ModelAndView gameHandler(HttpServletRequest request) {
    gameHandler2(null, request)
}

@RequestMapping(value = "/simple/{game}", method = RequestMethod.GET)
public ModelAndView gameHandler2(@PathVariable("game") String game,
        HttpServletRequest request) {

答案 3 :(得分:1)

@RequestMapping(value = {"/simple", "/simple/{game}"}, method = RequestMethod.GET)
public ModelAndView gameHandler(@PathVariable(value="example",required = false) final String example)

尝试这种方法,对我有用。

答案 4 :(得分:0)

我刚刚刚刚进行了测试,但是通过结合以上解决方案,我得到了:

@RequestMapping(value = {"/simple", "/simple/{game}"}, method = RequestMethod.GET)
public ModelAndView gameHandler(@PathVariable(value = "game", required = false) String example,
                                HttpServletRequest request) {
    if (example != null) {
        //...
    } else {
        //pick first, ...
    }
}

现在,当您使用“ / simple”时,字符串示例将为null而不是引发Exception。

简短的解决方案,没有花哨的Optional <>或Map <>

答案 5 :(得分:0)

我们可以在带有路径变量组合的显式映射的控制器中编写多个方法,以排除可选变量(如果使用旧版本的Spring)

在我的场景中,我想开发一个API来获取旧设备的回收价值,其中参数可以是品牌,型号和网络,但是网络是一种选择。

处理此问题的一个选项是使用network作为请求参数,而不是pathVariable。 例如/ value / LG / g3?network = vodafone,但是我不喜欢这种方法。

对我来说,下面使用的更清洁 / refurbValue / LG / g3 / refurbValue / LG / g3 / vodafone

   @RequestMapping(value = "/refurbValue/{make}/{model}/{network}", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
def getRefurbValueByMakeAndModelAndNetwork(@PathVariable String make, @PathVariable String model, @PathVariable String network ) throws Exception {
    //logic here
}

@RequestMapping(value = "/refurbValue/{make}/{model}", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
def getRefurbValueByMakeAndModel(@PathVariable String make, @PathVariable String model) throws Exception {
    //logic here
}

在上面的示例中,两个控制器可以使用相同的服务方法,并且可以完成参数的处理。就我而言,我使用的是Groovy,因此很容易与可选参数一起使用

地图getRefurbValue(字符串品牌,字符串模型,字符串网络=“”)