Java 如何将带有尾随斜杠的URL重定向到不带斜杠的相应URL?
SpringMVC(3.0)将带有或不带有斜杠的URL视为同一URL 例如: = 我需要用后面的斜杠重定向URL 不带URL的URL: 我需要在应用程序内部执行此操作(因此不要通过Apache等重写规则) 一种方法是:Java 如何将带有尾随斜杠的URL重定向到不带斜杠的相应URL?,java,spring,spring-mvc,redirect,model-view-controller,Java,Spring,Spring Mvc,Redirect,Model View Controller,SpringMVC(3.0)将带有或不带有斜杠的URL视为同一URL 例如: = 我需要用后面的斜杠重定向URL 不带URL的URL: 我需要在应用程序内部执行此操作(因此不要通过Apache等重写规则) 一种方法是: @ResponseStatus(value=HttpStatus.MOVED_PERMANENTLY) @RequestMapping(value = "/data/something/") public String dataSomethingRedirect(...) {
@ResponseStatus(value=HttpStatus.MOVED_PERMANENTLY)
@RequestMapping(value = "/data/something/")
public String dataSomethingRedirect(...) {
return "redirect:/data/something";
}
但这通常有两个问题:
有没有办法截取所有URL,如果它们有一个尾随斜杠,将它们重定向到没有斜杠的相对URL?我认为最好的选择是在进入SpringWeb的servlet之前,使用UrlRewriteFilter这样做。这将确保重定向规则不会影响控制器 请注意,这些规则是在.war项目中编写的,而不是在带有mod_rewrite的apache中编写的 图书馆的谷歌代码项目 在urlrewrite.xml文件中写入:
删除尾部斜杠
^(.*)/$
$1
在应用程序的web.xml中,添加:
URL重写过滤器
org.tuckey.web.filters.urlrewrite.UrlRewriteFilter
confPath
/WEB-INF/urlrewrite.xml
URL重写过滤器
/*
要求
请注意,web.xml中过滤器的声明顺序很重要,因此请在spring中的任何内容之前声明此过滤器
当然,这只是URLEwriteFilter功能的一小部分
注意。您可以在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);
}
或者您可以创建一个自定义
但是拦截器发生在请求映射到特定的控制器.action
之前,您无法了解该上下文中的控制器和操作
您所拥有的只是HTTPServlet API和请求+响应;因此,您可以:
response.sendRedirect("http://example.org/whitout-trailing-slash");
你不想读的答案
当考虑HTTP时,这种行为(带有尾随斜杠的URL=URL不带斜杠)是完全“有效”的。至少这是Spring的默认行为,您可以使用useTrailingSlashMatch
()禁用它
因此,在前端服务器上使用重写/重定向规则可能是一个解决方案;但是,我也不知道你的限制(也许你可以详细说明一下,我们可以找出其他解决方案?)我同意@Brian Clozel的观点:我认为做你想做的事不是一个好主意。那么,你为什么需要它 无论如何,我认为最简单的解决方案是编写一个定制的
javax.servlet.Filter
。因此,没有Spring依赖性。如果请求URL以斜杠结尾,您只需重定向到没有斜杠的相同URL即可。但请注意:
- 所有参数(GET和POST)都必须作为GET参数添加。您确定您的应用程序是方法无关的吗
- 您可能会在编码方面遇到一些问题。在过滤器中,您可以将POST参数编码为所需的编码。但未在应用程序中配置GET参数的默认编码。在server.xml(如果是Tomcat)中配置,默认值为ISO-8859-1
祝你好运 这通常适用于我在春天使用URLEwriteFilter
<?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>
删除尾部斜杠以进行搜索引擎优化
/**/
%{上下文路径}/$1
不确定spring 3.0是否有此功能,但spring 3.1允许您设置“useTrailingSlashMatch”属性。默认情况下,这是真的
我认为将其切换为false可以解决您的问题,但是它会影响整个应用程序中由RequestMappingHandlerMapping处理的所有映射。。。因此,您可能需要进行大量的回归。基于SEO,我认为区分是很重要的 如乌德哈夫·坎布里所说,如果在尾部斜杠中结束的URL存在,在搜索引擎中被索引,并且在互联网上有链接,则需要永久重定向(301)。标准重定向(302)比使用重复的URL要好,但还不够好 但是,如果URL不存在,它不会在Internet上建立索引,并且没有外部链接,则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>
删除尾部斜杠
^(.+)/$
404
无效的
为了完成配置
添加到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>
URL重写过滤器
org.tuckey.web.filters.urlrewrite.UrlRewriteFilter
confPath
/WEB-INF/urlrewrite.xml
URL重写过滤器
/*
要求
马文
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>4.0.3</version>
</dependency>
org.tuckey
URL重写过滤器
4.0.3
我发现,通过在@Configuration中的某个地方使用ErrorViewResolver bean,也可以更简单地处理这个问题:
@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);
}
};
}
@Autowired
私有DefaultErrorViewResolver DefaultErrorViewResolver;
@豆子
ErrorViewResolver ErrorViewResolver(){
返回新的ErrorViewResolver(){
@凌驾
公共模型和视图resolveErrorView(HttpServletRequest请求、HttpStatus状态、映射模型){
if(model.containsKey(“path”)&&!model.get(“path”).toString().endsWith(“/”){
返回新的ModelAndView(“重定向:”+model.get(“路径”)+“/”;
}
返回defaultErrorViewResolver.resolveErrorView(请求、状态、模型);
}
};
}
我不确定这是好的还是坏的做法,但在我的情况下,它是有效的,并且正是我需要它对任意路径“foo”所做的:当你请求/foo时,用302重定向到/foo/进行响应,当你请求/foo时,用它应该的方式进行响应。如果一个总是重定向到另一个,它们不是类似地等效吗?为实现这一目标所付出的努力可能很高。如果你的担心完全是c