相关推荐recommended
我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!
作者:mmseoamin日期:2023-12-11

项目从jdk8升级到jdk17,我不是为了追求java 17的新特性(准确来说也还没有去了解有什么新特性),也不是为了准确与时俱进,永远走在java行列的最前端,纯粹因为项目需要,因为我们都知道,只要项目能跑,你就不要动它!

目录

  • 背景
  • 目标
  • 环境安装
    • Java 17
      • 下载
        • 方式一
        • 方式二
        • 配置环境变量与java8共存
        • SpringBoot3.0.0
        • Maven 3.6.3+
        • Idea 2022.2.1+
          • 下载
          • 安装
          • 配置IDEA和项目 java17环境
            • IDEA中Maven设置
            • IDEA环境配置
              • Setting设置
              • Project Structure设置
              • 问题处理
                • 运行项目出现 无效的源发行版: 17
                • hibernate unknown
                • ERROR StatusLogger Unable to create Lookup for ctx
                • java.lang.TypeNotPresentException: Type javax.servlet.http.HttpServletRequest not present
                • swagger替换为openapi后,会有报错
                • flyway问题
                • 动态数据源问题
                • 最后

                  背景

                  Java 程序员应该都熟悉下面这句话: 版本任他发,我用 Java 8 。自从 2014 年 3 月 Java SE 8.0(1.8.0)发布,到现在已经是第九年,21 年 9 月 Java SE 17(LTS)也已经发布,但绝大部分 Java 开发人员依然使用 1.8 版本。懒惰是其中的一方面原因,生产环境稳定大于一切的压力之下,既然 Java8 已经表现很好没有什么问题,那么也就没有必要冒险去做版本升级了,毕竟“升级”在很多情况下都意味着工作量和风险。

                  不过在今年之后,这个情况发生了变化。由于厂商纷纷宣布即将停止 1.8 版本的更新维护:Oracle 于 2019 年 1 月停止商用用途中的更新,2020 年 12 月停止非商用版本更新;AdoptOpenJDK 于 2023 年 9 月或之前停止更新;Amazon Corretto 于 2023 年 6 月或之前停止更新。意味着 23 年 9 月之后,将不再有厂商继续更新 Java 8。

                  2014年发布的java SE 8和2017年发布的java EE 8,至今还是使用最广泛的java版本,大部分java开发者对于java 8之后的升级总是敬而远之,这跟java 9以后的破坏性升级和oracle的商用协议有关,但随着9月java 17的发布,我们有更多理由去升级和在新项目中使用更新的java了。


                  目标

                  本次操作是mac版本下的

                  • Java 8 应用升级到 Java 17
                  • SpringBoot 版本升级到 SpringBoot3.0.0
                  • 推荐的 Java 17 开发环境包括:Maven 3.6.3+、Idea 2022.2.1+

                    环境安装

                    Java 17

                    下载

                    方式一

                    下载链接🔗:JDK开发工具包17.0.9下载

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第1张

                    要选择对应的版本去下载,比如我mac,在左上角的苹果标志,直接点击,弹出菜单,点击“关于本机”,确认一下本机电脑的CPU是Intel还是ARM。

                    1. 如果是Intel,点击“x64 DMG Installer”的右边网址
                    2. 或者选择 macOS 下的 ARM64 DMG(适用于苹果芯片,如 M1、M2 等)

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第2张

                    我的是M2,所以如上图

                    按照步骤直接默认选项安装即可。

                    方式二

                    在 mac 下,也可以使用 sdkman 来安装 jdk 和 maven:

                    (其实我一开始是使用的此方法,但是由于那会网络一直不稳定,最后还是使用的方法一)

                    命令行执行下面操作即可(sdk 相关命令可以使用 sdk help 查看)

                    curl -s "https://get.sdkman.io" | bash
                    sdk install java 22.3.r17-grl
                    sdk install maven 3.8.2
                    

                    下载中截图

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第3张

                    由于我网络不稳定,出现如下报错:

                    Installing script cli archive...
                    * Downloading...
                    curl: (28) Failed to connect to github.com port 443 after 75015 ms: Couldn't connect to server
                    'curl --fail --location --progress-bar "${SDKMAN_SERVICE}/broker/download/sdkman/install/${SDKMAN_VERSION}/${SDKMAN_PLATFORM}" > "$sdkman_zip_file"': command failed with exit code 28.
                    

                    然后我就再次执行命令

                    curl -s "https://get.sdkman.io" | bash
                    

                    结果提示已经存在,可以强制更新

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第4张

                    算了,我还是卸载重新安装吧:

                    rm -rf "$HOME/.sdkman"
                    

                    再次执行上面的安装命令

                    继续有报错出来

                    touch: /Users/myName/.bash_profile: Permission denied
                    'touch "$sdkman_bash_profile"': command failed with exit code 1.
                    

                    可以看到上面报错是要修改.bash_profile文件,我们可以自己修改

                    vim ~/.bash_profile
                    

                    在.bash_profile文件最后一行加上下面内容

                    export SDKMAN_CANDIDATES_API=https://api.sdkman.io/2
                    [[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"
                    

                    然后执行

                    source ~/.bash_profile
                    

                    下载jdk17

                    sdk install java 22.3.r17-grl
                    

                    下载中

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第5张

                    我到这里又出现了下载超时的问题了,心里一万只🦙🦙🦙跑过啊,于是我果断去用了方式一


                    配置环境变量与java8共存

                    由于之前也是一直使用java8,所以下载安装完java17后,可以看下java版本是否有变

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第6张

                    还是java8,因为我们的环境还是没有变,我的是.bash_profile文件

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第7张

                    先看看下载的jdk17在不在默认下载的目录/Library/Java/JavaVirtualMachines

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第8张

                    接下来就是更换环境变量,使用jdk17了,如下

                    vim ~/.bash_profile
                    

                    增加如下内容

                    export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
                    #export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home
                    export PATH=$JAVA_HOME/bin:$PATH:.
                    export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
                    

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第9张

                    然后执行保存,再查看版本

                    source ~/.bash_profile
                    java -version
                    

                    可以发现已经是java17了

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第10张

                    不同Java版本间的切换

                    若要将Java17切换到Java其他版本,只需要将.bash_profile文件中的JAVA_HOME改成Java其他版本的目录即可,修改的过程和之前配置JAVA_HOME环境变量类似。


                    SpringBoot3.0.0

                    查看springBoot版本

                    	
                    		org.springframework.boot
                    		spring-boot-starter-parent
                    		2.5.5
                    		 
                    	
                    

                    这里只要更换版本即可

                    3.0.0
                    

                    然后reload maven,一定会有报错,这个我在下面也会有提到


                    Maven 3.6.3+

                    这里需要注意下载的版本是否是你的IDEA版本支持的Maven版本

                    Maven官网

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第11张

                    点击 Download 拉到最底下,下载历史版本

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第12张

                    下载解压更新系统变量就不说了


                    Idea 2022.2.1+

                    下载

                    因为社区版免费使用,所以下载社区版安装就好。下载的版本是Idea 2022.2.1+就可以,不做过多阐述。
                    

                    下载地址:https://www.jetbrains.com/idea/download/#section=mac

                    安装

                    mac 下,ideaIC-2023.1.2-aarch64.dmg 直接双击安装,按照说明完成操作即可。接下来就是启动。
                    

                    配置IDEA和项目 java17环境

                    IDEA中Maven设置

                    进入Idea File->settings…->Build,Execution,Deployment->Build Tools->Maven

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第13张

                    还需要配置另两个地方:Runner和Importing内选择Java17

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第14张

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第15张

                    IDEA环境配置

                    Setting设置

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第16张

                    Project Structure设置

                    File - Project Structure…

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第17张

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第18张

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第19张

                    ⚠️如果编译项目出现 java: 无效的源发行版: 17,则需要设置:

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第20张

                    全部配置完毕,就可以启动项目了,这就会遇到下面一堆的问题了,但是不要慌,我们一个个解决


                    问题处理

                    从这里开始,就是本篇的重点了,一个接一个地处理问题。
                    

                    运行项目出现 无效的源发行版: 17

                    这个可能性是有两种

                    1. 环境变量配置后没有成功保存

                      • 打开shell,执行java -version命令,如果出现的是jdk17,则说明环境变量正确,反之再去修改环境变量
                      • idea在更换jdk后没有重启

                    如果没问题,查看项目目录 External Libraries 外部库中,使用的应该就是Java17,如下

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第21张

                    hibernate unknown

                    maven中Dependencies引入的hibernate报错

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第22张

                    其实就是版本兼容的问题

                    需要删除原来的依赖,然后升级版本:6.1.7.Final

                            
                                org.hibernate
                                hibernate-core
                                6.1.7.Final
                            
                    

                    依赖默认情况下都在如下路径,后面的删除依赖也是同样的

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第23张

                    ERROR StatusLogger Unable to create Lookup for ctx

                    启动报错

                    我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第24张

                    ERROR StatusLogger Unable to create Lookup for ctx
                     java.lang.NoClassDefFoundError: org/apache/logging/log4j/util/ServiceLoaderUtil
                    Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.util.ServiceLoaderUtil
                    	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
                    	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
                    

                    这个可以看官方发行版本:log4j版本:2.22.0

                    其实也是版本兼容的问题,需要删除原来的依赖,然后升级版本:2.22.0

                    			
                    				org.apache.mvnging.log4j
                    				log4j-core
                    				2.22.0
                    			
                    			
                    				org.apache.logging.log4j
                    				log4j-slf4j-impl
                    				2.22.0
                    			
                    			
                    				org.apache.logging.log4j
                    				log4j-jul
                    				2.22.0
                    			
                    			
                    				org.apache.logging.log4j
                    				log4j-api
                    				2.22.0
                    			
                    

                    java.lang.TypeNotPresentException: Type javax.servlet.http.HttpServletRequest not present

                    启动报错

                    java.lang.TypeNotPresentException: Type javax.servlet.http.HttpServletRequest not present
                    Caused by: java.lang.ClassNotFoundException: javax.servlet.http.HttpServletRequest
                    

                    这个问题让我找了好半天的解决办法

                    参考链接:

                    1. Springfox Type javax.servlet.http.HttpServletRequest not present
                    2. Spring Boot3.0(六):整合swagger
                    3. Type javax.servlet.http.HttpServletRequest not present #4061

                    原因是:SpringFox 和 Spring Boot 3 的组合将无法工作。这里就需要替换了

                    解决:

                    需要删除原来的依赖

                    • 删除SpringFox的引用并且对于spring-boot和swagger-ui之间的集成
                      			
                      				io.springfox
                      				springfox-boot-starter
                      				${springfox.version}
                      			
                      
                      • 将库添加到项目依赖项列表中(无需额外配置):
                        
                            org.springdoc
                            springdoc-openapi-starter-webmvc-ui
                            2.2.0
                        
                        

                        swagger替换为openapi后,会有报错

                        这里替换为如下类即可

                        我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第25张

                        我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第26张

                        更多内容可以查看springfox迁移指南

                        flyway问题

                        org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$FlywayConfiguration and org.flywaydb.core.api.configuration.FluentConfiguration

                        我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!,在这里插入图片描述,第27张

                        ***************************APPLICATION FAILED TO START***************************Description:An attempt was made to call a method that does not exist. The attempt was made from the following location:
                        org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$FlywayConfiguration.configureProperties(FlywayAutoConfiguration.java:234)The following method did not exist:    'org.flywaydb.core.api.configuration.FluentConfiguration org.flywaydb.core.api.configuration.FluentConfiguration.oracleSqlplus(boolean)'The calling method's class, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$FlywayConfiguration, was loaded from the following location:
                        Action:Correct the classpath of your application so that it contains compatible versions of the classes org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$FlywayConfiguration and org.flywaydb.core.api.configuration.FluentConfiguration
                        

                        解决

                        升级版本:

                        			
                        				org.flywaydb
                        				flyway-core
                        				7.14.0
                        			
                        

                        并且:将属性设置为spring.flyway.enabled来禁用 Flyway 的自动配置

                        参考链接🔗:Spring-boot 3.0不支持flyway 7.15

                        动态数据源问题

                        ***************************
                        APPLICATION FAILED TO START
                        ***************************
                        Description:
                        Parameter 0 of constructor in com.axiomesh.bt.common.BTInitializer required a bean of type 'com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator' that could not be found.
                        Action:
                        Consider defining a bean of type 'com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator' in your configuration.
                        

                        解决