META-INF的目的是什么?
在Java中,您经常会看到包含一些元文件的META-INF文件夹。 这个文件夹的目的是什么,我可以放在那里?
一般来说,你不应该把任何东西放入META-INF中。 相反,你应该依靠你用来打包你的JAR的东西。 这是我认为Ant真正优秀的领域之一:指定JAR文件清单属性。 这样说很容易:
<jar ...> <manifest> <attribute name="Main-Class" value="MyApplication"/> </manifest> </jar>
至less,我觉得这很容易… 🙂
关键是META-INF应该被认为是一个内部的Java 元目录。 不要乱它! 您想要包含在JAR中的任何文件都应放在其他一些子目录或JAR本身的根目录下。
从官方的JAR文件规范 (链接到Java 7版本,但至lessv1.3以来,文本没有改变):
META-INF目录
META-INF目录中的以下文件/目录由Java 2 Platform进行识别和解释,以configuration应用程序,扩展,类加载器和服务:
MANIFEST.MF
清单文件,用于定义扩展和包相关的数据。
INDEX.LIST
该文件由jar工具的新“
-i
”选项生成,该选项包含应用程序或扩展中定义的包的位置信息。 它是JarIndex实现的一部分,由类加载器用来加速他们的类加载过程。
x.SF
JAR文件的签名文件。 “x”代表基本文件名。
x.DSA
与签名文件关联的签名块文件具有相同的基本文件名。 该文件存储相应签名文件的数字签名。
services/
该目录存储所有服务提供者configuration文件。
我注意到一些Java库已经开始使用META-INF作为一个目录,在这个目录中包含应该打包并包含在CLASSPATH和JAR中的configuration文件。 例如,Spring允许您使用以下命令导入类path中的XML文件:
<import resource="classpath:/META-INF/cxf/cxf.xml" /> <import resource="classpath:/META-INF/cxf/cxf-extensions-*.xml" />
在这个例子中,我直接引用了Apache CXF用户指南 。 在我所做的一个项目中,我们不得不通过Spring来允许多级configuration,我们遵循这个约定,并把我们的configuration文件放在META-INF中。
当我思考这个决定时,我不知道将configuration文件包含在特定的Java包中而不是META-INF中究竟会出现什么问题。 但似乎是一个新兴的事实标准; 无论是,还是一个新兴的反模式:-)
META-INF文件夹是MANIFEST.MF文件的主要堡垒。 该文件包含有关JAR内容的元数据。 例如,有一个名为Main-Class的条目,该条目用可执行JAR文件的静态main()指定Java类的名称。
你也可以在那里放置静态资源。
例如:
META-INF/resources/button.jpg
并通过web3.0容器获取它们
http://localhost/myapp/button.jpg
>阅读更多
/META-INF/MANIFEST.MF有特殊的含义:
- 如果使用
java -jar myjar.jar org.myserver.MyMainClass
运行jar,则可以将主类定义移动到jar中,以便将调用缩减为java -jar myjar.jar
。 - 如果使用
java.lang.Package.getPackage("org.myserver").getImplementationTitle()
则可以将Metainformations定义为包。 - 您可以引用您想要在Applet / Webstart模式下使用的数字证书。
只要在这里添加信息,在WAR文件的情况下,META-INF / MANIFEST.MF文件为开发人员提供了一个工具来启动容器的部署时间检查,确保容器可以find你的应用程序的所有类依赖于取决于。 这确保了如果您错过了一个JAR,您不必等到您的应用程序在运行时发现它已经丢失。
我最近一直在想这个问题。 对于使用META-INF,似乎没有任何限制。 当然,关于在那里放置货单的必要性有一定的限制,但似乎没有任何禁止在那里放置其他货物的禁令。
这是为什么?
cxf案件可能是合法的。 下面是另外一个地方,推荐使用这个非标准来解决JBoss-ws中一个令人讨厌的错误,这个错误会阻止服务器端对wsdl模式的validation。
http://community.jboss.org/message/570377#570377
但是,真的似乎没有任何标准,任何你不应该的。 通常这些东西都是非常严格的,但是由于某种原因,这里似乎没有标准。 奇。 看起来,META-INF已经成为任何需要的configuration的地方,不能轻易地以其他方式处理。
如果您使用的是JPA1,则可能必须在其中删除一个persistence.xml
文件,该文件指定了您可能要使用的持久性单元的名称。 持久性单元提供了一种方便的方式来指定一组元数据文件,类和包含要在分组中持久化的所有类的jar文件。
import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; // ... EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);
在这里看到更多: http : //www.datanucleus.org/products/datanucleus/jpa/emf.html
META-INF在Maven中
在Maven中, META-INF文件夹是由于标准目录布局而被理解的,它按名称约定将您的项目资源打包到JAR中:放置在$ {basedir} / src / main / resources目录中的任何目录或文件都打包到您的JAR中从JAR底部开始的完全相同的结构。 文件夹$ {basedir} / src / main / resources / META-INF通常包含.properties文件,而jar文件包含生成的MANIFEST.MF , pom.properties , pom.xml等文件。 像Spring这样的框架也使用classpath:/META-INF/resources/
来为Web资源提供服务。 有关更多信息,请参阅如何将资源添加到我的Maven项目
只是为了添加这里的信息,META-INF是一个特殊的文件夹, ClassLoader
的处理方式与jar中的其他文件夹不同。 嵌套在META-INF中的元素不与其外部的元素混合。 这就像另一个根。 至less从Enumerator<URL> ClassLoader#getSystemResources(String path)
方法等等透视:当给定的path以“META-INF”开始时,该方法search嵌套在所有jar子的META-INF文件夹内的资源在class级path中。 当给定的path不以“META-INF”开始时,该方法search类path中所有jar和目录的所有其他文件夹(META-INF外部)的资源。
如果您知道getSystemResources
方法专门处理的另一个文件夹名称,请对其进行评论。
所有答案都是正确的。 元信息有很多目的。 另外,这里是一个关于使用tomcat容器的例子。
转到Tomcat Doc并检查“ Standard Implementation> copyXML ”属性。
说明如下。
如果希望在部署应用程序时将位于应用程序(位于/META-INF/context.xml)中的上下文XML描述符复制到拥有的主机的xmlBase,则设置为true。 在后续启动中,即使embedded在应用程序中的描述符更新,复制的上下文XML描述符也将优先于应用程序中embedded的任何上下文XML描述符。 该标志的值默认为false。 请注意,如果拥有主机的deployXML属性为false,或者拥有主机的copyXML属性为true,则此属性将不起作用。
您的META-INF文件夹中有MANIFEST.MF文件。 您可以定义您必须有权访问的可选或外部依赖项 。
例:
考虑你已经部署你的应用程序和容器(运行时)发现你的应用程序需要一个不在lib文件夹内的库的新版本,在这种情况下,如果你已经在MANIFEST.MF
定义了可选的较新版本,那么你的应用程序将从那里引用依赖(并不会崩溃)。
Source:
Head First Jsp&Servlet