Tomcat 没有在 Web 应用程序的上下文中添加斜杠

Posted

技术标签:

【中文标题】Tomcat 没有在 Web 应用程序的上下文中添加斜杠【英文标题】:Tomcat is not adding trailing slash to web app's context 【发布时间】:2012-06-18 19:33:29 【问题描述】:

如果输入的 url 没有它,我想让 Tomcat 自动在我的应用程序的上下文中添加一个尾部斜杠。

当我使用 Jetty 进行测试时,它会自动将斜杠添加到我的应用程序的上下文中,但 Tomcat 不会这样做。

我不确定一旦部署上下文将被命名,因为我将 WAR 交给其他人,所以 html 中的任何资源引用都是相对的。有没有办法让 Tomcat 自动重定向到相同的上下文并添加斜杠?

目前使用 Tomcat 7 和 Spring 3。

【问题讨论】:

请添加您想要做什么的示例,并说明为什么需要斜线? 基本上我需要让http://url.com/context 加载http://url.com/context/ Tomcat 为所有演示应用程序添加斜杠,但不是我的。当我使用 Jetty 运行应用程序时,尾部斜杠也会自动添加。斜杠是必需的,因为context/resources/ 有图像、css、js 等,并且它们在 html 中使用相对路径,所以例如src="resources/image.jpg" 【参考方案1】:

这是一个旧帖子,但从 Tomcat 7.0.67 开始,您需要将以下属性添加到您的 context.xml 文件中:

<Context mapperContextRootRedirectEnabled="true">...</Context>

根据 7.0.67 changelog:

将为上下文根和目录提供重定向的功能从映射器中添加尾随 / 移动到 DefaultServlet。这使得此类请求能够在进行重定向之前由任何已配置的阀门和过滤器处理。此行为可通过 Context 的 mapperContextRootRedirectEnabled 和 mapperDirectoryRedirectEnabled 属性进行配置,可用于恢复之前的行为。

在 Tomcat 上下文中 documentation:

mapperContextRootRedirectEnabled:如果启用,对 Web 应用程序上下文根的请求将在必要时由 Mapper 而不是默认的 Servlet 重定向(添加尾部斜杠)。这更有效,但具有确认上下文路径存在的副作用。如果未指定,则使用默认值 false。

【讨论】:

偷偷摸摸的Tomcat!我只是浪费了整整两天时间试图找出我的网络应用程序出了什么问题!重新吸取的教训:如果一切都失败了,RTFM! 这救了我的命,我认为mapperContextRootRedirectEnabled的默认值为true,所以你不需要添加它们。 是的,自 7.0.68 起默认已更改为“true” 这为我解决了一个问题。在 F5 负载均衡器后面运行的 Tomcat 上的 Spring MVC 应用程序。 根据我从 7.0.66 开始的更新日志:tomcat.apache.org/tomcat-7.0-doc/…【参考方案2】:

您的应用程序的 web.xml 似乎有一个到 "/*" 的映射。映射到"/*" 的 servlet 会导致 tomcat 将请求按原样传递给 Web 应用程序(即不重定向)。

要正确重定向,您必须将"/*" 映射更改为仅"/",后者表示默认servlet。

【讨论】:

+1 在我的例子中,我已经将 Spring Security 配置为拦截 /*。 Spring Security 是否有任何配置可用于添加斜杠?【参考方案3】:

Tomcat 会自动添加尾部斜杠。只需使用 Tomcat 提供的示例应用程序对其进行测试..

如果 - 由于某些特殊配置 - 它没有,我会编写一个过滤器来检查查询字符串并根据应用程序的需要进行重定向。很多时候这是无论如何都需要的(进行 http->https 重定向等)

【讨论】:

你是对的,Tomcat 会自动添加这些。我需要弄清楚为什么在我的应用程序中禁用它。 Tomcat前面还有其他服务器吗?阿帕奇,nginx等?那些可能会搞砸重定向.. 实际上,它前面的 rproxy 服务器可以通过为我添加斜杠来解决问题。我认为这个问题与 Spring MVC 接受我的上下文有关,而没有尾部斜杠作为有效 url。 Spring MVC 仅在代理和tomcat 处理后(包括重定向)才获取请求。我的直觉是代理搞砸了重定向,但你应该查看日志 这个答案已经过时了。请参阅@Pat 的回答。【参考方案4】:

您是否尝试过在 Tomcat 上使用 URL Rewrite? 这可能会有所帮助:http://code.google.com/p/urlrewritefilter/

如果没有帮助,请查看:URL rewrite in tomcat web.xml

【讨论】:

【参考方案5】:

Pat 的出色回答帮助我挖掘了更多关于此的细节。这似乎与某些版本的 Tomcat(7.0.67+ 的 Tomcat 7,以及 8.29 和 8.37 之间的 Tomcat 8)中的一些怪癖有关,这与会话 cookie 和 URL 重定向有关。

底线似乎是,如果 java 服务器创建路径特定的会话 cookie,其末尾带有斜线(如“/app_name/”),那么服务器还必须执行自动初始重定向(/app_name -- > /app_name/) ... 否则,会话 cookie 将不会随请求一起发送,并且它永远不会像您拥有有效会话一样查看服务器。这可能会导致从应用程序到身份验证的重定向循环。

在 Tomcat 中有一些配置可以控制这两种行为,但据我所知,它们在这些版本中基本上是不同步的,因此可能会得到 cookie 的尾随斜线,没有获得重定向。 Tomcat 更改日志中有几个相关的问题/更改: https://tomcat.apache.org/tomcat-8.0-doc/changelog.html

正如 Pat 已经指出的,这可以通过将此属性添加到应用的 Context 元素来解决:

<Context mapperContextRootRedirectEnabled="true">

【讨论】:

以上是关于Tomcat 没有在 Web 应用程序的上下文中添加斜杠的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Tomcat 7.0 中设置 Web 应用程序的上下文路径

当我的tomcat关闭时,没有调用spring bean的destroy-method

如何在 tomcat 容器中安装 servlet 并将其加载到每个 Web 应用程序的上下文中?

tomcat的缺省servlet如何处理静态资源

在Tomcat上发布JNDI资源

需要在 Tomcat 中运行同一个 Web 应用程序的多个实例