2KB项目,专业的源码交易网站 帮助 收藏 每日签到

将 Spring Boot 应用程序迁移到 Java 9:兼容性

  • 时间:2019-01-23 18:25 编辑:2KB 来源:2KB.COM 阅读:500
  • 扫一扫,手机访问
  • 分享
摘要: 英文原文:Mig
英文原文:Migrating a Spring Boot App to Java 9: Compatibility

随着 Java 9 的到来,关于如何迁移应用程序以使用模块系统有很多的讨论。遗憾的是,大多数文章的焦点都集中于简单的 Hello World 程序上。或者更糟的是,对于 Spring 应用程序,示例应用程序使用传统做法 - 例如使用 XML 作为示例。本文的目的旨在通过对 Spring Boot 程序提供逐步的迁移指南来纠正这一点,本文所使用的示例程序是 Spring Pet clinic 。

使用 Java 9 主要有两个步骤:首先,要兼容,然后使用完整的模块系统。这篇文章目的是实现第一点,后续的文章会考虑后面一点。

冲突的 Java 版本

一旦 JDK9 在目标机器上可用,首先在 POM 中就要解决冲突,把 java.version 的值从 8 修改为 9:

<properties>
    <!-- Generic properties -->
    <java.version>9</java.version>
</properties>

现在,可以进行 mvn clean 编译。

Cobertura 的故障

发现的第一个错误是这样的:

[ERROR] Failed to execute goal org.codehaus.mojo:cobertura-maven-plugin:2.7:clean (default) on project spring-petclinic:
 Execution default of goal org.codehaus.mojo:cobertura-maven-plugin:2.7:clean failed:
  Plugin org.codehaus.mojo:cobertura-maven-plugin:2.7 or one of its dependencies could not be resolved:
  Could not find artifact com.sun:tools:jar:0 at
   specified path /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/../lib/tools.jar -> [Help 1]

Cobertura 是一款免费的Java代码覆盖率报告工具。
— https://github.com/cobertura/cobertura

它需要访问 tools.jar,而这一部分是 JDK8(或更早的)。Java 9 的一个改变就是移除了这个库。因此,就不能编译了。这已经是一个被记录了的问题。Cobertura 库的最近一次提交是一年前了,只是对 Cobertura Maven 插件进行了注释。想想还是让 JaCoCo  代替 Cobertura 吧。

Wro4J 错误

下一个错误是:

[ERROR] Failed to execute goal ro.isdc.wro4j:wro4j-maven-plugin:1.8.0:run (default) on project spring-petclinic:
 Execution default of goal ro.isdc.wro4j:wro4j-maven-plugin:1.8.0:run failed:
  An API incompatibility was encountered while executing ro.isdc.wro4j:wro4j-maven-plugin:1.8.0:run:
   java.lang.ExceptionInInitializerError: null


wro4j 是一个免费开源的 Java 项目,可以有效减少项目页面的加载时间. 它能很好地组织 (js & css) 静态资源, 在运行期(使用简单的过滤器) 或者编译器 (使用 maven 插件)合并或最小化这些资源。此外在处理 web 资源时,有很多有用的的特性可以使用. 
— https://github.com/wro4j/wro4j

这个问题引用自 Github issue。改变已经提交并合并, 但是这个问题仍未解决,因为 Java 9 的兼容应该是2.0 版的一部分.

现在我们给 Wro4J 加上注释 .

编译失败

此时编译项目显示下面的错误信息:

/Users/i303869/projects/private/spring-petclinic/src/main/java/org/springframework/samples/petclinic/vet/Vet.java
Error:(30, 22) java: package javax.xml.bind.annotation is not visible
  (package javax.xml.bind.annotation is declared in module java.xml.bind, which is not in the module graph)
/Users/i303869/projects/private/spring-petclinic/src/main/java/org/springframework/samples/petclinic/vet/Vets.java
Error:(21, 22) java: package javax.xml.bind.annotation is not visible
  (package javax.xml.bind.annotation is declared in module java.xml.bind, which is not in the module graph)
Error:(22, 22) java: package javax.xml.bind.annotation is not visible
  (package javax.xml.bind.annotation is declared in module java.xml.bind, which is not in the module graph)

