Springboot2.x升级文档

    前言

一、选择对应的版本

二、升级前的注意事项

三、修改pom.xml依赖

四、maven依赖升级

五、配置文件升级

六、代码层的修改

    参考资料


前言

由于公司需要对现有技术架构进行升级,需要将springboot版本升级为2.x以上,与之对应的Springcloud版本也需升级。下面对升级的过程和问题做一个总结。


一、选择对应的版本

Springboot和Springcloud版本存在对应关系,关于Springboot和Springcloud的版本关联性,可以参考官方链接:springboot和springcloud版本对应关系,本文以Springboot-2.1.9以及Springcloud-Greenwich.SR2作为实例进行版本升级的演示。


二、升级前的注意事项

注意: springboot-2.x依赖于JDK8及以上,并且支持JDK9的新特性。所以要确认项目的JDK版本。

注意: springboot-2.x对一些第三方类库进行了版本升级,其中最重要的例如:Spring Framework 5+以及Tomcat 8.5+。因此对于Spring 4所集成的在新版本中可能会被废弃,例如:guava cache


三、修改pom.xml依赖

所示过程都以springboot项目开发规范进行,例如将parent定义为父工程,然后将Springcloud以依赖的形式引入。pom.xml文件的修改分为如下三个步骤:

  1. 修改parent标签内容,将项目父工程设定为springboot-2.x:
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
        <relativePath/>
    </parent>
    
  2. 修改properties标签内容,设定一些基本属性值,如springcloud版本:
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>
    
  3. 新增dependencyManagement标签内容,新增springcloud依赖:
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
  4. 您可以在pom.xml中增加如下内容,无需修改settings.xml的mirror镜像源即可使用阿里仓库进行jar包的下载。
    <repositories>
        <repository>
            <id>maven-ali</id>
            <url>http://maven.aliyun.com/nexus/content/groups/public//</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>always</updatePolicy>
                <checksumPolicy>fail</checksumPolicy>
            </snapshots>
        </repository>
    </repositories>
    

等待jar包下载完毕之后,升级的第一步已经完成,接下来进行jar包的管理。


四、maven依赖升级

升级版本之后,会导致很多jar包和配置文件的不兼容,因此,现在要开始修改依赖和配置文件的内容。注意:期望开发人员开始使用IDEA作为开发工具进行项目的升级,本文中的软件截图皆来自于IDEA,并期望借助IDEA完成项目的升级改造。

你可以在IDEA右侧,maven视图中看到,哪些依赖的版本失效,如图所示,版本号为"unknown"的即需要进行修改,以eureka为例,在新版本中eureka所属的artifactId发生了变化,修改为正确的artifactId即可。

Springboot2.x升级文档如果你使用的是eclipse,则在jar包下载过程中会报错如下:
Springboot2.x升级文档

  1. eureka-client-artifactId的改变:

    1.5.7的版本中,eureka依赖:
    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
    
    2.x以上的版本,eureka依赖:
    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>	   
    
  2. eureka-server-artifactId的改变:

    1.5.7的版本中,eureka依赖:
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>
    
    2.x以上的版本,eureka依赖:
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
  3. feign-artifactId的改变:

    1.5.7的版本中,feign依赖:
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
    </dependency>
    
    2.x以上的版本,feign依赖:
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  4. mybatis依赖升级,有关mybatis-spring-boot-stater版本与spring-boot版本的对应关系,见参考资料mybatis-springboot-starter官方文档

    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.1</version>
    </dependency>
    

修改完之后,IDEA的maven->dependencies视图中,原本为"unknown"版本的包将显示为正确的版本。


五、配置文件升级

