使用 Tomcat,@WebFilter 不适用于 web.xml 中的 <filter-mapping>

Posted

技术标签:

【中文标题】使用 Tomcat,@WebFilter 不适用于 web.xml 中的 <filter-mapping>【英文标题】:Using Tomcat, @WebFilter doesn't work with <filter-mapping> inside web.xml 【发布时间】:2012-06-07 02:00:24 【问题描述】:

这是一个有效的 web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app 
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

     <filter>
        <filter-name>rememberMeCookieFilter</filter-name>
        <filter-class>be.example.fun.jsp.filters.RememberMeCookieFilter</filter-class>
    </filter>

    <filter>
        <filter-name>mustBeSignedInFilter</filter-name>
        <filter-class>be.example.fun.jsp.filters.MustBeSignedInFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>rememberMeCookieFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>mustBeSignedInFilter</filter-name>
        <url-pattern>/private/*</url-pattern>
    </filter-mapping>
</web-app>

当我删除 &lt;filter&gt; 元素并改用以下注释时:

@WebFilter(filterName="rememberMeCookieFilter")
public class RememberMeCookieFilter implements Filter

@WebFilter(filterName="mustBeSignedInFilter")
public class MustBeSignedInFilter implements Filter

然后Tomcat 7.0.14给我以下错误:

java.lang.IllegalArgumentException: Filter mapping must specify either a <url-pattern> or a <servlet-name>
    at org.apache.catalina.core.StandardContext.validateFilterMap(StandardContext.java:2956)
    at org.apache.catalina.core.StandardContext.addFilterMap(StandardContext.java:2915)
    at org.apache.catalina.deploy.WebXml.configureContext(WebXml.java:1180)
    at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1270)
        ...

我按照this question的回答,但这对我不起作用。

这是我的网络应用程序的依赖项:

<dependencies>
        <!-- SLF4J (+ LOGBack) for logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.4</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy</artifactId>
            <version>1.8.3</version>
        </dependency>

        <!-- The servlet API that I installed in my local repo -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>3.0</version>
            <type>jar</type>
            <scope>provided</scope>
            <!--optional>false</optional-->
        </dependency>

        <!-- JUnit for testing -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

编辑:我只在使用 Tomcat (7.0.14) 时遇到问题。 Glassfish 很好。

【问题讨论】:

您可以尝试使用最新版本的 Tomcat 7 吗?当前版本是 7.0.27。 【参考方案1】:

这是 Tomcat 7 中的一个错误。我将其报告为 issue 53354。

由于无法在 @WebFilter 中指定调用顺序,因此用户必须在 web.xml 中明确指定 &lt;filter-mapping&gt;。这与 Glassfish 和 JBoss AS 中的 @WebFilter(filterName) 结合使用,如下所示:

@WebFilter(filterName="filter1")
public class Filter1 implements Filter 

@WebFilter(filterName="filter2")
public class Filter2 implements Filter 

<filter-mapping>
    <filter-name>filter1</filter-name>
    <url-pattern>/url1/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>filter2</filter-name>
    <url-pattern>/url2/*</url-pattern>
</filter-mapping>

但是它在 Tomcat 7.0.27 中失败并出现以下令人困惑的异常(&lt;url-pattern&gt; 已设置)

Caused by: java.lang.IllegalArgumentException: Filter mapping must specify either a <url-pattern> or a <servlet-name>
    at org.apache.catalina.core.StandardContext.validateFilterMap(StandardContext.java:3009)
    at org.apache.catalina.core.StandardContext.addFilterMap(StandardContext.java:2968)
    at org.apache.catalina.deploy.WebXml.configureContext(WebXml.java:1207)
    at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1294)
    at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:855)
    at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:345)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5161)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 7 more

与此同时,您最好的选择是改用 Glassfish 或 JBoss AS,或者通过&lt;filter&gt; 注册过滤器。

【讨论】:

我可以使用 元素,因为我这样做是为了我自己的学习。为什么现在才发现这个问题? Servlet 3.0 已经出现了一段时间,Tomcat 7 也是,这是一个非常基本的功能......(我才刚刚开始学习 servlet)。人们是否放弃了过滤器以换取其他东西或...? 不知道。也许是因为人们没有意识到这一点。或者也许是因为订购对他们来说并不重要。或者可能是因为他们没有将 Tomcat 用于具有多个过滤器的不那么小的 web 应用程序,这些过滤器对于排序很重要。或者也许是因为他们认为不值得付出努力报告。等等。谁知道呢。 仅供参考:几秒前被Mark 发送到fixed。将在 7.0.28 及以后。 使用 JBoss AS 7.1 时,我需要使用 "metadata-complete="false"" 来避免同样的问题。你知道为什么 JBoss 和 Tomcat 的行为不同吗?哪个是对的? @BalusC 是否已在 tomcat 8 中修复?【参考方案2】:

您必须为 Servlet 过滤器指定一个目标。为“servletNames”或“urlPatterns”提供一个值。

http://docs.oracle.com/javaee/6/api/javax/servlet/annotation/WebFilter.html

例如

@WebFilter(filterName="mustBeSignedInFilter", urlPatterns= "/signed/in/path/*" )
public class MustBeSignedInFilter implements Filter

【讨论】:

我只是从我的 web.xml 中删除 元素,而不是 元素。正如以下问题中所回答的那样,它应该可以工作:***.com/questions/6560969/…。它仅在我将其部署在 Glassfish 环境中时才有效。

以上是关于使用 Tomcat,@WebFilter 不适用于 web.xml 中的 <filter-mapping>的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat 7.0.73 不适用于 java 9

Tomcat:“X-Forwarded-For”不适用于负载均衡器

Proxy 后面的 SpringBoot 适用于 Undertow,但不适用于 Tomcat

Oracle Java EE 7 JSF 示例不适用于 Tomcat

带有 Spring Boot 的 Spring MVC 不适用于 Eclipse 的 Tomcat 服务器

AWS Elastic Beanstalk Tomcat 适用于 .war 但不适用于 .zip