将 Spring Boot 应用迁移到 Java 9 — 模块 已翻译 100%

oschina 投递于 2017/10/30 16:17 (共 5 段, 翻译完成于 11-02)
阅读 1210
收藏 1
0
加载中

上周,我试图制作一个 Spring Boot 应用程序 —— 是一个著名宠物诊所(Pet Clinic)的 app,对 Java 9 兼容。这很不容易,我不得不放弃了很多功能。总而言之,唯一的好处是改进了 String 内存管理。

本周,我想完全拥抱 Java 9 模块系统来继续迁移。

配置模块元数据

Java 9 中的模块信息通过 module-info.java 文件实现。第一步是在源目录的根目录下创建一个这样的文件,模块名称为:

module org.springframework.samples.petclinic {
}

剩下的旅程可能是天堂或地狱。不过我很幸运受益于 IntelliJ IDEA,这个 IDE 向导会准确地说出它不能读取的类,并允许您将其放入模块文件中。最后,看起来是这样的

module org.springframework.samples.petclinic {
    requires java.xml.bind;
    requires javax.transaction.api;
    requires validation.api;
    requires hibernate.jpa;
    requires hibernate.validator;
    requires spring.beans;
    requires spring.core;
    requires spring.context;
    requires spring.tx;
    requires spring.web;
    requires spring.webmvc;
    requires spring.data.commons;
    requires spring.data.jpa;
    requires spring.boot;
    requires spring.boot.autoconfigure;
    requires cache.api;
}

请注意, maven-compiler-plugin 和 maven-surefire-plugin 中的模块配置可以被删除。

亚林瓜子
翻译于 2017/10/31 08:40
1

不使用 IDE 进行配置

如果你手上恰巧没有理想的 IDE 环境,配置过程如下:

  1. 运行 mvn clean test

  2. 分析错误日志来获取缺少的包名

  3. 定位到上面提到的包

  4. 如果这是一个模块 Jar,那么把模块名称加到依赖模块名称列表里面

  5. 否则,猜测一下自动模块名称(译注:自动模块名称(automatic module name)是为了在java 9 项目中使用那些没有进行模块化处理的包(即没有 module-info )而出现的概念,它们的名字一般就是去掉了版本号的jar包文件名),再加入到依赖模块名称列表里面

例如:

[ERROR] ~/spring-petclinic/src/main/java/org/springframework/samples/petclinic/system/CacheConfig.java:[21,16]
  package javax.cache is not visible
[ERROR]   (package javax.cache is declared in the unnamed module, but module javax.cache does not read it)

javax.cache 位于 cache-api-1.0.0.jar中,由于这不是一个模块,所以在 JAR 包中没有 module-info 文件。但可知它的自动模块名称为 cache.api 。将其写入到模块依赖中。重复上述步骤。

SeanWangOSC
翻译于 2017/10/31 16:13
0

ASM 故障

从这篇文章的第一部分开始,我已经意识到,Spring Boot 1.5 将不会与 Java 9 兼容。我们开始吧。

将 Spring Boot 升级到 2.0.0.M5,需要对模块依赖性进行一些更改:

  • hibernate.validator 变为 org.hibernate.validator

  • validation.api 变为 java.validation

当你认为它可以工作的时候:

Caused by: java.lang.RuntimeException
	at org.springframework.asm.ClassVisitor.visitModule(ClassVisitor.java:148)

这个问题已经记录在案。此时,显式声明主类解决了这个问题。

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <jvmArguments>--add-modules java.xml.bind</jvmArguments>
        <mainClass>org.springframework.samples.petclinic.PetClinicApplication</mainClass>
    </configuration>
    ...
</plugin>
亚林瓜子
翻译于 2017/11/01 08:37
0

Javassist 失败

现在 app 可以使用以下命令做测试了: mvn clean spring-boot:run 。不幸的是,一个新的异常挡住了我们前行的路:

2017-10-16 17:20:22.552  INFO 45661 --- [           main] utoConfigurationReportLoggingInitializer :

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-10-16 17:20:22.561 ERROR 45661 --- [           main] o.s.boot.SpringApplication               :
 Application startup failed

org.springframework.beans.factory.BeanCreationException:
  Error creating bean with name 'entityManagerFactory' defined in class path resource
   [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]:
    Invocation of init method failed; nested exception is org.hibernate.boot.archive.spi.ArchiveException:
     Could not build ClassFile

快速搜索下定位到 Java 9 和 Javassit 的一个不兼容性问题。Javassist 是这里的罪魁祸首。它的依赖性需要 Spring Data JPA,通过 Hibernate 传递。要解决它,需要移除依赖关系,并添加最新版本:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <exclusions>
        <exclusion>
            <artifactId>javassist</artifactId>
            <groupId>org.javassist</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.22.0-GA</version>
    <scope>runtime</scope>
</dependency>

幸运的是,此版本是兼容的 —— 最起码对我们的用法是。

Tocy
翻译于 2017/11/01 09:47
0

它运行了!

我们做到了! 如果你到了这一步,你应该拍拍肩膀,喝杯啤酒,或者你认为你应该得到的任何东西。

锦上添花的是,开发工具的依赖可以被重新添加。

结论

不管你喜欢还是不喜欢,迁移到 Java 9 需要使用 Jigsaw。至少,这意味着一趟痛苦的旅程,以及遇到错误就要搜索下一个补丁的过程,并且还要删除构建过程中的重要步骤。对于库/框架开发人员来说,为他们的内部 api 添加额外的访问控制层是很有趣的,对于应用程序来说这样做比较少。在这个阶段,不值得迁移到 Java 9。

我希望在几个月后再进行这个实验,到时候再留意情况的改善。

这篇文章的完整源代码可以在 GitHub 上找到。

溪边九节
翻译于 2017/10/31 16:55
0
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(1)

亚林瓜子
亚林瓜子
迁不动😂
返回顶部
顶部