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有特殊的含义:

  1. 如果使用java -jar myjar.jar org.myserver.MyMainClass运行jar,则可以将主类定义移动到jar中,以便将调用缩减为java -jar myjar.jar
  2. 如果使用java.lang.Package.getPackage("org.myserver").getImplementationTitle()则可以将Metainformations定义为包。
  3. 您可以引用您想要在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.MFpom.propertiespom.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