Spring 具有多个path元素的RequestMapping

Spring 具有多个path元素的RequestMapping,spring,mapping,Spring,Mapping,我正在尝试编写最简单的Spring应用程序,它在@RequestMapping中使用多个path元素。例如,/appcontext/blog/hello-world.html应该在请求映射中工作(显然/appcontext是我的应用程序的上下文) 春天能做这样的事吗?当它只映射一件事情时,我就可以轻松地工作。例如: INFO: Mapped "{[/blog/hello],methods=[],params=[],headers=[],consumes=[],produces=[],cust

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

春天能做这样的事吗?当它只映射一件事情时,我就可以轻松地工作。例如:

INFO:   Mapped "{[/blog/hello],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String mainweb.BlogController.foo()
@请求映射(“hello world”)

工作并将匹配/hello-world.do、/anything/hello-world.do,但我的问题是,如果hello-world位于/blog路径中,并且每当我使用以下内容时,我都会尝试只匹配hello-world:

@请求映射(“/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'
春天能做这样的事吗?我不想把所有的请求映射都放在/,因为这将是一片混乱

我唯一能做的映射是:

@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之外,什么都不会触发

谢谢大家!


编辑:我创建了一个非常简单的项目,它只有一个类,控制器和一个方法,RequestMapping。这个项目除了不起作用外什么都不做。除了使用通配符外,根本无法让@RequestMapping执行任何操作。这似乎是春天的一个关键错误;所有文档都说@RequestMapping不仅仅映射一个通配符。

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

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

/blog/hello
鉴于您正试图访问:

/context/blog/hello.html
i、 e.您正在用“/context”作为URI的前缀,并用“.html”作为其后缀。这就是为什么它没有反应

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

请注意,通过添加“.html”后缀,您没有使用您定义的路径。如果您希望使用这样的随机后缀,那么也可以在映射中使用wildrcards。i、 e.@RequestMapping(value=“/blog/hello**”)

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

编辑-我刚刚还发现,您的控制器正在进一步破坏这些映射。只需一起阅读以下映射: @请求映射(“/blog/hello”) @RequestMapping(“/blog/hello.html”) @请求映射(“/blog/hello.*”)


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

解决了这个问题。servlet映射切掉了部分路径!servlet映射基本上创建了一个小型上下文。我不知道它会这样做,直观上也不明显,但事实就是如此。

在服务器日志中,它显示了完整的URI。web应用程序根本不应该看到上下文元素。我无法想象我需要将上下文硬编码到我的RequestMapping中?如果我这样做,那就是春天的设计缺陷。如果可以避免的话,我绝对不想使用通配符。我真正想要的是使用类似于{path}的东西从路径中获取变量,但如果存在另一个path元素,则似乎不支持这样做。我的理想是像我的foo5方法一样,但是Spring支持吗?Spring中没有bug。这通常意味着您错误配置了web服务器。是web服务器定义了将传递给Spring的上下文。鉴于您的配置将“/context”作为上下文传递,我建议您在web服务器配置中查找该文本。我认为这是Spring中的一个bug。我将应用程序更改为在根上下文中运行,行为没有变化。我的foo1到foo5方法在那里,我仍然得到“在DispatcherServlet中找不到URI为[/blog/hello.html]的HTTP请求的映射”,即使它清楚地表明/blog/hello.html、/blog/hello等在映射中。这都是Spring 3.2.4。我将尝试将它放在一个最小的示例项目中,并在其上提交一个bug。因此,您现在已经修复了您的上下文(它现在说的是/blog/hello.html,而不是/context/blog/hello.html)。但是,如果您仍在使用上面的控制器,那么它将无法工作。这里到处都是冲突映射。我删除了除foo1方法之外的所有方法,以删除任何冲突。在这一点上,我的整个应用程序是一个控制器和一个@RequestMapping,它不工作。唯一有效的是通配符映射。我可以这样做,让一个方法检查URI,然后将请求发送到其他方法,但这看起来相当笨拙。当然有更好的方法吗?