接下来进行配置文件的修改,springboot-2.x废弃了很多原有的配置,当你用IDEA打开配置文件的时候,就会发现若干配置出现红波浪线如图所示,您可以通过IDEA快速修复功能(快捷键Alt+Enter)进行修正,这也是再次推荐使用IDEA的原因。或者您可以根据本文总结的配置对照表进行修改,但并不一定全。
Springboot2.x升级文档

  1. web部分:

    old property new property remark
    server.context-path server.servlet.context-path 项目访问路径
    server.context-parameters.* server.servlet.context-parameters.* ServletContext初始化参数
    spring.http.multipart.maxFileSize spring.servlet.multipart.max-file-size 限定单个文件上传大小的上限
    spring.http.multipart.maxRequestSize spring.servlet.multipart.max-request-size 限定单次请求文件大小的上限
  2. actuator部分:

    old property new property remark
    management.context-path management.server.servlet.context-path actuator暴露接口的前缀
    management.security.enabled actuator是否需要安全保证
    management.port management.server.port actuator暴露的端口
    endpoints.key.enabled management.endpoint.key.enabled 配置指定actuatorEndpoint
    management.endpoints.web.exposure.include=* 暴露所有端点
    endpoints.health.sensitive actuator的health接口是否需要安全保证
  3. security部分:

    old property new property remark
    security.user.name spring.security.user.name username
    security.user.password spring.security.user.password password
    security.basic.path (通过代码配置)
    security.basic.enabled (通过代码配置)
  4. redis部分:

    old property new property remark
    spring.redis.pool.max-active spring.redis.jedis.pool.max-active 最大活动连接数量
    spring.redis.pool.max-wait spring.redis.jedis.pool.max-wait 最大阻塞等待时间
    spring.redis.pool.max-idle spring.redis.jedis.pool.max-idle 最大空闲连接数量
    spring.redis.pool.min-idle spring.redis.jedis.pool.min-idle 最小空闲连接数量
  5. quartz部分:

    old property new property remark
  6. datasource部分:

    old property new property remark
    spring.datasource.driverClassName spring.datasource.driver-class-name
    spring.datasource.url spring.datasource.jdbc-url 多数据源
    spring.datasource.url spring.datasource.url 单数据源

    注意: 在新版本中,MySQL的驱动类名也变了,启动一个带有数据源的项目后,您将在控制台中看到如下日志信息:

    Loading class ‘com.mysql.jdbc.Driver’. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver’. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

  7. eureka部分:

    old property new property remark
    spring.cloud.client.ipAddress spring.cloud.client.ip-address eureka客户端的ip地址

六、代码层的修改

类所属的包名的改变
新版本中有一些类的包名更改了,例如DataSourceBuilder类:该类原有的包路径为

// 1.5.7版本中的路径
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
// 2.x版本中的路径
import org.springframework.boot.jdbc.DataSourceBuilder;

对于此类问题有很多,修改起来也比较简单,您可以使用IDEA自动修复工具进行包的改变,您只需要删除错误的import语句,IDEA会为您自动导包。

项目启动报错

接下来将解决一个比较棘手的问题:在本人升级的项目中使用了Spring4.x具有的guava cache,但是该组件在Spring 5中废除,取而代之的是caffeine。这意味着程序将不能再使用guava cache,尝试降低spring-context-support.jar的版本也是不行的。项目启动报错如图:
Springboot2.x升级文档对使用guava cache的工程进行代码修改,将缓存策略修改为caffeine。原有的guava缓存策略代码如下:

public GuavaCacheManager guavaCacheManager() {
    GuavaCacheManager cacheManager = new GuavaCacheManager();
    //规定了缓存在1小时没有使用的情况下进行回收
    //规定了缓存的最大容量
    cacheManager.setCacheBuilder(CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).maximumSize(100000));
    ArrayList<String> cacheNames = new ArrayList<>();
    cacheNames.add("common-cache-guava-caching");
    cacheManager.setCacheNames(cacheNames);

    return cacheManager;
}

使用springboot-caffeine的代码如下,配置与使用guava cache是等同的。有关于caffeine更多的配置或详细信息,请参考caffeine官方文档

public CaffeineCacheManager guavaCacheManager() {
    CaffeineCacheManager cacheManager = new CaffeineCacheManager();
    Caffeine caffeine = Caffeine.newBuilder()
        .initialCapacity(100)
        .maximumSize(100000)
        .expireAfterWrite(1, TimeUnit.HOURS);
    cacheManager.setCaffeine(caffeine);
    ArrayList<String> cacheNames = new ArrayList<>();
    cacheNames.add("common-cache-guava-caching");
    cacheManager.setCacheNames(cacheNames);
    return cacheManager;
}

