经过一个多月的努力,奇文网盘终于又出来了一个比较稳定的版本了,这个版本经历了很多新功能的优化,还有底层框架Spring Boot版本的更新,这篇文章主要讲述一些升级过程中遇到的问题,同时希望大家能够在这个过程中也能获得一些新知识,感受新版本带来的变化。
01
—
为什么要升级2.6.2
相比大家都听说过上个月log4j2 爆出来的远程代码执行漏洞,这个漏洞的影响范围是非常大的,可谓是全球性的。
而奇文网盘所使用的的log4j2,也在此次影响范围之中,作为一款优秀的前后端分离的网盘,目前已被很多中小型公司所使用,或作为二次开发使用。因此在bug爆出来的当天,就有小伙伴在群里询问如何升级log4j2,log4j2是Spring Boot的一个基础依赖包,但是在当时连最新版本的Spring Boot版本也在影响范围之中,因此我给的升级建议就是在pom中覆盖版本即可,但是不一定有什么新影响。
02
—
Spring Boot 官方包紧急更新
Spring Boot 作为基础框架,也没闲着,接连发布了好几个版本。奇文网盘也紧跟着脚步,将Spring Boot升级到了最新,直接从2.4.x到2.6.x,跨了两个大版本。
03
—
JPA建表机制变化
奇文网盘的建表和建库是在启动阶段通过JAP来完成的,在网盘的上个版本,启动项目的时候,会先创建或更新表,然后更新数据,但是在网盘升级到最新版本之后,这种机制发生了一些变化。
在旧项目配置文件中,配置如下,包含初始化数据的路径(database/data.sql),初始化表规则(update),编码格式(utf-8),模式(ALWAYS),在启动的时候会扫描数据库,自动完成建表,并将初始化数据跑到库中:
#数据库初始化
spring.datasource.data=classpath:database/data.sql
spring.datasource.sql-script-encoding=utf-8
spring.datasource.initialization-mode=ALWAYS
#jpa配置
spring.jpa.properties.hibernate.hbm2ddl.auto=update
复制
而在新版本中,可以看到jpa相关配置文件只剩下一行了,如下:
#jpa配置 create/update
spring.jpa.hibernate.ddl-auto=update
复制
当配置为 create 时,系统启动时会创建表结构并更新数据,配置为 update 时,系统启动时仅仅只是创建或更新表结构,并不会初始化数据。
因此在这个最新版本中,我将该值默认配置为update,用户在启动系统后需要手动执行数据库初始化脚本,该脚本存放在 resources/import.sql
而且我还多做了一步,在系统数据未初始化时,后台能够给出异常报错,用户部署后,一看日志便知道是怎么回事,如下图:
04
—
多环境切换
在Spring boot 中,当有多个环境的配置文件需要切换的时候,只需要修改application.properties中的配置即可:
#环境切换 dev/prod
spring.profiles.active=dev
复制
目前还真是这样,这个值不配置还不行,假如没有配置,系统就不会加载带环境后缀的配置文件,如 application-dev.properties。
但是之前的版本如果不配置,系统默认会加载dev后缀的配置,说明Spring Boot取消了这种默认值。
还有另一处不同,那就是之前旧版本,该配置在大部分场景下都不生效,假如该配置修改为prod,启动的时候还是加载的dev的配置,网上大部分的解决办法都是使用系统环境变量来处理,现在反倒好了,无脑配置该属性便可。
05
—
ES启动问题
这个问题花了我好几天的时间,才得以解决,ES是一个搜索插件,上个版本用户如果没有打开ES服务端口,并不会影响网盘的启动,而现在,如果没有启动ES,网盘启动直接就报错了,报的错大概是下面这种:
Caused by: java.util.concurrent.ExecutionException: java.net.ConnectException: Timeout connecting to [/127.0.0.1:9200]
at org.elasticsearch.common.util.concurrent.BaseFuture$Sync.getValue(BaseFuture.java:262) ~[elasticsearch-7.15.2.jar:7.15.2]
at org.elasticsearch.common.util.concurrent.BaseFuture$Sync.get(BaseFuture.java:249) ~[elasticsearch-7.15.2.jar:7.15.2]
at org.elasticsearch.common.util.concurrent.BaseFuture.get(BaseFuture.java:76) ~[elasticsearch-7.15.2.jar:7.15.2]
at org.elasticsearch.client.RestHighLevelClient.performClientRequest(RestHighLevelClient.java:2075) ~[elasticsearch-rest-high-level-client-7.15.2.jar:7.15.2]
... 42 common frames omitted
Caused by: java.net.ConnectException: Timeout connecting to [/127.0.0.1:9200]
at org.apache.http.nio.pool.RouteSpecificPool.timeout(RouteSpecificPool.java:169) ~[httpcore-nio-4.4.15.jar:4.4.15]
at org.apache.http.nio.pool.AbstractNIOConnPool.requestTimeout(AbstractNIOConnPool.java:632) ~[httpcore-nio-4.4.15.jar:4.4.15]
at org.apache.http.nio.pool.AbstractNIOConnPool$InternalSessionRequestCallback.timeout(AbstractNIOConnPool.java:898) ~[httpcore-nio-4.4.15.jar:4.4.15]
at org.apache.http.impl.nio.reactor.SessionRequestImpl.timeout(SessionRequestImpl.java:198) ~[httpcore-nio-4.4.15.jar:4.4.15]
at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processTimeouts(DefaultConnectingIOReactor.java:213) ~[httpcore-nio-4.4.15.jar:4.4.15]
at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processEvents(DefaultConnectingIOReactor.java:158) ~[httpcore-nio-4.4.15.jar:4.4.15]
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor.execute(AbstractMultiworkerIOReactor.java:351) ~[httpcore-nio-4.4.15.jar:4.4.15]
at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.execute(PoolingNHttpClientConnectionManager.java:221) ~[httpasyncclient-4.1.5.jar:4.1.5]
at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase$1.run(CloseableHttpAsyncClientBase.java:64) ~[httpasyncclient-4.1.5.jar:4.1.5]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_131]
复制
遇事不决问百度,结果没有想要的结果,大部分的答案都是,报这个错是因为ES服务没有启动,但是我想要的效果是不要让这个错影响我项目的启动,因为并不是每个用网盘的人,都需要这块的功能,最后通过一个注解解决了问题,这个注解便是 @Lazy,原因是:
Spring在启动的时候便会给接口对象注入实例,注入实例必然要创建这个接口的实例,如果创建这个实例的过程出现错误,那么启动就会失败,ES在创建实例的时候,去探测了服务,结果抛出 Timeout connecting 异常,因此创建实例失败,造成启动失败,解决办法就是延迟这个对象的创建过程,而 @Lazy 便可以达到这种效果。
@Lazy
public interface IElasticSearchService extends ElasticsearchRepository<FileSearch,Long> {
}
复制
@Autowired
@Lazy
private IElasticSearchService elasticSearchService;
复制
当然,@Lazy还有其他作用