Servlet处理带尾部斜杠/的URI
有一个需求:让一个Servlet能够同时处理形如/XXX/YYY
和/XXX/YYY/
的URI,即URI尾部的斜杠有没有都要能处理到。
很容易想到,做两个URL Pattern/XXX/YYY
和/XXX/YYY/
映射到该Servlet,问题就解决了。
但如果URI是动态的呢?比如XXX
和YYY
都是不确定的,成分数量也是不确定的,但处理逻辑又是相同的,那么就需要将任意URI都映射到该Servlet上。为了使静态资源能正常响应而不匹配进来,URL Pattern不要写/*
,而是写/
(fallback匹配),同时在web.xml
中做静态资源文件的URL Pattern(如*.css
)映射到default
(因为优先级*.xxx
> /
> 静态资源默认)。
此时,静态资源的URI和形如/XXX/YYY
(尾部无斜杠)的URI就都能正常响应了,但是/XXX/YYY/
(尾部有斜杠)却404,原因是Servlet容器将尾部带斜杠的URI看做是静态资源了,在没有精确匹配的情况下,会作为目录去匹配默认主页文件(实际请求/XXX/YYY/index.html
)。也就是说,请求根本就没有走到预期的Servlet中。
那怎么办呢?难道用/*
Servlet抓到所有的请求,然后自己做分发?很麻烦,而且对于静态资源是重复造轮子。
解决思路其实很简单,用Filter把尾部斜杠去掉,然后内部转发一下就可以了。Filter用URL Pattern/*
抓到所有请求,如果发现URI尾部带斜杠,就移除尾部斜杠然后转发,否则正常放行。
@WebFilter("/*")
public class TheFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
String uri = httpRequest.getRequestURI();
if (uri.endsWith("/")) {
uri = uri.substring(0, uri.length() - 1);
httpRequest.getRequestDispatcher(uri).forward(servletRequest, servletResponse);
return;
}
filterChain.doFilter(servletRequest, servletResponse);
}
}