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

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

  随着 Java 9 的到来,关于如何迁移应用程序以使用模块系统有很多的讨论。遗憾的是,大多数文章的焦点都集中于简单的 Hello World 程序上。或者更糟的是,对于 Spring 应用程序,示例应用程序使用传统做法 - 例如使用 XML 作为示例。

  本文的目的旨在通过对 Spring Boot 程序提供逐步的迁移指南来纠正这一点,本文所使用的示例程序是 Spring Pet clinic 。

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

  冲突的 Java 版本

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

  9

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

  冲突的 Java 版本

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

  [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(https://github.com/wro4j/wro4j/issues/1039)。改变已经提交并合并, 但是这个问题仍未解决,因为 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 设置:

  maven-compiler-plugin

  3.7.0

  --add-modules

  java.xml.bind

  现在项目可以编译了。

  测试故障

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

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

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

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

  maven-surefire-plugin

  2.20.1

  --add-modules java.xml.bind

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

  包故障

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

  [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.(AbstractZipArchiver.java:116)

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

  maven-jar-plugin

  3.0.2

  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.(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 里面加上必要的参数:

  org.springframework.boot

  spring-boot-maven-plugin

  --add-modules java.xml.bind

  ...

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

  结论

  在 JDK 9 运行重要的遗留项目需要费点功夫。更糟糕的是, 必须放弃一些重要特性: 代码覆盖和 web 性能提升。反过来, 唯一得到的微不足道的好处是 Stirng 内存空间改善。

  成都java培训哪家好,当然是成都达内培训,成都达内是一家专业的程序员培训机构,专注于网络营销课程,成都web前端培训,成都软件测试培训,成都php培训,成都java培训,成都安卓培训,成都会计实操培训,web前端开发,成都网络营销培训,成都it培训,成都编程培训,成都程序员培训等IT培训,专业的成都软件培训机构,专业师资授课,真实项目实战、零首付、低押金、名企就业,达内培训怎么样,成都java培训机构www.cdtedu.com/pxkc/java/

时间: 2024-10-11 04:06:53

将Spring Boot应用程序迁移到Java9:兼容性的相关文章

Spring Boot 2.0 迁移指南

![img](https://mmbiz.qpic.cn/mmbiz_jpg/1flHOHZw6Rs7yEJ6ItV43JZMS7AJWoMSZtxicnG0iaE0AvpUHI8oM7lxz1rRsmaa4IfbolVRG2WQwhXrchmVWS8Q/640?tp=webp&wxfrom=5&wx_lazy=1&wx_co=1) ### 前提 本文档将帮助您把应用程序迁移到 Spring Boot 2.0. ### 在你开始之前 首先,**Spring Boot 2.0需要Ja

Spring Boot入门程序

创建第一个Spring Boot的入门程序. 带你一步一步的,搭建第一个Spring Boot 的入门程序,并成功运行,通过实践过程,初步认识和了解如何使用Spring Boot 创建应用程序. 一.开发环境 (1)JDK 1.8 (2)Eclipse Oxygen EE版本 或者也可以使用 IntelliJ IDEA (3)Tomcat 9 二.创建 Spring Boot 入门程序 1.创建工程 在Eclilpse EE中,点击"File"--"New"--&q

docker 部署Spring Boot:Docker化Spring Boot应用程序

第一章 1.创建项目存放目录 mkdir /root/sproot -p 2.准备好Spring Boot应用程序 jar 包 testrest.jar 第二章 1. 安装docker 在所有节点执行:   setenforce 0 iptables -F iptables -t nat -F iptables -I FORWARD -s 0.0.0.0/0 -d 0.0.0.0/0 -j ACCEPT iptables -I INPUT -s 192.168.0.0/24 -j ACCEPT

2.3.2 引导Spring Boot应用程序:编写引导类

我们的目标是在Spring Boot中运行一个简单的微服务,然后重复这个步骤以提供功能.为此,我们需要在许可证服务微服务中创建以下两个类. 一个Spring引导类,可被Spring Boot用于启动和初始化应用程序. 一个Spring控制器类,用来公开可以被微服务调用的HTTP端点. 如刚才所见,Spring Boot使用注解来简化设置和配置服务.在代码清单2-2中查看引导类时,这一点就变得显然易见.这个引导类位于src/main/java/com/thoughtmechanix/license

02-第一个Spring Boot应用程序

Spring Boot深度课程系列 02第一个Spring Boot应用程序 1.版本要求 集成开发环境:IntelliJ IDEA 2017.2.1 ,Spring Boot 版本:2.2.42. 2.步骤介绍 3.编写Helloworld,参照Spring MVC的写法 A) 在chapter01文件夹下创建包controller,创建类HelloController. B) 代码如下 package com.java.chapter01.controller; import org.spr

Spring boot web程序static资源放在jar外部

spring boot程序的static目录默认在resources/static目录, 打包为jar的时候,会把static目录打包进去,这样会存在一些问题: static文件过多,造成jar包体积过大 临时修改不方便 查看官方文档,可以发现,static其实是可以外置的. 方法1 直接修改配置文件 spring.resources.static-locations=file:///E://resources/static 自定义Configuration方法 @Configuration p

Spring Boot 2程序不能加载 com.mysql.jdbc.Driver 问题

用Spring Boot Starter 向导生成了一个很简单SpringBoot程序, 用到了 MySQL, 总是下面不能加载 Mysql driver class 错误. Cannot load driver class: com.mysql.jdbc.Driver 刚开始以为是 application.properties 中相关的配置项写法不合规, 发现很正常. 检查了 MySQL jar 文件也很正常. 突然想起之前好像也碰到过同样的问题, 又想了很久, 终于想起上次是因为用了 spr

第一个Spring Boot Web程序

需要的环境和工具: 1.Eclipse2.Java环境(JDK 1.7或以上版本)3.Maven 3.0+(Eclipse已经内置了) 写个Hello Spring: 1.新建一个Maven项目 选择 maven-archetype-quickstart 删除项目中的 test,这个我们用不到, 刚刚建好的项目如图所示: 修改 pom.xml ,如果你是第一次玩Spring那么修改pom.xml后Eclipse会自动下载相关依赖包: 1 <project xmlns="http://mav

Spring boot 开发应用程序

一 .maven POM.XML <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&g