0

我正在尝试编写最简单的 Spring 应用程序,它在 @RequestMapping 中使用多个路径元素。例如,/appcontext/blog/hello-world.html 应该在请求映射中工作(显然 /appcontext 是我的应用程序的上下文)。

Spring可以做这样的事情吗?当它只映射一件事时,我让它很容易工作。例如:

@RequestMapping("你好世界")

工作并将匹配 /hello-world.do , /anything/hello-world.do ,但我的问题是,如果它在 /blog 路径中​​,我试图只匹配 hello-world ,并且每当我使用类似的东西时:

@RequestMapping("/blog/hello-world")

它永远不会触发。

服务器日志例如:

INFO:   Mapped "{[/blog/hello],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String mainweb.BlogController.foo()

看起来它应该可以工作(这是我唯一的请求映射),但是:

WARNING:   No mapping found for HTTP request with URI [/context/blog/hello.html] in DispatcherServlet with name 'dispatcher'

Spring可以做这样的事情吗?我不想把我所有的请求映射都放在 / 中,因为它会一团糟。

我开始工作的唯一映射是:

@RequestMapping("/**")

从那里,我可以直接查看 HttpServletRequest 对象,但这似乎破坏了拥有@RequestMapping 的全部意义。

这是我的控制器:

@Controller
public class BlogController {
    private static final Logger LOG = Logger.getLogger(BlogController.class.getName());

    @RequestMapping("/blog/hello")
    public String foo1() {
        LOG.info("foo1");
        return "nothing";
    }

    @RequestMapping("/blog/hello.html")
    public String foo2() {
        LOG.info("foo2");
        return "nothing";
    }
    @RequestMapping("/blog/hello.*")
    public String foo3() {
        LOG.info("foo3");
        return "nothing";
    }
    @RequestMapping("/blog/**")
    public String foo4() {
        LOG.info("foo4");
        return "nothing";
    }
    @RequestMapping("/blog/{path}")
    public String foo5(@PathVariable String path) {
        LOG.info("foo5 " + path);
        return "nothing";
    }
    // added this as a test - it's the only way that this controller works
    @RequestMapping("/**")
    public String foo6() {
        LOG.info("foo6");
        return "nothing";
    }
}

如果我没有 foo6 映射,那么无论我去什么 URL,这都不起作用。

当我使用该控制器时,服务器日志中会显示以下内容:

INFO:   Mapped "{[/blog/hello],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String mainweb.BlogController.foo1()
INFO:   Mapped "{[/blog/hello.html],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String mainweb.BlogController.foo2()
INFO:   Mapped "{[/blog/hello.*],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String mainweb.BlogController.foo3()
INFO:   Mapped "{[/blog/**],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String mainweb.BlogController.foo4()
INFO:   Mapped "{[/blog/{path}],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String mainweb.BlogController.foo5(java.lang.String)
INFO:   Mapped "{[/**],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String mainweb.BlogController.foo6()

但是同样,如果我把它放进去,除了 foo6 之外什么都不会触发。

谢谢!

编辑:我创建了一个非常简单的项目,它只有一个类 Controller 和一个方法 RequestMapping。这个项目除了不工作之外什么都不做。除了使用通配符之外,根本没有办法让@RequestMapping 做任何事情。这似乎是 Spring 中的一个严重错误。所有文档都说@RequestMapping 不仅仅映射一个通配符。

4

2 回答 2

0

Figured it out. The servlet-mapping chops off part of the path! The servlet-mapping basically creates a mini-context. I didn't know it did that, and it's not intuitively obvious, but that's what's happening.

于 2013-11-06T18:18:32.280 回答
0

在我看来,它没有映射到 /blog 路径的原因是您没有使用该路径来访问它。

根据您在上述问题中发布的错误,您已定义/映射:

/blog/hello

而您正在尝试访问:

/context/blog/hello.html

即,您在 URI 前面加上“/context”,并在后面加上“.html”。这就是它没有响应的原因。

我建议尝试访问您已映射的 URI。但是,您可能还需要确保应用程序的根上下文是正确的。

请注意,通过添加“.html”后缀,您没有使用您定义的路径。如果您希望使用诸如此类的随机后缀,那么也可以在映射中使用通配符。即@RequestMapping(value = "/blog/hello**")

但是,如果可以避免使用通配符,我通常建议不要使用它,因为当您向应用程序添加更多映射时,它们可能会引发一些意外。

编辑 - 我也刚刚发现您的控制器更加混乱了这些映射。只需一起阅读以下映射:@RequestMapping("/blog/hello") @RequestMapping("/blog/hello.html") @RequestMapping("/blog/hello.*")

您的映射相互冲突。该列表中的第一个映射是其他映射的子集,因此它将用于匹配任何这些映射的任何 URL。即第二个2是多余的。您可以通过将“裸”/blog/hello 放在其他 2 之后来潜在地解决此问题,以便首先获取更具体的映射,但是,依赖于编写方法的顺序似乎是在自找麻烦我。

于 2013-11-06T09:11:38.550 回答