这意味着,在默认情况下,类路径下的代码无法访问模块。这个问题需要用 Java 9 的 javac 编译指令加上选项-- add-modules 手动添加。在 Maven 里, 可以用 maven-compiler-plugin 设置:

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.7.0</version>
    <configuration>
        <compilerArgs>
            <arg>--add-modules</arg>
            <arg>java.xml.bind</arg>
        </compilerArgs>
    </configuration>
</plugin>

现在项目可以编译了。

测试故障

接下来的步骤是使用 mvn 测试进行的单元测试失败的过程。

导致的原因是一样的,但更难找到。它需要检查那些万无一失的报告。有些包含以下行中的异常:

Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException

又一次,测试代码不能访问模块。然而,这一次,需要配置 maven-surefire-plugin 插件:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.20.1</version>
    <configuration>
        <argLine>--add-modules java.xml.bind</argLine>
    </configuration>
</plugin>

这样才能使得测试工作有效。

包故障

如果有人认为这是路的尽头,那就再想想。打包阶段也会出现一个相当神秘的错误:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-jar-plugin:2.6:jar (default-jar) on project spring-petclinic:
 Execution default-jar of goal org.apache.maven.plugins:maven-jar-plugin:2.6:jar failed:
  An API incompatibility was encountered while executing org.apache.maven.plugins:maven-jar-plugin:2.6:jar:
   java.lang.ExceptionInInitializerError: null
...
Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
at org.codehaus.plexus.archiver.zip.AbstractZipArchiver.<clinit>(AbstractZipArchiver.java:116)

这一项更难找到: 它需要谷歌搜索才能找到解决方案。这被归咎于 plexus-archiver。maven-jar-plugin 与最新版本冲突,而本文编写时使用 Java 9 兼容版本的 archiver 版本,解决了这个问题:

<plugin>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.0.2</version>
</plugin>

Spring Boot 插件错误

走到这一步, 项目最终可以正常编译、测试、打包。下一步是使用 Spring Boot 的 Maven 插件运行应用,即 mvn spring-boot:run。但是再次显示运行失败…:

[INFO] --- spring-boot-maven-plugin:1.5.1.RELEASE:run (default-cli) @ spring-petclinic ---
[INFO] Attaching agents: []
Exception in thread "main" java.lang.ClassCastException:
 java.base/jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to java.base/java.net.URLClassLoader
at o.s.b.devtools.restart.DefaultRestartInitializer.getUrls(DefaultRestartInitializer.java:93)
at o.s.b.devtools.restart.DefaultRestartInitializer.getInitialUrls(DefaultRestartInitializer.java:56)
at o.s.b.devtools.restart.Restarter.<init>(Restarter.java:140)
at o.s.b.devtools.restart.Restarter.initialize(Restarter.java:546)
at o.s.b.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:67)
at o.s.b.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:45)
at o.s.c.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
at o.s.c.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at o.s.c.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:122)
at o.s.b.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:68)
at o.s.b.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:48)
at o.s.b.SpringApplication.run(SpringApplication.java:303)
at o.s.b.SpringApplication.run(SpringApplication.java:1162)
at o.s.b.SpringApplication.run(SpringApplication.java:1151)
at org.springframework.samples.petclinic.PetClinicApplication.main(PetClinicApplication.java:32)

这是因为 Spring Boot v1.5 开发者工具和 Java 9 不兼容,可以在 documented issue 里找到。

好在这个 bug 在 Spring Boot 2.0.0.M5 里已经修复。但不幸的是, 在写这篇文章的时候,特定的版本仍然无法使用。现在, 移除开发者工具,再次尝试运行。又失败了, 但是这次显示的是一个熟悉的异常:

Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException

在 spring-boot-maven-plugin 里面加上必要的参数:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <jvmArguments>--add-modules java.xml.bind</jvmArguments>
    </configuration>
    ...
</plugin>

应用终于启动成功并可以访问了!

结论

在 JDK 9 运行重要的遗留项目需要费点功夫。更糟糕的是, 必须放弃一些重要特性: 代码覆盖和 web 性能提升。反过来, 唯一得到的微不足道的好处是 Stirng 内存空间改善。在下一篇博客里,我会尝试改善这一情况,在项目里使用模块化的特性。

这篇文章的全部源码位于 GitHub 

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部