最近介于Log4j的漏洞,Spring boot也将版本升级到了2.6.2,并更新依赖版本Upgrade to Log4j2 2.17.0
, 本打算激进些直接把Spring Cloud升级到2021.0.x,Boot升级到2.6.2,奈何Cloud Alibaba还没兼容这块,发现直接强制升级存在循环依赖的问题,目前已知Nacos没问题,Sentinel和Dubbo存在循环依赖,所以还是乖乖升级到兼容版本,并且单独升级依赖的Log4j和Logback吧。
更新过程中碰到一系列的问题,及解决方案供大家少走些弯路。
Spring Cloud Alibaba版本信息详细可查看:版本说明
例如报错:Param ‘serviceName’ is illegal, serviceName is blank
因为我的Nacos配置放到了bootstrap.yml,发现读取不到Nacos配置中心的配置,后续发现控制台也不显示Nacos相关信息。
从Spring Boot 2.4版本开始,配置文件加载方式进行了重构。
package org.springframework.cloud.util;
public abstract class PropertyUtils {
public static boolean bootstrapEnabled(Environment environment) {
return (Boolean)environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class, false) || MARKER_CLASS_EXISTS;
}
详细可查看官方说明:config-first-bootstrap
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bootstrapartifactId>
dependency>
Spring Cloud 2020.0.0版本之前会自动引入Netflix Ribbon依赖,Netflix Ribbon功能跟loadbalancer一样,因Netflix公司停止维护Ribbon后, 在Spring Cloud 2020.0.0版本之后Spring使用loadbalancer替代了Ribbon, 但是loadbalancer依赖需要手动引入。
# 引入loadbalancer
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-loadbalancerartifactId>
dependency>
解决方案是引入caffeine,或者关闭cache
<dependency>
<groupId>com.github.ben-manes.caffeinegroupId>
<artifactId>caffeineartifactId>
<version>3.1.0version>
dependency>
先说有效方案,经过测试发现依赖有问题,引入依赖即可解决:
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>5.2.21.RELEASEversion>
dependency>
之前找到的网友配置,无效,以下可忽略,仅做记录:
spring:
cloud:
loadbalancer:
ribbon:
enabled: false
cache:
enabled: true
caffeine:
spec: initialCapacity=500,expireAfterWrite=5s
但是发现配置有可能还会存在提示,没有生效!网络上有说Naocs discovery依赖有冲突导致没生效,exclusion
spring-cloud-starter-netflix-ribbon
,但是实际查看了下此版本并没有依赖这个包。
项目配置:
driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://127.0.0.1:3306/tuine?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
项目中使用到了log4jdbc-log4j2-jdbc4.1
,升级后出现此错误提示。 因为mysql最新驱动名称为com.mysql.cj.jdbc.Driver,log4jdbc只支持com.mysql.jdbc.Driver,所以需要将自动加载数据库驱动关闭。
resources文件下新增log4jdbc.log4j2.properties
文件
log4jdbc.auto.load.popular.drivers=false
log4jdbc.drivers=com.mysql.cj.jdbc.Driver
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
测试启动过程中,发现Idea直接退出,没有任何提示输出。这是Idea的设置问题
在启动的Edit Configuration
里设置指定服务的Active profiles
,例如:local
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2
在NonBlocking线程中再调用阻塞方法。例如Netty的线程就不允许阻塞,因为是在Netty的pipeline里,而Netty的线程本身是不允许阻塞的。
修改为异步调用:eg.
CompletableFuture<JSONObject> f = CompletableFuture.supplyAsync(() -> {
ResponseEntity<String> resEntity = restTemplate.exchange(authServiceUrl + "/permission", HttpMethod.GET, httpEntity, String.class);
return JSONUtil.parseObj(resEntity.getBody());
});
JSONObject jsonObject = f.get();
org.springframework.beans.BeanInstantiationException: Failed to instantiate [feign.jaxrs2.JAXRS2Contract]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: javax/ws/rs/Path
网络上有说 javax/ws/rs/Path 是属于jsr311-api.jar 包下的,引入相关jsr311-api
包即可,实际测试引入netflix-ribbon即可。
引入ribbon
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
2.2.10.RELEASE
提示allowedOrigins不允许设置*。2.4版本后需要修改此选项
When allowCredentials is true, allowedOrigins cannot contain the special value "*“since that cannot be set on the “Access-Control-Allow-Origin” response header. To allow credentials to a set of origins, list them explicitly or consider using"allowedOriginPatterns” instead.
allowedOrigins更改为allowedOriginPatterns即可
allowedOrigins: "*"
# 替换为
allowedOriginPatterns: "*"
新版本中Spring Boot不自动包含此包,自行引入即可。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
<version>2.3.3.RELEASEversion>
dependency>
此处还是因为2020版本不再使用netflix,没有了ribbon导致的问题,依旧是引入:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-loadbalancerartifactId>
dependency>
如出现以下报错:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.hibernate.validator.internal.xml.config.ValidationBootstrapParameters.(ValidationBootstrapParameters.java:65)
The following method did not exist:
javax.validation.BootstrapConfiguration.getClockProviderClassName()Ljava/lang/String;
解决方案为将 JavaEE7升级到JavaEE8
<dependency>
<groupId>javaxgroupId>
<artifactId>javaee-apiartifactId>
<version>8.0.1version>
dependency>