使用Tomcat时,@WebFilter不能在web.xml的<filter-mapping>内工作

9
以下是一个可用的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>

当我移除了<filter>元素并使用以下注释时:
@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)
        ...

我按照这个问题的答案做了,但对我没有用。

这是我的Web应用程序的依赖关系:

<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。 - Christopher Schultz
2个回答

13

这是Tomcat 7的一个bug。我已经报告了问题53354

由于无法在@WebFilter中指定调用顺序,因此用户被强制在web.xml中显式指定<filter-mapping>。在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上它会失败,并抛出以下令人困惑的异常(<url-pattern>已经被设置)

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,或者通过

我使用<filter>元素来学习,所以这没问题。为什么现在才发现这个问题?Servlet 3.0 已经发布一段时间了, Tomcat 7 也是,而且这是一个非常基本的功能...(我刚开始学习servlet)。人们是否已经放弃使用Filter并转向其他方式了呢? - AndrewBourgeois
不清楚。也许是因为人们不知道这一点。或者可能是因为他们不在意顺序。或者因为他们没有在不太小的Web应用程序中使用Tomcat,这些应用程序具有多个过滤器,其中顺序很重要。或者是因为他们觉得汇报这个问题不值得花费精力。等等,谁知道呢。 - BalusC
2
FYI:刚才已经被Mark修复了(https://issues.apache.org/bugzilla/show_bug.cgi?id=53354#c1)。将在7.0.28及以后版本中更新。 - BalusC
在使用JBoss AS 7.1时,我需要使用“metadata-complete =”false“”来避免这个问题。你知道为什么JBoss和Tomcat的行为不同吗?哪一个是正确的? - AndrewBourgeois
1
@BalusC,这个问题在Tomcat 8中修复了吗? - Dejell

2

我只是从我的web.xml文件中删除了<filter>元素,而不是<filter-mapping>元素。正如在以下问题中回答的那样,它应该可以工作:https://dev59.com/wmw15IYBdhLWcg3whME1。仅当我在Glassfish环境中部署它时才起作用。 - AndrewBourgeois

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接