美文网首页
web.xml中的servlet和filter的url-patt

web.xml中的servlet和filter的url-patt

作者: tengwind | 来源:发表于2018-05-25 19:15 被阅读0次

今天在启动web应用的时候发现了一个问题,filter一直不生效,配置了spring的字符编码fitler,配置如下:

 <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <!--注意这里的配置-->
        <url-pattern>/</url-pattern>
    </filter-mapping>

注意上面的配置url-parrtern配置成”/“,后来我测试把/修改成/*就能成功,这就很奇怪了,激发了我强烈的兴趣。我把tomcat的源码通过maven的方式加入到了项目中,跟进到tomcat的源码看看到底是上面情况。可以查看项目中调试tomcat源码文章如何调试,发现了原因,先把tomcat对url-pattern的匹配源码贴出:

 for (int i = 0; i < filterMaps.length; i++) {
            if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
                continue;
            }
            //根据requestPath匹配web.xml中配置的url
            if (!matchFiltersURL(filterMaps[i], requestPath))
                continue;
            ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
                context.findFilterConfig(filterMaps[i].getFilterName());
            if (filterConfig == null) {
                // FIXME - log configuration problem
                continue;
            }
            boolean isCometFilter = false;
            if (comet) {
                try {
                    isCometFilter = filterConfig.getFilter() instanceof CometFilter;
                } catch (Exception e) {
                    // Note: The try catch is there because getFilter has a lot of 
                    // declared exceptions. However, the filter is allocated much
                    // earlier
                    Throwable t = ExceptionUtils.unwrapInvocationTargetException(e);
                    ExceptionUtils.handleThrowable(t);
                }
                if (isCometFilter) {
                    filterChain.addFilter(filterConfig);
                }
            } else {
                filterChain.addFilter(filterConfig);
            }
        }

在上面代码中matchFiltersURL(filterMaps[i], requestPath) 这行代码会根据每次请求找到对应需要执行的filter集合,构建ApplicationFilterConfig对象,将对象加入到我们属性的filterChain中。下面看一下matchFiltersURL源码:

private boolean matchFiltersURL(FilterMap filterMap, String requestPath) {
        // Check the specific "*" special URL pattern, which also matches
        // named dispatches
        if (filterMap.getMatchAllUrlPatterns())
            return (true);
        if (requestPath == null)
            return (false);
        // Match on context relative request path
        String[] testPaths = filterMap.getURLPatterns();
        for (int i = 0; i < testPaths.length; i++) {
            if (matchFiltersURL(testPaths[i], requestPath)) {
                return (true);
            }
        }
        // No match
        return (false);
    }

代码中根据web.xml配置的url-pattern存入到了filterMap对象中,调用matchFiltersURL(String testPath, String requestPath)比对是否匹配。

  private boolean matchFiltersURL(String testPath, String requestPath) {
        
        if (testPath == null)
            return (false);

        // Case 1 - Exact Match
        if (testPath.equals(requestPath))
            return (true);
        // Case 2 - Path Match ("/.../*")
        if (testPath.equals("/*"))
            return (true);
        if (testPath.endsWith("/*")) {
            if (testPath.regionMatches(0, requestPath, 0, 
                                       testPath.length() - 2)) {
                if (requestPath.length() == (testPath.length() - 2)) {
                    return (true);
                } else if ('/' == requestPath.charAt(testPath.length() - 2)) {
                    return (true);
                }
            }
            return (false);
        }
        // Case 3 - Extension Match
        if (testPath.startsWith("*.")) {
            int slash = requestPath.lastIndexOf('/');
            int period = requestPath.lastIndexOf('.');
            if ((slash >= 0) && (period > slash) 
                && (period != requestPath.length() - 1)
                && ((requestPath.length() - period) 
                    == (testPath.length() - 1))) {
                return (testPath.regionMatches(2, requestPath, period + 1,
                                               testPath.length() - 2));
            }
        }
        // Case 4 - "Default" Match
        return (false); // NOTE - Not relevant for selecting filters
    }

上面是关键的匹配代码,我们发现没有单独的匹配/的代码逻辑,只有/*的逻辑,所以在web.xml中配置”/“是不生效的。

相关文章

网友评论

      本文标题:web.xml中的servlet和filter的url-patt

      本文链接:https://www.haomeiwen.com/subject/cfbyjftx.html