ImageIO PSD 库插件在 jar 中不起作用
ImageIO PSD library plugin not working inside of a jar
我正在使用 ImageIO 并尝试将代码打包到 JAR 中,但是,我发现(经过一些调试后)打包的 JAR 中不存在 PSD 插件
感谢这个答案中的代码,我发现了:
Add/remove ImageReader from jar to ImageIO-registry
在我的 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>
我使用的maven命令是:
clean compile assembly:single
旁注我用来调试的代码:
ImageIO.scanForPlugins()
IIORegistry.getDefaultInstance().registerApplicationClasspathSpis()
val ir = ImageIO.getImageReadersByFormatName("PSD")
while (ir.hasNext())
{
val r = ir.next() as ImageReader
println(r)
}
在 IDE 中打印:
com.twelvemonkeys.imageio.plugins.psd.PSDImageReader@1963006a
当 运行 来自命令行的 jar 时,它不打印任何东西,这让我相信 PSD 插件在 JAR 内部不工作,但如何工作?
问题是目标 assembly:single
将您自己的项目中的 "everything" 和所有引用的 JAR 合并到一个 JAR 中,但跳过了那里存在的文件。
ImageIO 依赖于 Java 的 SPI/service 加载器机制,因此插件将通过 META-INF\services\javax.imageio.spi.ImageReaderSpi
加载。但是,当有多个 JAR 包含这样的文件并使用 assembly:single
时,其中一个文件 "wins" 和其他 JAR 中的文件将被跳过。在您的项目中,imageio-bmp
和 imageio-psd
都有这样一个文件,第一个文件 "wins" 在生成的 JAR 中。 (似乎 IDE 以另一个顺序和正确的版本 "wins" 加载这些文件,但这只是一个猜测。)
解决方案: Maven 应该将所有 META-INF\services\javax.imageio.spi.ImageReaderSpi
文件合并到生成的 JAR 中的一个文件中。为此,Maven 需要额外的配置信息。
- 将文件
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>
重要的部分是 metaInf-services
设置,它合并 META-INF\services
中的文件。
- 在您的
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>
重要提示:
- maven-assembly-plugin版本应该是2.2.1,因为目前的3.x版本好像不行。但是,如果确实需要,您可以尝试更新的 2.2.x 或 2.x 版本。我只试过 2.2.1 就可以了。
- main-class 块必须根据您的 main class 名称更改,如果需要的话。
- 描述符文件可以放在你项目的不同目录下,但是之后pom中的引用一定要改(相对于你maven项目的根目录)。
- 如果您的构建配置中有
jar-with-dependencies
,则应将其删除,因为描述符文件包含该设置。
虽然我在一个示例项目上尝试过,但这个解决方案可能并不完美,您可以根据需要进行调整,但我希望这是一个合适的起点。
我正在使用 ImageIO 并尝试将代码打包到 JAR 中,但是,我发现(经过一些调试后)打包的 JAR 中不存在 PSD 插件
感谢这个答案中的代码,我发现了: Add/remove ImageReader from jar to ImageIO-registry
在我的 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>
我使用的maven命令是:
clean compile assembly:single
旁注我用来调试的代码:
ImageIO.scanForPlugins()
IIORegistry.getDefaultInstance().registerApplicationClasspathSpis()
val ir = ImageIO.getImageReadersByFormatName("PSD")
while (ir.hasNext())
{
val r = ir.next() as ImageReader
println(r)
}
在 IDE 中打印:
com.twelvemonkeys.imageio.plugins.psd.PSDImageReader@1963006a
当 运行 来自命令行的 jar 时,它不打印任何东西,这让我相信 PSD 插件在 JAR 内部不工作,但如何工作?
问题是目标 assembly:single
将您自己的项目中的 "everything" 和所有引用的 JAR 合并到一个 JAR 中,但跳过了那里存在的文件。
ImageIO 依赖于 Java 的 SPI/service 加载器机制,因此插件将通过 META-INF\services\javax.imageio.spi.ImageReaderSpi
加载。但是,当有多个 JAR 包含这样的文件并使用 assembly:single
时,其中一个文件 "wins" 和其他 JAR 中的文件将被跳过。在您的项目中,imageio-bmp
和 imageio-psd
都有这样一个文件,第一个文件 "wins" 在生成的 JAR 中。 (似乎 IDE 以另一个顺序和正确的版本 "wins" 加载这些文件,但这只是一个猜测。)
解决方案: Maven 应该将所有 META-INF\services\javax.imageio.spi.ImageReaderSpi
文件合并到生成的 JAR 中的一个文件中。为此,Maven 需要额外的配置信息。
- 将文件
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>
重要的部分是 metaInf-services
设置,它合并 META-INF\services
中的文件。
- 在您的
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>
重要提示:
- maven-assembly-plugin版本应该是2.2.1,因为目前的3.x版本好像不行。但是,如果确实需要,您可以尝试更新的 2.2.x 或 2.x 版本。我只试过 2.2.1 就可以了。
- main-class 块必须根据您的 main class 名称更改,如果需要的话。
- 描述符文件可以放在你项目的不同目录下,但是之后pom中的引用一定要改(相对于你maven项目的根目录)。
- 如果您的构建配置中有
jar-with-dependencies
,则应将其删除,因为描述符文件包含该设置。
虽然我在一个示例项目上尝试过,但这个解决方案可能并不完美,您可以根据需要进行调整,但我希望这是一个合适的起点。