Как перенаправить URL-адреса с завершающим косой чертой на соответствующие без него?
Spring MVC (3.0) рассматривает URL-адреса с и без конечных косых черт как один и тот же URL-адрес.
Например:
http://www.example.org/data/something= http://www.example.org/data/something/
Мне нужно перенаправить URL с завершающими косой чертой
http://www.example.org/data/something/
к URL без него:
http://www.example.org/data/something
Мне нужно сделать это внутри приложения (так что не переписывайте правила через Apache и т.д.).
Способ сделать это:
@ResponseStatus(value=HttpStatus.MOVED_PERMANENTLY)
@RequestMapping(value = "/data/something/")
public String dataSomethingRedirect(...) {
return "redirect:/data/something";
}
но у этого обычно есть 2 проблемы:
- слишком много контроллеров
- проблема с параметрами: как неправильное кодирование
Вопрос
Есть ли способ перехватить все URL-адреса и в случае, если они имеют завершающую косую черту, перенаправить их на относительный без косой черты?
Ответы
Ответ 1
Вы можете перечислить все правила перезаписи, которые вам нужны в вашей веб-конфигурации
Если их не так много, вы можете настроить такие виды переадресации, как это.
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/my/path/", "/my/path")
.setKeepQueryParams(true)
.setStatusCode(HttpStatus.PERMANENT_REDIRECT);
}
Или вы можете создать пользовательский HandlerInterceptor
Но перехватчики возникают до того, как запросы сопоставлены с конкретным Controller.action
, и вы не можете знать контроллеры и действия в этом контексте.
Все, что у вас есть, это API HTTPServlet и запрос + ответ; поэтому вы можете:
response.sendRedirect("http://example.org/whitout-trailing-slash");
Ответ, который вы не хотите читать
Это поведение (URL с конечным слэш = URL без него) отлично "допустимо" при рассмотрении HTTP. По крайней мере, это поведение по умолчанию с Spring, которое можно отключить с помощью useTrailingSlashMatch
(см. Javadoc).
Таким образом, использование правил перезаписи/переадресации на интерфейсном сервере может быть решением; но опять же, я не знаю ваших ограничений (может быть, вы могли бы разобраться в этом, и мы могли бы найти другие решения?).
Ответ 2
Я думаю, что вам лучше всего сделать это, прежде чем войти в веб-сервлет Spring, используя UrlRewriteFilter. Это гарантирует, что ваши правила перенаправления не повлияют на ваши контроллеры.
Обратите внимание, что вы пишете правила в своем проекте .war, а не в apache с mod_rewrite.
Перейдите сюда для проекта библиотеки на 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 важен, поэтому попробуйте объявить это перед чем-либо из spring.
Конечно, это лишь часть того, что может сделать UrlRewriteFilter.
С уважением.
Ответ 3
Это обычно работает для меня с URLRewriteFilter в 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>
Ответ 4
Не уверен, что это было spring 3.0, но spring 3.1 RequestMappingHandlerMapping позволяет установить свойство useTrailingSlashMatch. По умолчанию это верно.
Я думаю, что переключение на false приведет к решению вашей проблемы, однако это повлияет на ВСЕ-сопоставления, обрабатываемые RequestMappingHandlerMapping в вашем приложении... поэтому у вас может быть справедливое количество регрессий.
Ответ 5
Я согласен с @Brian Clozel: я не думаю, что это хорошая идея делать то, что вы хотите. Итак, зачем вам это нужно?
В любом случае, я думаю, что самым простым решением является создание пользовательского javax.servlet.Filter
. Таким образом, никакая зависимость Spring. Если URL-адрес запроса заканчивается косой чертой, вам просто нужно перенаправить на тот же URL без него. Но предостережение:
-
Все параметры (GET и POST) должны быть добавлены как параметры GET. Вы уверены, что ваше приложение является агностическим?
-
У вас могут быть проблемы с кодировкой. В фильтре вы можете кодировать POST-параметры требуемой кодировке. Но кодировка по умолчанию для параметров GET не настроена в вашем приложении. Конфигурируется в server.xml(если Tomcat), а значение по умолчанию - ISO-8859-1.
Удачи!
Ответ 6
Основываясь на SEO, я думаю, что важно сделать различие.
Если URL-адрес, который заканчивается в концевой косой черты, существует, индексируется в поисковых системах и есть ссылки в Интернете, требуется постоянное перенаправление (301), как говорит Уддхав Камбли. Стандартное перенаправление (302) будет лучше, чем дублированный URL-адрес, но недостаточно.
Однако, если URL-адрес никогда не существовал, он не индексируется в Интернете и внешних ссылок нет, URL-адрес не существует. Поэтому 404, страница не найдена, лучше подходит.
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>
И чтобы завершить настройку...
добавить в 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>