有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用URLhttp://localhost:8080/appcontext/METAINF/index.html?

我有一个作为http://localhost:8080/appcontext(上下文是/appcontext)在本地运行的示例应用程序

现在,当在浏览器中访问http://localhost:8080/appcontext/META-INF/index.html时,我想显示文本Hello, World!

Servlet映射代码

这就是我试图将Servlet映射到/META-INFURL的方式。但它不起作用:

<?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_2_5.xsd" version="2.5"
>
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.example.mapmetainf.MyServlet</servlet-class>
    </servlet>

    <!--
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/META-INF/index.html</url-pattern>
    </servlet-mapping>
    -->

    <!--
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/META-INF/*</url-pattern>
    </servlet-mapping>
    -->

    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Servlet规范

JavaServlet规范3.1,第SRV章。9.6 Web应用程序归档文件:

This directory must not be directly served as content by the container in response to a Web client’s request, [...]. Also, any requests to access the resources in META-INF directory must be returned with a SC_NOT_FOUND(404) response.

这禁止直接映射的META-INF目录。战争但是我不认为它禁止将Servlet映射到/appcontext/META-INFURL


共 (4) 个答案

  1. # 1 楼答案

    我相信你的要求在应用层面是不可能的。规范只讨论了META-INF文件夹,但也暗示了URL。我在这里使用“隐含”一词是因为让我们思考一下服务器允许您做您想做的事情的后果

    如果服务器允许/appcontext/META-INFurl到达您的某个过滤器/servlet,那么它无法知道您(开发人员)是否会根据规范处理该情况。严格来说,它并不完全符合规范。更糟糕的是,它依赖于web开发人员来完成这项工作。如果是这种情况,那么对于每个需要默认行为(即META-INF不可访问)的web应用程序,开发人员必须实现一个servlet/过滤器来完成服务器首先应该做的事情(!)

    因此,我相信,您所请求的内容只能在服务器级别上可用,并且只有在服务器允许您这样做的情况下,也就是说,如果服务器为您提供了这样做的配置选项,或者允许您编写自己的拦截器类,以不同于默认行为的方式处理请求

    例如,在Tomcat 7中META-INFStandardContextValve classinvoke()方法中禁止访问:

    public final void invoke(Request request, Response response) throws IOException, ServletException {
    
        // Disallow any direct access to resources under WEB-INF or META-INF
        MessageBytes requestPathMB = request.getRequestPathMB();
        if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
                || (requestPathMB.equalsIgnoreCase("/META-INF"))
                || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
                || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
                notFound(response);   // <-- Issues a response.sendError(HttpServletResponse.SC_NOT_FOUND);
                return;
        }
        ...
    }
    

    因此,您必须创建自己的Valve实现(即AllowMetaInfAccessValve,基本上是上述类的副本,没有“disallow”检查),将其打包到jar中,并将其放入<TOMCAT_HOME>/lib文件夹中

    然后在server.xml中声明如下内容。使用这种方法,尝试访问META-INF文件夹的URL将到达您的servlet,这是您自己的责任

    ...
    <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
        ...
        <Valve className="com.mypackage.valves.AllowMetaInfAccessValve" allow="true"/>
        ...
    </Host>
    ...
    

    更新:进一步澄清我的推理:servlet确实可以做很多事情,而不是从META-INF文件夹提供文件。但它也可以做到这一点。甚至更糟糕的是,web开发人员只要忘记禁止访问,就足以访问META-INF文件夹

    但这里的重点不是servlet会做什么或不会做什么。问题是:实现服务器的人员是否应该依赖web开发人员来遵守规范?我猜他们不会对这种想法感到太舒服。规范基本上是一组规则。如果你想说“我的服务器遵循那套规则”,你不能依赖第三个人会做什么。设身处地为他们着想。你会怎么做?您会依赖于某个开发人员,还是确保您的服务器遵守规则
    我相信大多数人都会做出同样的决定,即默认情况下禁止访问并提供某种扩展点。现在,如果这是一个好的决定还是一个坏的决定,只有时间会告诉我们。毕竟,规范也在演变。我希望现在更清楚了

  2. # 2 楼答案

    Servlet 3兼容容器

    WEB-INF/lib中JAR中META-INF/resources目录中的任何内容都会自动公开为静态资源

  3. # 3 楼答案

    使用“META-INF”作为上下文名称没有任何限制(据我所知,对上下文名称没有任何限制——至少我在Servlet 3.0 spec中找不到任何限制)

    请求的根路径将是/META-INF,它将被发送到适当的servlet上下文。无法访问的实际信息性META-INF将位于URL/META-INF/META-INF

    编辑:回复您的评论和问题编辑,尽管您的问题仍然令人困惑:

    至于制作/context/META-INF/abc。如果你说“你好,世界”或其他什么,你已经回答了你自己的问题:

    Also, any requests to access the resources in META-INF directory must be returned with a SC_NOT_FOUND(404) response.

    您可以做的一件事是添加一个定制的404响应来满足您的需求

  4. # 4 楼答案

    /META-INF//WEB-INF/文件夹是Java web应用程序中的特殊文件夹。在正常情况下,没有一个健全的servlet容器允许您访问这些文件夹中的任何,因为它们通常包含不向公众公开的非常敏感的数据。如果您的应用程序部署在<context>下,则任何人都无法访问<context>/META-INF/*<context>/WEB-INF/*

    如果可能,请使用其他URL;我认为没有充分的理由从/META-INF/提供静态或动态页面

    但是,如果您确实需要将此URL设置为完全相同的URL,我将解决一个技巧,并使用mod_proxy在您的应用程序前面设置一个Apache web服务器

    你可以这样说

    RewriteCond     %{REQUEST_URI}  ^/META-INF/(.*)$                          [NC]
    RewriteRule     ^(.*)$          /metaInf/$0                               [P,L]
    

    (由hart编写,确保检查准确的语法。)这将把对/META-INF/的所有外部请求重定向到您自己的应用程序/metaInf/文件夹,并将其重定向到外部世界—您似乎正在为来自/META-INF/的页面提供服务

    但正如前面所说的,除非你有一个非常具体的理由,否则你不会真的想做什么