您现在的位置是:首页 >其他 >Spring Boot3.0升级相关问题网站首页其他
Spring Boot3.0升级相关问题
Spring Boot 3.0升级相关问题
我是现升级到Spring Boot 2.7.6 后升级到 3.0
原始版本:
springboot 1.5.1.RELEASE + jdk1.8
目标版本:
springboot 3.0 + jdk17
注意事项:
1. org.apache.maven.plugins:maven
前期项目中如果刷新maven时会出现 org.apache.maven.plugins:maven-xxxxxxx 的情况,在maven配置项中加入以下代码
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
<!-- maven官方镜像 -->
<mirror>
<id>mirrorId</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name </name>
<url>http://repo1.maven.org/maven2/</url>
</mirror>
<!-- 阿里云镜像 -->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://central.maven.org/maven2</url>
<mirrorOf>central</mirrorOf>
</mirror>
<!-- 阿里云镜像 -->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
<mirrorOf>central</mirrorOf>
</mirror>
<!-- junit镜像地址 -->
<mirror>
<id>junit</id>
<name>junit Address/</name>
<url>http://jcenter.bintray.com/</url>
<mirrorOf>central</mirrorOf>
</mirror>
2.{org.springframework.boot:spring-boot-starter-cloud-connectors:null:jar}: The version cannot be empty.**
如果在升级 Spring Boot 版本时遇到了 org.springframework.boot:spring-boot-starter-cloud-connectors:null:jar 版本为空的错误,可能是由于版本引发的问题。此错误通常发生在将 Spring Boot 1.x 项目升级到 2.x 时。 你可以检查项目中是否有指定 spring-cloud-connectors
的版本,如果没有,可以手动添加依赖,并指定版本。示例 Maven 依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cloud-connectors</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>
Spring Boot版本差异产生的问题
1.mapstruct** 版本(找不到Mapper注解、Mapping注解)
如果项目中引用 mapstruct 的话,需要要将mapstruct 版本升级至1.4.1以上版本,目前我选择的版本是 1.4.2.Final
同时,我们升级了jdk的版本,那么在原本的依赖中也要进行更改
<!-- 原始版本 -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<!-- 新版本 去掉jdk8 即可-->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
2.Pageable 接口
Pageable接口是spring Data库中定义的一个接口,该接口是所有分页相关信息的一个抽象,通过该接口,我们可以得到和分页相关所有信息(例如pageNumber、pageSize等)。
在这个接口中 getOffset() 方法主要时用于返回要根据基础页和页大小取的偏移量,现在由于版本提升,其返回值由 int 类型转换为 long ,如果代码中引用到这个方法时,需要注意类型转换。
3.org.springframework.data.repository.query.QueryByExampleExecutor中的方法 findOne应用到给定类型;
这个是由于版本更换导致的问题,然后我之前在 1.5的版本上调用的是org.springframework.data.repository 包下的,升级后需换为 findById().**orElse(null),因为find.one 是 repository.query包下的,**会出现报错。
同理:delete() 方法也存在问题,如果删除一个deleteById(),如果删除多个,传入集合的方式,采取deleteAll();
4.com.mongodb.client.MongoCollection无法转换为com.mongodb.DBCollection**
DBCollection
是 mongo-java-driver
包中的一个类,用于操作 MongoDB 数据库中集合(Collection)。自从 MongoDB Java Driver 3.x 发布以来, DBCollection
已经被弃用了,取而代之的是 MongoCollection
类。 你可以使用 MongoCollection
类来替换 DBCollection
,它提供了更好的代码兼容性和更多的功能。下面是一个样例代码,演示如何使用 MongoCollection
:
// 1. 创建 MongoDB 客户端实例
MongoClient mongoClient = new MongoClient("localhost", 27017);
// 2. 获取数据库
MongoDatabase database = mongoClient.getDatabase("myDb");
// 3. 获取集合
MongoCollection<Document> collection = database.getCollection("myCollection");
// 4. 插入文档
Document doc = new Document("name", "John Doe")
.append("age", 30)
.append("email", "johndoe@example.com");
collection.insertOne(doc);
// 5. 查询文档
Document query = new Document("name", "John Doe");
FindIterable<Document> results = collection.find(query);
for (Document result : results) {
System.out.println(result.toJson());
}
// 6. 更新文档
Document updateQuery = new Document("name", "John Doe");
Document updateDoc = new Document("$set", new Document("age", 35));
UpdateResult updateResult = collection.updateOne(updateQuery, updateDoc);
System.out.println("Update Count: " + updateResult.getModifiedCount());
// 7. 删除文档
Document deleteQuery = new Document("name", "John Doe");
DeleteResult deleteResult = collection.deleteOne(deleteQuery);
System.out.println("Delete Count: " + deleteResult.getDeletedCount());
// 8. 关闭客户端
mongoClient.close();
注意, MongoCollection
使用了泛型,你需要指定集合中文档的类型。在上面的样例代码中,我们使用了 Document 类型。如果你想使用自定义的 Java 类型,需要将它映射为 MongoDB 的 BSON 格式。你可以使用 MongoDB 提供的 Codec
接口实现对 Java 类型和 BSON 格式之间的转换。
5.Relaxe*dPropertyResolver 找不到
Spring Boot 2.0不是直接使用现有的PropertySource接口进行绑定,而是引入了一个新的ConfigurationPropertySource接口。 我们引入了一个新的接口,为我们提供了一个合理的地方来实施放松绑定规则,这些规则以前是活页夹的一部分接口的主要API非常简单:
// 原来的code:
RelaxedPropertyResolver propertyResolver =
new RelaxedPropertyResolver(environment, "spring.datasource");
propertyResolver.getSubProperties("....")
// 现在的code:
Iterable sources = ConfigurationPropertySources.get(environment);
Binder binder = new Binder(sources);
BindResult bindResult = binder.bind("spring.datasource", Properties.class);
Properties properties= bindResult.get();
6.reids找不到(JedisPool找不到了)
版本升级后,jedis需要重新进行引入
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.10.2</version>
</dependency>
备注:版本需要根据自己需要去调整
7.EmbeddedServletContainerCustomizer、UndertowEmbeddedServletContainerFactory接口找不到了
从 Spring Boot 2.0 版本开始, EmbeddedServletContainerCustomizer
接口已过时并且不建议使用。在 Spring Boot 2.0 及以后的版本中,建议使用 WebServerFactoryCustomizer
接口来定制嵌入式 Web 服务器。 如果在升级 Spring Boot 版本后出现 EmbeddedServletContainerCustomizer
接口找不到的问题,可以尝试将其替换为 WebServerFactoryCustomizer
接口,同时 UndertowEmbeddedServletContainerFactory
接口可以替换为UndertowServletWebServerFactory
,并相应地修改方法签名。以下是一些可能的解决方案:
public class WebConfigurer implements ServletContextInitializer, WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory container) {
MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
// IE issue, see https://github.com/jhipster/generator-jhipster/pull/711
mappings.add("html", "text/html;charset=utf-8");
// CloudFoundry issue, see https://github.com/cloudfoundry/gorouter/issues/64
mappings.add("json", "text/html;charset=utf-8");
container.setMimeMappings(mappings);
/*
* Enable HTTP/2 for Undertow - https://twitter.com/ankinson/status/829256167700492288
* HTTP/2 requires HTTPS, so HTTP requests will fallback to HTTP/1.1.
* See the JHipsterProperties class and your application-*.yml configuration files
* for more information.
*/
if (jHipsterProperties.getHttp().getVersion().equals(JHipsterProperties.Http.Version.V_2_0)) {
if (container instanceof UndertowServletWebServerFactory) {
((UndertowServletWebServerFactory) container)
.addBuilderCustomizers((builder) -> {
builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true);
});
}
}
}
}
8.ExportMetricReader、ExportMetricWriter注解找不到了
在Spring Boot 2.7中,确实已经移除了 @ExportMetrics
和 @ExportMetricWriter
注解。如果要导出自定义的 MeterRegistry
实例以供给其他 Bean 使用,可以考虑使用 MeterRegistryPostProcessor
接口或 MeterRegistryCustomizer
接口。 MeterRegistryPostProcessor
接口用于在容器加载 MeterRegistry
实例时进行后处理,可以通过它来将 MeterRegistry
实例导出到其他组件中。以下是一个示例:
@Configuration
public class MyMetricsConfig {
@Bean
public PrometheusMeterRegistry myMeterRegistry() {
return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
}
@Bean
public MeterRegistryPostProcessor myMeterRegistryPostProcessor(PrometheusMeterRegistry myMeterRegistry) {
return (registry) -> {
registry.add(myMeterRegistry);
};
}
}
@Service
@MicrometerMetrics
public class MyService {
private final MeterRegistry meterRegistry;
@Autowired
public MyService(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
// ...
}
在上面的示例中, MyMetricsConfig
配置类中定义了一个名为 myMeterRegistry
的 PrometheusMeterRegistry
实例,并通过 myMeterRegistryPostProcessor
方法创建了一个 MeterRegistryPostProcessor
实例,将 myMeterRegistry
导出到其他组件中。 MeterRegistryCustomizer
接口用于在容器加载 MeterRegistry
实例时进行后处理,可以通过它来定制 MeterRegistry
实例的一些属性。以下是一个示例:
@Configuration
public class MyMetricsConfig {
@Bean
public PrometheusMeterRegistry myMeterRegistry() {
return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
}
@Bean
public MeterRegistryCustomizer<PrometheusMeterRegistry> myMeterRegistryCustomizer() {
return (registry) -> {
registry.config().commonTags("application", "myapp");
};
}
}
@Service
@MicrometerMetrics
public class MyService {
private final MeterRegistry meterRegistry;
@Autowired
public MyService(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
// ...
}
在上面的示例中, MyMetricsConfig
配置类中定义了一个名为 myMeterRegistry
的 PrometheusMeterRegistry
实例,并通过 myMeterRegistryCustomizer
方法创建了一个 MeterRegistryCustomizer
实例,增加了一个名为 application
值为 myapp
的通用标签。
9.JmxReporter类找不到
缺少一个JmxReporter这个类,同时是在com.codahale.metrics这个包中
直接导入一个依赖就可以解决
<dependency>
<groupId>com.codahale.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>3.0.2</version>
</dependency>
10.getErrorAttributes()方法被改写
在Spring Boot 2.7中, getErrorAttributes()
方法已经被移除,推荐使用 getErrorAttributes(WebRequest, ErrorAttributeOptions)
方法。 getErrorAttributes(WebRequest, ErrorAttributeOptions)
方法的返回值类型为 Map
。 ErrorAttributeOptions
是一个枚举类型,表示错误属性的选项,可以使用 ErrorAttributeOptions.defaults()
方法获取默认的选项值。可以在选项中设置是否包含堆栈跟踪信息、异常类型等信息。 下面是一个使用 getErrorAttributes(WebRequest, ErrorAttributeOptions)
方法的示例代码:
@ControllerAdvice
public class MyErrorController implements ErrorController {
private static final String PATH = "/error";
@Override
public String getErrorPath() {
return PATH;
}
@RequestMapping(PATH)
public ResponseEntity<Map<String, Object>> error(WebRequest webRequest) {
ErrorAttributeOptions options = ErrorAttributeOptions.defaults()
.including(ErrorAttributeOptions.Include.STACK_TRACE);
Map<String, Object> errorAttributes = new DefaultErrorAttributes()
.getErrorAttributes(webRequest, options);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorAttributes);
}
}
在上面的代码中,我们重写了 ErrorController
接口的 getErrorPath()
方法,指定了错误端点的路径为 /error
。在 error()
方法中,我们创建了一个 ErrorAttributeOptions
对象,并指定了包含堆栈跟踪信息。然后使用 DefaultErrorAttributes
的实例调用 getErrorAttributes(WebRequest, ErrorAttributeOptions)
方法获取错误属性,最后使用 ResponseEntity
返回错误属性 Map
。 需要注意的是, DefaultErrorAttributes
是一个默认的错误属性解析器,它将错误信息解析成一个 Map
对象。如果需要自定义错误属性,可以创建一个实现了 ErrorAttributes
接口的类,并在控制器中使用。
11.MultipartConfigFactory类中上传数据大小改写
//原始的方法中我们可以直接定义
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize("100MB");
factory.setMaxRequestSize("100MB");
//现在要进行改写
factory.setMaxFileSize( DataSize.parse("100", DataUnit.MEGABYTES));
factory.setMaxRequestSize( DataSize.parse("100", DataUnit.MEGABYTES));
-
PageRequest
类的构造方法从公共访问权限变为了受保护的访问权限PageRequest
类的构造方法从公共访问权限变为了受保护的访问权限,不再可以直接外部调用。如果你之前的代码中使用到了PageRequest
的构造方法,需要进行如下修改:可以使用其静态方法 PageRequest.of() 和 new PageReques()效果一致
- 首先,创建一个继承自
PageRequest
的子类,如下所示:
- 首先,创建一个继承自
public class CustomPageRequest extends PageRequest {
public CustomPageRequest(int page, int size) {
super(page, size);
}
public CustomPageRequest(int page, int size, Sort.Direction direction, String... properties) {
super(page, size, direction, properties);
}
}
在这个子类中,我们继承了 PageRequest
,并且提供了两个构造方法,可以通过这两个构造方法来创建新的分页请求对象。 2. 然后,在之前使用 PageRequest
的地方,替换为使用我们创建的 CustomPageRequest
,如下所示:
Pageable pageable = new CustomPageRequest(pageNumber, pageSize);
或者:
Pageable pageable = new CustomPageRequest(pageNumber, pageSize, Sort.Direction.ASC, "id");
这样就可以在你的代码中继续使用分页请求对象了。需要注意的是,如果你的代码中创建分页请求对象的地方比较多,那么需要替换所有的地方。
同理 sort 类也发生了改变 ,举例:
//之前的写法
Sort sort = new Sort( direction, properties)
//现在可通过静态调用
by(Sdirection, properties);