How to redirect URLs with trailing slash to the co

2019-01-17 11:24发布

Spring MVC (3.0) considers URLs with and without trailing slashes as the same URL.

For example:

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

I need to redirect the URL with trailing slashes

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

to the URL without it:

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

I need to do this internally the application (so not rewrite rules via Apache, etc).

A way to do it is:

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

but this has generally 2 problems:

  1. too many controllers
  2. problem with parameters: like wrong encoding

Question

Is there a way to intercept all the URLs and in case they have a trailing slash, redirect them to the relative one without slash?

7条回答
Rolldiameter
2楼-- · 2019-01-17 11:46

I think you best option would be to do this before entering in Spring web's servlet, using UrlRewriteFilter. This will ensure that your redirect rules would not impact your controllers.

Please note that you write the rules in your .war project, not in an apache with mod_rewrite.

Go here for the library's project on googlecode.

in the urlrewrite.xml write :

<?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>

In the web.xml of your application, add :

<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>

Beware, the declaration order of the filters in the web.xml is important, so try to declare this one before anything from spring.

Of course, this is but a fraction of what UrlRewriteFilter can do.

Regards.

查看更多
贪生不怕死
3楼-- · 2019-01-17 11:48

Based on SEO, I think it is important to make a distinction.

If the URL that finished in the trailing slash exist, is indexed in the search engines and there are links on Internet, a permanent redirection (301) is required as Uddhav Kambli says. The standard redirection (302) will be better than having a duplicated URL, but is not good enough.

However, if the URL never existed, it is not indexed on Internet and there are no external links, the URL does not exist. Therefore a 404, page not found, is a better fit.

WEB-INF/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>
        <set type="status">404</set>
        <to>null</to>
    </rule>
</urlrewrite>

And in order to complete the configuration ...

add to WEB-INF/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>

Maven

<dependency>
    <groupId>org.tuckey</groupId>
    <artifactId>urlrewritefilter</artifactId>
    <version>4.0.3</version>
</dependency>
查看更多
祖国的老花朵
4楼-- · 2019-01-17 11:56

I have found that this can also be handled much more simply by using an ErrorViewResolver bean somewhere in your @Configuration:

@Autowired
private DefaultErrorViewResolver defaultErrorViewResolver;

@Bean
ErrorViewResolver errorViewResolver() {
    return new ErrorViewResolver() {
        @Override
        public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
            if(model.containsKey("path") && !model.get("path").toString().endsWith("/")) {
                return new ModelAndView("redirect:"+model.get("path") + "/");
            }
            return defaultErrorViewResolver.resolveErrorView(request, status, model);
        }
    };
}

I'm not sure if this is good or bad practice, but it is effective in my circumstance, and does exactly what I need it to do for an arbitrary path 'foo': respond with a 302 redirect to /foo/ when you request /foo and respond as it should when you request /foo.

查看更多
forever°为你锁心
5楼-- · 2019-01-17 11:57

Not sure if spring 3.0 had this, but spring 3.1 RequestMappingHandlerMapping allows you to set a "useTrailingSlashMatch" property. By default it is true.

I think switching it to false would solve your issue, however it would affect ALL mappings handled by RequestMappingHandlerMapping across your application... so you may have a fair amount of regression to do.

查看更多
Deceive 欺骗
6楼-- · 2019-01-17 11:57

I agree with @Brian Clozel: I don't think is a good idea to do what you want. So, why you need it?

Anyway, I think the simplest solution is to write a custom javax.servlet.Filter. So, no Spring dependency. If the request URL ends with slash you just have to redirect to the same url without it. But caution:

  • All parameters (GET and POST) must be added as GET parameters. Are you sure that your application is method agnostic?

  • You can have some problems with encoding. In the filter you can encode POST parameters to the required encoding. But the default encoding for GET parameters is not configured in your application. Is configured in server.xml (if Tomcat) and default value is ISO-8859-1.

Good luck!

查看更多
女痞
7楼-- · 2019-01-17 12:03

This usually works for me with URLRewriteFilter in Spring.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN" 
 "http://www.tuckey.org/res/dtds/urlrewrite3.2.dtd">
<urlrewrite>
    <rule>
         <note>Remove trailing slash for SEO purposes</note>
         <from>/**/</from>
         <to type="permanent-redirect">%{context-path}/$1</to>
    </rule>
</urlrewrite>
查看更多
登录 后发表回答