如何将带有尾部斜杠的URL重定向到没有它的相应URL?

Spring MVC (3.0) 将带有和不带尾部斜杠的 URL 视为同一 URL。

例如:

http://www.example.org/data/something = http://www.example.org/data/something/

我需要使用尾部斜杠重定向网址

http://www.example.org/data/something/

到没有它的网址:

http://www.example.org/data/something

我需要在应用程序内部执行此操作(因此不要通过Apache等重写规则)。

一种方法是:

@ResponseStatus(value=HttpStatus.MOVED_PERMANENTLY)
@RequestMapping(value = "/data/something/")
public String dataSomethingRedirect(...) {
    return "redirect:/data/something";
}

但这通常有2个问题:

  1. 控制器太多
  2. 参数问题:如编码错误

问题

有没有办法拦截所有URL,如果它们有尾随斜杠,请将它们重定向到没有斜杠的相对URL?


答案 1

您可以在 Web 配置中列出所需的所有重写规则

如果其中不多,则可以像这样配置重定向视图

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addRedirectViewController("/my/path/", "/my/path")
      .setKeepQueryParams(true)
      .setStatusCode(HttpStatus.PERMANENT_REDIRECT); 
}

或者,您可以创建自定义处理程序接收器

但是拦截器在请求映射到特定之前发生,您无法知道该上下文中的控制器和操作。Controller.action

你所拥有的只是HTTPServlet API和请求+响应;所以你可以:

response.sendRedirect("http://example.org/whitout-trailing-slash");

您不想阅读的答案

在考虑 HTTP 时,此行为(带有尾部斜杠的 URL = 没有它的 URL)是完全“有效的”。至少这是Spring的默认行为,你可以用它来禁用(参见javadoc)。useTrailingSlashMatch

因此,在前端服务器上使用重写/重定向规则可能是一个解决方案;但同样,我不知道你的限制(也许你可以详细说明这一点,我们可以找出其他解决方案?


答案 2

我认为你最好的选择是在进入Spring web的servlet之前,使用UrlRewriteFilter来做到这一点。这将确保您的重定向规则不会影响控制器。

请注意,您在 .war 项目中编写规则,而不是在具有mod_rewrite的 apache 中编写规则。

转到此处查看googlecode上的库项目。

在 urlrewrite 中.xml写:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.1//EN" "http://www.tuckey.org/res/dtds/urlrewrite3.1.dtd">
<urlrewrite>
    <rule match-type="regex">  
      <note>Remove trailing slash</note>
      <from>^(.*)/$</from>
      <to type="redirect">$1</to>
    </rule>  
</urlrewrite>

在应用程序的 Web.xml中,添加 :

<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
       <init-param>
            <param-name>confPath</param-name>
            <param-value>/WEB-INF/urlrewrite.xml</param-value>
        </init-param>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

请注意,web中过滤器的声明顺序.xml很重要,因此请尝试在春季之前声明此顺序。

当然,这只是UrlRewriteFilter所能做的一小部分。

问候。