• 随笔 0
  • 阅读 0
  • 评论 0

Servlet处理带尾部斜杠/的URI

有一个需求:让一个Servlet能够同时处理形如/XXX/YYY/XXX/YYY/的URI,即URI尾部的斜杠有没有都要能处理到。

很容易想到,做两个URL Pattern/XXX/YYY/XXX/YYY/映射到该Servlet,问题就解决了。

但如果URI是动态的呢?比如XXXYYY都是不确定的,成分数量也是不确定的,但处理逻辑又是相同的,那么就需要将任意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);
    }
}
posted @ 2021-09-13 19:08  幽室星辰  阅读(194)  评论(0编辑  收藏  举报