简体   繁体   English

ImageIO PSD库插件不能在jar内部工作

[英]ImageIO PSD library plugin not working inside of a jar

I'm working with ImageIO and I'm trying to package the code into a JAR, however, I found out (after some debugging) that the PSD plugin is not present inside of the packaged JAR 我正在使用ImageIO,我正在尝试将代码打包到JAR中,但是,我发现(在一些调试之后)PSD插件不在打包的JAR中

I found out thanks to the code in this answer: Add/remove ImageReader from jar to ImageIO-registry 我发现感谢这个答案中的代码: 从jar添加/删除ImageReader到ImageIO-registry

In my pom.xml I have the following ImageIO dependencies: 在我的pom.xml中,我有以下ImageIO依赖项:

   <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-bmp</artifactId>
        <version>3.4</version>
    </dependency>
    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-psd</artifactId>
        <version>3.4</version>
    </dependency>
    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-core</artifactId>
        <version>3.4</version>
    </dependency>
    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-metadata</artifactId>
        <version>3.4</version>
    </dependency>

The maven command I use is: 我使用的maven命令是:

clean compile assembly:single

Side note the code I used to debug: 请注意我用于调试的代码:

        ImageIO.scanForPlugins()
        IIORegistry.getDefaultInstance().registerApplicationClasspathSpis()
        val ir = ImageIO.getImageReadersByFormatName("PSD")
        while (ir.hasNext())
        {
            val r = ir.next() as ImageReader
            println(r)
        }

Which in IDE prints: 哪个在IDE中打印:

com.twelvemonkeys.imageio.plugins.psd.PSDImageReader@1963006a

And when running the jar from a commandline it doesn't print anything, leading me to believe the PSD plugin is not working inside of the JAR but how? 当从命令行运行jar时它不打印任何东西,导致我相信PSD插件在JAR内部不起作用但是如何?

The problem is that the target assembly:single merges "everything" from your own project and all referenced JARs into one JAR but skips files that exist there yet. 问题是目标assembly:single将您自己项目中的“所有内容”和所有引用的JAR合并到一个JAR中,但是会跳过那里存在的文件。

ImageIO relies on the SPI/service loader mechanism of Java and therefore the plugins will be loaded via META-INF\\services\\javax.imageio.spi.ImageReaderSpi . ImageIO依赖于Java的SPI /服务加载器机制,因此插件将通过META-INF\\services\\javax.imageio.spi.ImageReaderSpi加载。 However, when having more than one JAR with such a file and using assembly:single , one of those file "wins" and the ones from the other JARs are skipped. 但是,当有多个JAR与这样的文件并使用assembly:single ,其中一个文件“wins”和其他JAR中的一个被跳过。 In your project, both imageio-bmp and imageio-psd do have such a file and the first one "wins" in the resulting JAR. 在你的项目中, imageio-bmpimageio-psd都有这样一个文件,第一个文件在生成的JAR中“获胜”。 (Seems like the IDE loads those files in another order and the correct version "wins", but that is just a guess.) (看起来像IDE以其他顺序加载这些文件而正确的版本“获胜”,但这只是猜测。)

Solution: Maven should merge all META-INF\\services\\javax.imageio.spi.ImageReaderSpi files into one file in the resulting JAR. 解决方案: Maven应将所有META-INF\\services\\javax.imageio.spi.ImageReaderSpi文件合并到生成的JAR中的一个文件中。 To do that, Maven needs additional configuration information. 为此,Maven需要其他配置信息。

  1. Add a file descriptor.xml to the root of your project, something like this: 将文件descriptor.xml添加到项目的根目录,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
    <!-- copied from jar-with-dependencies (http://maven.apache.org/plugins/maven-assembly-plugin/descriptor-refs.html#jar-with-dependencies) -->
    <id>jar-with-deps-merge-services</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <containerDescriptorHandlers>
        <containerDescriptorHandler>
            <handlerName>metaInf-services</handlerName>
        </containerDescriptorHandler>
    </containerDescriptorHandlers>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>
</assembly>

The important part is the metaInf-services setting which merges the files in META-INF\\services . 重要的部分是metaInf-services设置,它合并META-INF\\services的文件。

  1. Add a reference to the descriptor.xml in your pom.xml : pom.xml添加对descriptor.xml的引用:
[...]
<build>
    <plugins>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2.1</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>your.main.MainClass</mainClass>
                    </manifest>
                </archive>
                <descriptors>
                    <descriptor>descriptor.xml</descriptor>
                </descriptors>
            </configuration>
        </plugin>
    </plugins>
</build>

Important notes: 重要笔记:

  • The maven-assembly-plugin version should be 2.2.1 because the current 3.x version does not seem to work. maven-assembly-plugin版本应该是2.2.1,因为当前的3.x版本似乎不起作用。 However, you can try newer 2.2.x or 2.x versions if really needed. 但是,如果确实需要,您可以尝试更新的2.2.x或2.x版本。 I've only tried 2.2.1 and it works. 我只试过2.2.1并且它有效。
  • The main-class block must be changed according to your main class name if you need it. 如果需要,必须根据主类名更改主类块。
  • The descriptor file can be placed in a different directory in your project, but then the reference in the pom must be changed (it is relative to the root of your maven project). 描述符文件可以放在项目的不同目录中,但是必须更改pom中的引用(它相对于maven项目的根目录)。
  • If you have jar-with-dependencies in your build config, this should be removed there because the descriptor file includes that setting. 如果你的构建配置中有jar-with-dependencies ,那么应该删除它,因为描述符文件包含该设置。

Even though I tried this on a sample project, this solution might not be perfect and you might adapt it according to your needs, but I hope this is a suitable point to start from. 即使我在一个示例项目中尝试过这个,但这个解决方案可能并不完美,您可以根据自己的需要进行调整,但我希望这是一个合适的起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM