【问题标题】:How to read manifest.mf from POJO class (not a servlet) instantiated by spring?如何从spring实例化的POJO类(不是servlet)中读取manifest.mf?
【发布时间】:2011-04-23 21:24:27
【问题描述】:

我有一个名为 BuildNumberService 的简单服务,它将由 spring 实例化。

我正在尝试为该类找到最干净的代码,以便从它已打包到的 jar 文件中找出 MANIFEST.MF 文件。

代码必须在 servlet 容器中运行。

@Service
public class BuildNumberService {

    private static final String IMPLEMENTATION_BUILD = "Implementation-Build";

    private String version = null;

    public BuildNumberService() {

      // find correct manifest.mf
      // ?????


      // then read IMPLEMENTATION_BUILD attributes and caches it.
       Attributes mainAttributes = mf.getMainAttributes();
       version = mainAttributes.getValue(IMPLEMENTATION_BUILD);
    }

    public String getVersion() {
        return this.version;
    }
}

你会怎么做?

编辑:实际上,我想要做的是,按名称查找与实际类位于同一包中的资源。

【问题讨论】:

标签: java spring servlets manifest.mf


【解决方案1】:

如果您知道 jar 在文件系统上(例如不在战争中),并且您还知道安全管理器授予您访问类的保护域的权限,您可以这样做:

public static InputStream findManifest(final Class<?> clazz) throws IOException,
    URISyntaxException{
    final URL jarUrl =
        clazz.getProtectionDomain().getCodeSource().getLocation();
    final JarFile jf = new JarFile(new File(jarUrl.toURI()));
    final ZipEntry entry = jf.getEntry("META-INF/MANIFEST.MF");
    return entry == null ? null : jf.getInputStream(entry);
}

【讨论】:

  • @BalusC 这太容易了。让我自己做腿部工作:-)(说实话,不知道)
  • 这是类找到打包它的 jar 的唯一方法吗?似乎 jdk 使得在运行时读取这些元数据变得很困难。好像不应该这样做。
  • 不应该这样做。我将其改写为:只应该由真正知道自己在做什么的人来完成(例如,具有组件扫描的框架,如 hibernate、spring、seam 等必须使用这样的功能)。但是,是的,我猜这是唯一的方法
【解决方案2】:

我找到了另一种解决方案,可以在不引用 servlet 上下文的情况下加载 MANIFEST.MF,只需使用 Spring Framework。

我在 Spring 3.1.2.RELEASE 中使用了这个配置,但我相信它在以后的版本中应该可以正常工作。

首先,在 applicationContext.xml 中编写以下 bean

<bean class="java.util.jar.Manifest" id="manifest">
    <constructor-arg>
        <value>/META-INF/MANIFEST.MF</value>
    </constructor-arg>  
</bean>

您应该注意到,来自 Manifest 类的构造函数参数接受 InputStream 作为参数,但是,您不必担心,因为 Spring 会将提供的值转换为匹配构造函数参数。 此外,通过以斜杠 / (/META-INF/...) 开头的路径,Spring 在 servlet 上下文对象上查找此文件,而以 classpath: 前缀开头,它引导 Spring 查看类路径以查找请求的资源。

其次,在你的类中声明上述 bean:

@Autowired
@Qualifier("manifest")
private Manifest manifest;

我的 MANIFEST.MF 位于 $WEBAPP_ROOT/META-INF/ 文件夹下,我已在 Apache Tomcat 7 和 WildFly 8 上成功测试了此解决方案。

【讨论】:

    【解决方案3】:
    Manifest mf = new Manifest();
    Resource resource = new ClassPathResource("META-INF/MANIFEST.MF");
                        InputStream is= resource.getInputStream();
                            mf.read(is);
                            if (mf != null) {
                                Attributes atts = mf.getMainAttributes();
                                implementationTitle = atts.getValue("Implementation-Title");
                            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-02
      • 1970-01-01
      • 1970-01-01
      • 2015-04-03
      • 2017-12-12
      • 2015-01-02
      • 2022-08-10
      相关资源
      最近更新 更多