java - Spring boot 1.4.x 和自定义 CharsetProvider

标签 java spring spring-boot gsm

我正在尝试注册自定义 CharsetProvider 以便能够使用 X-Gsm7Bit 编码。我用 https://github.com/OpenSmpp/opensmpp/tree/master/charset/src/main/java/org/smpp/charset来自 Logica 的供应商。 为了注册这个新的字符集提供程序,我使用了内容为 org.smpp.charset.Gsm7BitCharsetProviderMETA-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/

相关文章:

java - 从单词中删除指定的尾随和前导标点符号 (Java)

java - 使用 Spring Boot 和 RabbitMQ 进行异步请求-回复

java - 读取本地的java spring属性

java - 如何修复 "401 Unauthorized. No Api Key provided"

java - 使用 api 26 构建应用程序,但使用 api 24 构建库

Java 1.4.2 - 读取文件

java - Spring WebFlow 中的重定向/转发到子域

java - 文本/csv文件下载在百行时转换为文本/纯文本

mysql - SpringBoot Redis 集成测试

mysql - 如何获取Keycloak访问 token 并将其存储在数据库中以供Spring Boot使用?