我正在尝试注册自定义 CharsetProvider 以便能够使用 X-Gsm7Bit 编码。我用 https://github.com/OpenSmpp/opensmpp/tree/master/charset/src/main/java/org/smpp/charset来自 Logica 的供应商。
为了注册这个新的字符集提供程序,我使用了内容为 org.smpp.charset.Gsm7BitCharsetProvider
的 META-INF/services/java.nio.charsets.spi.CharsetProvider
文件。
我无法让它工作。 测试应用程序的来源在这里 https://github.com/asmsoft/provider
当我将它作为 fat jar 启动时,我得到 java.util.ServiceConfigurationError: java.nio.charset.spi.CharsetProvider: Provider org.smpp.charset.Gsm7BitCharsetProvider not found
mvn clean
mvn package
java -jar target/provider-1.0-SNAPSHOT.jar
如果我用 mvn spring-boot:run
启动它,我会得到 java.io.UnsupportedEncodingException: X-Gsm7Bit
当我使用我的 IDE 启动应用程序时,一切正常。
目前我按如下方式解决了我的问题:我已将提供自定义字符集的 jar 放入 JAVA_HOME/jre/lib/ext
并且一切再次按预期工作,字符集正在启动时注册。
我对这个解决方案不满意,想寻求您的帮助。
最佳答案
我认为您遇到了 JDK 中的错误。 javadoc for CharsetProvider
说:
Charset providers are looked up via the current thread's context class loader
然而,code that looks up the providers讲述一个不同的故事:
ClassLoader cl = ClassLoader.getSystemClassLoader();
ServiceLoader<CharsetProvider> sl =
ServiceLoader.load(CharsetProvider.class, cl);
如您所见,它使用系统类加载器而不是线程的上下文类加载器。
它在您的 IDE 中工作,因为您的应用程序的类及其依赖项都可用于系统类加载器。当您将应用程序打包到一个 fat jar 子中时,它会失败,因为您的应用程序的类及其依赖项随后可用于 Spring Boot 的类加载器,它是系统类加载器的子级。在使用另一个类加载器的任何环境中,您都会遇到同样的问题,例如对 servlet 容器的传统 war 部署。
为避免该问题,您需要使提供者对系统类加载器可用。正如您所发现的,将其 jar 放在 JAVA_HOME/jre/lib/ext
中是实现该目的的一种方法。其他选项包括使用阴影 jar 而不是 fat jar,或者对 fat jar 进行后处理以将提供者的类直接添加到 jar 的根而不是作为嵌套 jar。
关于java - Spring boot 1.4.x 和自定义 CharsetProvider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39641604/