在春天,如果PathVariable包含RequestMapping值

时间:2018-02-01 05:48:06

标签: spring request-mapping path-variables

如果我想创建一个带有RequestMapping =“/ {content}”的基本控制器来处理一般情况。但是对于某些特定的内容,我想为这种特殊情况创建一个具体的控制器,并从该基本控制器继承。

例如:

@RequestMapping(value = "/{content}")
class ContentController {

    public ContentController(@PathVariable String content) { ... }

}


@RequestMapping(value = "/specialContent")
class SpecialContentController extends ContentController {

    public SpecialContentController() { super("specialContent"); }

    // overwrite sth
    ....

} 

这合法吗?还是其他一些更好的实施?

2 个答案:

答案 0 :(得分:0)

@PathVariable不应该在构造函数中使用。

答案 1 :(得分:0)

你似乎对春天的控制器如何工作感到困惑。

控制器是singleton,它是在应用程序upstart上创建的,其方法被调用以处理传入的请求。

因为你的控制器不是为每个请求创建的,而是在处理任何请求之前创建的,所以你不能在构造函数中使用路径变量 - 因为在创建实例时没有关于它的值的信息,而且因为你会希望它反映当前正在处理的请求,并且由于控制器可以同时处理多个请求,因此您无法将其作为类属性存储,或者多个请求会相互干扰。

为了达到你想要的效果,你应该使用方法并将它们组合起来,如下所示:

@RestController
public class ContentController {

    @GetMapping("/specialContent")
    public Map<String, String> handleSpecialContent() {
        Map<String, String> map = handleContent("specialContent");
        map.put("special", "true");
        return map;
    }

    @GetMapping("/{content}")
    public Map<String, String> handleContent(@PathVariable String content) {
        HashMap<String, String> map = new HashMap<>();
        map.put("content", content);
        return map;
    }

}

请注意{content:^(?!specialContent$).*$}中的正则表达式,以确保Spring永远不会在那里路由 specialContent 。您可以获得正则表达式here的解释,并使用它来玩具here

如果我们进行测试,你可以看到它有效:

$ http localhost:8080/test
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Date: Thu, 01 Feb 2018 08:18:11 GMT
Transfer-Encoding: chunked

{
    "content": "test"
}

$ http localhost:8080/specialContent
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Date: Thu, 01 Feb 2018 08:18:15 GMT
Transfer-Encoding: chunked

{
    "content": "specialContent",
    "special": "true"
}