springboot-2.x中redis的相关代码也需要修改,原有的代码如下:

public RedisCacheManager cacheManager(RedisTemplate redisTemplate) {
    RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate);
    //过期时间单位毫秒
    redisCacheManager.setDefaultExpiration(72000);
    redisCacheManager.setUsePrefix(true);
    redisCacheManager.setCachePrefix(new DefaultRedisCachePrefix());
    ArrayList<String> cacheNames = new ArrayList<>();
    cacheNames.add("common-cache-redis-caching");
}

升级后的RedisCacheManager删除了这个构造方法,修改代码如下所示,有关redis的最新使用方法请参考官方文档:Spring Data Redis官方文档

public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
    config.entryTtl(Duration.ofMillis(72000));

    Set<String> cacheNames = new HashSet<>();
    cacheNames.add("common-cache-redis-caching");

    Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
    configMap.put("common-cache-redis-caching", config);

    RedisCacheManager cacheManager = RedisCacheManager.builder(redisTemplate.getConnectionFactory())
        .initialCacheNames(cacheNames)
        .withInitialCacheConfigurations(configMap)
        .build();
    return cacheManager;
}

由devtools引发的类转换异常

在解决了代码编译问题之后,启动项目在运行时发现报错,大致归为ClassCastException: A cannot be cast to A的问题,明明是同一个类,但是在A aa = (A) obj;的时候发生异常。

在百度和查阅文档之后,发现是因为devtools造成的。devtools重新启动功能通过使用两个类加载器来实现,默认情况下,IDE加载的文件以 “restart” classloader加载,而任何以.jar结尾的文件将以“base” classloader加载。本人涂着省事的目的直接禁用了devtools依赖。以下是官方文档的说明已经解决问题的办法,您可以在META-INF/spring-devtools.properties文件中加入一些内容。更多详情参见spring-boot-devtools官方文档
Springboot2.x升级文档
前端request请求404

再次启动项目后,发现前端请求后台的接口有很多都是404,进一步发现这些请求都是xxx.do的方式,您可以进行如下配置:spring.mvc.pathmatch.use-suffix-pattern=true,建议新创建的项目不要使用.do或.action结尾的请求。具体原因参考springboot官方文档
Springboot2.x升级文档
前端request请求406

再次启动项目后,发现前端请求后台的接口存在部分406,另外在控制台中有Could not find acceptable representation报错。请您修改application启动类代码,继承WebMvcConfigurationSupport,并重新配置消息转化类和新增ResourceHandler,代码如下:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class MmsOperateApplication extends WebMvcConfigurationSupport {
    
    public static void main(String[] args) {
        SpringApplication.run (MmsOperateApplication.class, args);
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //1、定义一个convert转换消息的对象
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        //2、添加fastjson的配置信息
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        //3、在convert中添加配置信息
        fastConverter.setFastJsonConfig(fastJsonConfig);
        //4、将convert添加到converters中
        converters.add(fastConverter);
        //5、追加默认转换器
        super.addDefaultHttpMessageConverters(converters);
    }

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/index.html")
                .addResourceLocations("classpath:static/index.html");
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/");
    }
}

在修改完毕后,本人所升级的项目已能够正常启动。关于更多的问题或配置将在以后的日子里进行更新。


参考资料

[1] Upgrading from Spring Boot 1.5
[2] springboot和springcloud版本对应说明
[3] spring-redis文档
[4] springcloud文档
[5] caffeine官方文档
[6] mybatis-springboot-starter官方文档

Springboot2.x升级文档Springboot2.x升级文档 天上掉下的猪八戒 发布了3 篇原创文章 · 获赞 3 · 访问量 101 私信 关注
上一篇:springboot中Thymeleaf和Freemarker模板引擎的区别


下一篇:java-在Jar中加载资源