我有一个以http://localhost:8080/appcontext
在本地运行的示例应用程序(上下文为/appcontext
)。
现在,当我在浏览器中访问http://localhost:8080/appcontext/META-INF/index.html
时,我想显示文字Hello, World!
。
Servlet映射代码
这就是我尝试将Servlet映射到/META-INF
URL的方法。但它不起作用:
<?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规范
Java Servlet Specification 3.1,Chapter SRV.9.6 Web Application Archive File:
此容器不得直接由容器作为内容提供,以响应Web客户端的请求,[...]。此外,任何访问META-INF资源的请求 必须使用SC_NOT_FOUND(404)响应返回目录。
这禁止直接映射.war的META-INF
目录。但我不认为它禁止将Servlet映射到/appcontext/META-INF
URL。
答案 0 :(得分:1)
使用“META-INF”作为上下文名称没有任何限制(据我所知,对上下文名称没有任何限制 - 至少我找不到{{3 }})。
请求的根路径是/ META-INF,它将被分派到适当的servlet上下文。无法访问的实际信息META-INF将位于URL / META-INF / META-INF。
编辑:回复您的评论和问题修改,但您的问题仍然令人困惑:
至于使/context/META-INF/abc.file说“Hello world”或者其他什么,你已经回答了你自己的问题:
此外,任何访问META-INF目录中资源的请求都必须返回SC_NOT_FOUND(404)响应。
您可以做的一件事是添加一个自定义的404响应来完成您想要的任务。
答案 1 :(得分:1)
/META-INF/
和/WEB-INF/
文件夹是Java Web应用程序中的特殊文件夹。在正常情况下,没有合适的servlet容器可以让你访问这些文件夹中的任何,因为它们通常包含非常敏感的数据,不会暴露给普通公众。如果您的应用部署在<context>
下,则预计任何人都无法访问<context>/META-INF/*
和<context>/WEB-INF/*
。
如果可能,请依赖其他网址;我认为没有充分理由从/META-INF/
提供静态或动态页面。
但是,如果你真的需要这个URL,我会解决这个问题,并使用mod_proxy在你的应用程序前设置一个Apache Web服务器。
在那里你可以说像
RewriteCond %{REQUEST_URI} ^/META-INF/(.*)$ [NC]
RewriteRule ^(.*)$ /metaInf/$0 [P,L]
(由hart撰写,请务必检查确切的语法。)这会将/META-INF/
的所有外部请求重定向到您自己的应用程序/metaInf/
文件夹,并向外界显示您正在服务来自/META-INF/
的网页。
但正如所说的那样,除非你有非常具体的理由这样做,否则你不想做的事情。
答案 2 :(得分:1)
我相信你所要求的是在应用程序级别无法实现的。该规范仅讨论META-INF
文件夹,但也暗示了URL。我在这里使用“暗示”一词,因为让我们想一下服务器允许你做你想做的事情的后果。
如果服务器允许/appcontext/META-INF
url到达您的某个过滤器/ servlet,那么它无法知道您(开发人员)是否会根据规范处理该案例。严格来说,它并不完全符合规范。更糟糕的是,依靠Web开发人员来做。如果是这种情况,那么对于每个需要默认行为的Web应用程序(即META-INF
无法访问),开发人员必须实现servlet / filter来执行服务器应该执行的操作第一名(!)
所以我相信你所要求的只能在服务器级别提供,并且只有服务器允许你这样做,即服务器为你提供配置选项,或者允许你编写自己的拦截器类来处理请求的方式与默认行为不同。
在Tomcat 7中,例如META-INF
invoke()
方法{}禁止访问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
实现(即<TOMCAT_HOME>/lib
基本上是上述类的副本而没有“禁止”检查),将它打包在一个罐子里然后放入它在server.xml
文件夹中。
然后在你的META-INF
中,你会宣布下面的内容。使用该方法,尝试访问...
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
...
<Valve className="com.mypackage.valves.AllowMetaInfAccessValve" allow="true"/>
...
</Host>
...
文件夹的URL将到达您的servlet,并由您自己负责。
META-INF
更新:为了澄清我的理由:除了从META-INF
文件夹提供文件之外,servlet可以做很多事情。但它也可以做到这一点。或者更糟糕的是,对于Web开发人员来说,忘记禁止访问就足以让{{1}}文件夹变得可访问。
这里的重点不是servlet会做什么或不会做什么。关键是:实现服务器的人是否应该依赖Web开发人员来遵守规范?我的猜测是,他们不会对这种想法感到太舒服。规范基本上是一组规则。如果您希望能够说“我的服务器遵循这套规则”,那么您就无法依赖第三人的行为。把自己放在鞋子里。你会怎么做?您是否依赖某些开发人员或确保您的服务器遵守规则? 我相信大多数人会做出同样的决定,即默认禁止访问并提供某种扩展点。现在,如果这是一个好的决定或坏的决定,只有时间会证明。毕竟,规格也在不断发展。我希望现在更清楚了
答案 3 :(得分:-1)
与Servlet 3兼容的容器
WEB-INF / lib中JAR中的META-INF / resources目录中的任何内容都会自动公开为静态资源。