34

@PathVariable如果路径变量不在 url 中,是否可以返回 null ?否则我需要做两个处理程序。一个 for/simple和另一个 for /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 [示例]

4

6 回答 6

37

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

这反映了路径变量的性质——它们为空没有任何意义。REST 样式的 URL 始终需要完整的 URL 路径。如果您有一个可选组件,请考虑将其设为请求参数(即使用@RequestParam)。这更适合可选参数。

于 2011-03-30T23:48:05.987 回答
36

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

@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,您可以使用 java.util.Optional,它在@RequestParamSpring MVC中受支持@PathVariable@RequestHeader@MatrixVariable

@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"
    }           
}
于 2016-01-08T06:32:49.670 回答
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) {
于 2011-12-12T17:45:42.580 回答
3
@RequestMapping(value = {"/simple", "/simple/{game}"}, method = RequestMethod.GET)
public ModelAndView gameHandler(@PathVariable(value="example",required = false) final String example)

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

于 2018-08-14T06:48:31.490 回答
1

我刚刚测试了这个,但是通过结合上面的解决方案,我得到了这个:

@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”时,字符串示例将为空,而不是抛出异常。

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

于 2019-12-27T05:02:27.320 回答
0

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

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

处理此问题的一种选择是使用网络作为请求参数而不是 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,因此它很容易与可选参数一起使用,例如

Map getRefurbValue(String brand, String model, String network="")

于 2020-10-12T12:41:37.457 回答