为什么以“/WEB-INF”开头的请求不能映射到servlet/筛选器



[context]tomcat 7-java 1.7

大家好;我面临着陌生的工作。在我的web.xml文件中,我映射了如下请求:

web.xml

<web-app>
    <filter>
        <filter-name>filter</filter-name>
        <filter-class>demo.DemoFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>demo.DemoServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

DemoFilter.java(实现Filter(

@Override
public void doFilter( ServletRequest req, ServletResponse res, FilterChain chain )
        throws IOException, ServletException
{
    try
    {
        chain.doFilter(req, res);
    }
    catch ( Exception e )
    {
        System.err.println("error");
        ((HttpServletResponse) res).setContentType("text/html");
        ((HttpServletResponse) res).setStatus(HttpServletResponse.SC_NOT_FOUND);
        res.getWriter().write("foo");
    }
}

DemoServlet.java(扩展HttpServlet(

@Override
protected void doGet( HttpServletRequest req, HttpServletResponse resp )
        throws ServletException, IOException
{
    System.err.println(req.getRequestURI());
    throw new RuntimeException("ERROR");
}

[1=预期结果]首先,当我尝试请求"/foo/bar"时,过滤器和servlet被调用(页面显示单词"foo"(。控制台结果:

/foo/bar    
error

[2=意外结果]然后,当我尝试请求"/WEB-INF/foo/bar"时,没有调用任何东西(我的过滤器和servlet没有被命中(,我得到了Tomcat错误报告:

HTTP Status 404 -
type Status report
message
description The requested resource is not available.
Apache Tomcat/7.0.30

编辑:在这里,我期望得到以下结果:

/WEB-INF/foo/bar    
error

我的目标是使用我的过滤器来处理异常(包括"/WEB-INF"调用(。

  • 为什么以"/WEB-INF/"开头的请求从未命中映射在"/*"模式上的过滤器/servlet
  • 我们如何解决这个问题

提前感谢!

PS:我想保留我当前的web.xml配置("url pattern"="/*";不使用"错误页面"(


编辑我的问题被误解了。我不想在我的"WEB-INF"目录下提供文件访问服务。我想用我的Filter和Servlet(url pattern='/*'(为每个请求提供服务,即使请求URI以"/WEB-INF/"开头。谢谢

这里有一个主要的概念误解。/WEB-INF中的资源根本无法公开访问。你提出问题的方式表明情况并非如此。这是不对的。我相信你只是问错了具体问题。

根据一条评论,我理解您希望在/WEB-INF中记录访问的文件以及404个错误。我猜你实际上是想在直接请求的资源旁边记录转发的、包含的和错误的资源。通常,转发和包含的资源确实隐藏在/WEB-INF中,以防止直接访问。

默认情况下,过滤器仅在直接请求的资源上调用,而不是在转发和包含的资源上,也不是在404尝试中的错误资源上。为此,您需要将适当的<dispatcher>条目添加到映射中:

<filter-mapping>
    <filter-name>filter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

(每个都是可选的;完全不存在时,REQUEST是默认的(

这样,过滤器不仅会拦截直接请求的资源,还会拦截转发的、包含的和错误的资源。ERROR调度器也将使其在404错误上启动。

WEB-INF目录是WEB应用程序的私有区域,不能通过指定URL的方式直接从浏览器访问WEB-INF下的任何文件。

web容器将不提供此目录的内容。然而,类可以访问该目录的内容,比如您在应用程序中映射到web.xml中的servlet。

如果您想限制对某些文件的直接URL访问,请将它们放在WEB-INF目录下。

此处引用:http://www.servletworld.com/servlet-tutorials/web-application-directory-structure.html

WEB-INF目录是WEB应用程序的私有区域,WEB-INF下的任何文件不能通过指定URL类似于http://somesite/WEB-INF/someresource.html。Web容器将不提供此目录的内容。然而应用程序中的类可以访问WEB-INF目录。因此,如果有任何资源,如JSP或HTML文档不希望直接从web浏览器访问,您应该将其放在WEB-INF目录下。

发布的两个答案都是正确的,这对于您使用的任何应用程序服务器和JDK都是一样的。尽管从servlet规范3.0来看,web.xml是可选的,或者您可以使用web-framgment.xml来破坏web.xml。

根据servlet规范,客户端访问WEB-INF/目录中资源的任何请求都必须返回SC_NOT_FOUND(404(响应。参见第10.5节目录结构。

https://download.oracle.com/otn-pub/jcp/servlet-3_1-fr-eval-spec/servlet-3_1-final.pdfhttps://download.oracle.com/otn-pub/jcp/servlet-3.0-fr-eval-oth-JSpec/servlet-3_0-final-spec.pdf