【问题标题】:Filter mapping url-pattern that excludes subdirectories排除子目录的过滤器映射 url 模式
【发布时间】:2011-03-28 20:53:03
【问题描述】:

有没有办法让过滤器映射不包含子目录?

例如。

我的上下文根目录中有 .xhtml 文件,还有一个名为“test”的子文件夹,其中包含具有相同扩展名的文件。是否可以将过滤器映射到上下文根目录中的文件而不是“test”目录中的文件?

【问题讨论】:

    标签: java servlets web.xml servlet-filters


    【解决方案1】:

    url-pattern 确实在匹配上有限制。它只允许精确、前缀或后缀匹配。不是中间/整体/正则表达式匹配。所以例如/*.xhtml 你打算做的事是行不通的。

    如果您只想在 /test 文件夹中排除 XHTML,那么您最好的方法是使用 Filter 监听 url-pattern*.xhtml,它基本上在 doFilter() 方法中完成以下工作:

    // First cast ServletRequest to HttpServletRequest.
    HttpServletRequest hsr = (HttpServletRequest) request;
    
    // Check if requested resource is not in /test folder.
    if (!hsr.getServletPath().startsWith("/test/")) {
        // Not in /test folder. Do your thing here.
    }
    

    HttpServletRequest#getServletPath() 基本上从上下文路径返回请求 URI 的部分。

    如有必要,您可以将值 /test 配置为过滤器的 <init-param>,以便您可以从 web.xml 内部而不是在过滤器的代码中控制值。

    【讨论】:

    • 我首先想到的是在过滤器中硬编码?但 init-param 很聪明。在这里学到了一些东西。
    【解决方案2】:

    解决方案,基本上你需要自己的过滤器类并将排除 URL 定义为过滤器的 init-param

    package test;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class LoginValidationFilter implements Filter {
    
        private String loginPage = "";
        private List<String> excludedURLs;
    
        public void init(FilterConfig filterConfig) throws ServletException {
            this.loginPage = filterConfig.getInitParameter("loginPage");
    
            String[] excluded = filterConfig.getInitParameter("excludedURLs").split(";");
            excludedURLs = new ArrayList<String>();
            for (int i = 0; i < excluded.length; i++) {
                excludedURLs.add(excluded[i]);
            }
        }
    
        public void destroy() {
            this.loginPage = "";
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,
                ServletException {
    
            HttpServletRequest httpRequest = request instanceof HttpServletRequest ? (HttpServletRequest) request : null;
            HttpServletResponse httpResponse = response instanceof HttpServletResponse ? (HttpServletResponse) response
                    : null;
    
            if (httpRequest == null || httpResponse == null) {
                filterChain.doFilter(request, response);
                return;
            }
    
            boolean isExcludedURL = false;
            for (int i = 0; i < excludedURLs.size(); i++) {
                if (httpRequest.getRequestURL().indexOf(excludedURLs.get(i)) > -1) {
                    isExcludedURL = true;
                    break;
                }
            }
    
            if (isExcludedURL) {
                filterChain.doFilter(request, response);
            } else {
                if (UserUtil.validateUserLogin(httpRequest)) {
                    filterChain.doFilter(request, response);
                } else {
                    httpResponse.sendRedirect(httpRequest.getContextPath() + loginPage);
                }
            }
        }
    }
    

    并在web.xml中定义过滤、映射和排除URL

    <filter>
        <filter-name>LoginValidationFilter</filter-name>
        <filter-class>test.LoginValidationFilter</filter-class>
        <init-param>
            <param-name>loginPage</param-name>
            <param-value>/login.jsp</param-value>
        </init-param>
        <init-param>
            <param-name>excludedURLs</param-name>
            <param-value>/admin/;/assets/;/content/;/css/;/js/;/login.jsp;/login.cmd;/logout.cmd;forgot_password.jsp;pageName=</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>LoginValidationFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    【讨论】:

    • 对不起,这是我的第一篇文章,我花了大约 30 分钟来纠正格式。解决方案,基本上你需要自己的过滤器类并将排除 URL 定义为过滤器的 init-param。
    【解决方案3】:

    使用可用于标准 servlet/过滤器的内容,没有直接的方法可以排除子目录,因为*.ext 样式映射包含子目录。您可以通过声明另一个专门处理 /test/*.xhtml 映射并相应处理的过滤器来解决此问题。

    【讨论】:

    • 但是带有映射 /* 的过滤器仍然会包含 /test 下的所有内容,不是吗?
    • 没错。我在想第一个匹配的是使用的那个,但事实并非如此。相反,您可以在过滤器中添加一个 url 正则表达式检查 - 如果它与正则表达式匹配,则过滤器在委托给 remaning 过滤器链之前执行它的工作。如果正则表达式不匹配,它只是委托给过滤器链而不做任何工作。
    【解决方案4】:

    您可以为上下文根目录中的每个文件添加一个 url 映射值,因此过滤器将应用于这些文件,但不会应用于测试文件夹中的文件(实际上它只会应用于那些特定文件)。以下对我有用

    <url-pattern>/index.faces</url-pattern>
    

    【讨论】:

      【解决方案5】:

      一些容器(如resin)在web.xml 中定义了过滤映射定义的扩展,允许指定url-regexp,它允许基于正则表达式匹配url。 (reference)。看看你的容器是否有这样的东西。

      【讨论】:

        猜你喜欢
        • 2023-03-25
        • 2013-01-29
        • 2011-09-16
        • 2019-03-06
        • 2011-04-10
        • 2014-04-22
        • 2012-11-04
        • 2021-06-15
        • 2014-11-16
        相关资源
        最近更新 更多