news 2026/1/14 6:12:41

Spring Boot 4.0 新特性整合 MyBatis-Plus 完整教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot 4.0 新特性整合 MyBatis-Plus 完整教程

Spring Boot 4.0 整合 MyBatis-Plus 完整教程

注:Spring Boot 4.0 ,本教程基于 Spring Boot 4.0 的预览版和新特性预期进行构建。实际发布时可能会有调整。

一、Spring Boot 4.0 新特性概述

1.1 主要新特性

  • Java 21+ 支持:基于虚拟线程的响应式编程增强
  • GraalVM 原生镜像优化:更完善的 AOT 编译支持
  • 响应式编程增强:更好的响应式 MyBatis 支持
  • 模块化改进:更好的 Java Module 支持
  • AI/机器学习集成:内置 AI 功能支持

1.2 构建工具要求

  • JDK 21+
  • Maven 3.9+ 或 Gradle 8.5+
  • GraalVM 23.0+(可选,用于原生编译)

二、项目初始化

2.1 使用 Spring Initializr

# 使用官方 Initializrcurlhttps://start.spring.io/starter.zip\-dtype=maven-project\-dlanguage=java\-dbootVersion=4.0.0-M1\-dbaseDir=spring-boot4-mybatisplus\-dgroupId=com.example\-dartifactId=demo\-dname=demo\-ddescription=Demo+project+for+Spring+Boot+4.0+with+MyBatis-Plus\-dpackageName=com.example.demo\-dpackaging=jar\-djavaVersion=21\-ddependencies=web,data-jpa\-o demo.zip

2.2 手动创建 pom.xml

<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>4.0.0-M1</version><relativePath/></parent><groupId>com.example</groupId><artifactId>springboot4-mybatisplus</artifactId><version>1.0.0</version><name>springboot4-mybatisplus</name><description>Spring Boot 4.0 with MyBatis-Plus</description><properties><java.version>21</java.version><mybatis-plus.version>3.5.5</mybatis-plus.version><graalvm.version>23.0.0</graalvm.version></properties><dependencies><!-- Spring Boot 4.0 核心依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 响应式 Web 支持(新特性) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><!-- MyBatis-Plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis-plus.version}</version></dependency><!-- 数据库驱动 --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><!-- 响应式 MySQL 驱动(新特性) --><dependency><groupId>io.asyncer</groupId><artifactId>r2dbc-mysql</artifactId><scope>runtime</scope></dependency><!-- 响应式 R2DBC --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-r2dbc</artifactId></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- GraalVM 原生镜像支持(新特性) --><dependency><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- 响应式测试支持 --><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><!-- Spring Boot Maven 插件,支持 AOT --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><image><builder>paketobuildpacks/builder-jammy-tiny:latest</builder><env><BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE></env></image></configuration></plugin><!-- GraalVM Native Image 插件 --><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><version>${graalvm.version}</version><extensions>true</extensions><executions><execution><id>build-native</id><goals><goal>compile-no-fork</goal></goals><phase>package</phase></execution></executions></plugin></plugins></build><!-- Spring Milestone 仓库 --><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository></repositories></project>

三、配置 MyBatis-Plus

3.1 应用配置(application.yml)

# Spring Boot 4.0 新配置格式spring:application:name:springboot4-mybatisplus# 数据源配置(虚拟线程优化)datasource:driver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://localhost:3306/mybatis_plus_demo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=trueusername:rootpassword:123456hikari:# 虚拟线程池配置(Spring Boot 4.0 新特性)thread-factory:org.springframework.boot.jdbc.VirtualThreadExecutor# 响应式数据源(新特性)r2dbc:url:r2dbc:mysql://localhost:3306/mybatis_plus_demousername:rootpassword:123456# AOT 编译配置aot:enabled:truegenerate-code:true# GraalVM 原生镜像配置native:mode:nativedebug:true# MyBatis-Plus 配置mybatis-plus:configuration:# 自动映射行为auto-mapping-behavior:full# 驼峰命名转换map-underscore-to-camel-case:true# 日志实现log-impl:org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:# 逻辑删除字段名logic-delete-field:deleted# 逻辑删除值logic-delete-value:1# 逻辑未删除值logic-not-delete-value:0# 主键类型id-type:auto# 分页插件配置pagehelper:helper-dialect:mysqlreasonable:truesupport-methods-arguments:true# 日志配置logging:level:com.example.demo.mapper:debugorg.springframework.r2dbc:debugpattern:console:"%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"# 虚拟线程配置(Spring Boot 4.0 新特性)server:tomcat:threads:# 使用虚拟线程use-virtual-threads:true# 响应式服务器配置netty:connection-timeout:2m

3.2 MyBatis-Plus 配置类

packagecom.example.demo.config;importcom.baomidou.mybatisplus.annotation.DbType;importcom.baomidou.mybatisplus.core.handlers.MetaObjectHandler;importcom.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;importcom.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;importcom.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;importcom.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;importorg.apache.ibatis.reflection.MetaObject;importorg.mybatis.spring.annotation.MapperScan;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.transaction.annotation.EnableTransactionManagement;importjava.time.LocalDateTime;/** * MyBatis-Plus 配置类 * 使用 Spring Boot 4.0 新特性:虚拟线程兼容性配置 */@Configuration@EnableTransactionManagement@MapperScan("com.example.demo.mapper")publicclassMyBatisPlusConfig{/** * MyBatis-Plus 拦截器配置 * 支持分页、乐观锁、防全表更新与删除 */@BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptor=newMybatisPlusInterceptor();// 分页插件interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));// 乐观锁插件interceptor.addInnerInterceptor(newOptimisticLockerInnerInterceptor());// 防止全表更新与删除interceptor.addInnerInterceptor(newBlockAttackInnerInterceptor());returninterceptor;}/** * 元数据处理器 - 自动填充字段 */@BeanpublicMetaObjectHandlermetaObjectHandler(){returnnewMetaObjectHandler(){@OverridepublicvoidinsertFill(MetaObjectmetaObject){// 使用虚拟线程安全的日期时间this.strictInsertFill(metaObject,"createTime",LocalDateTime.class,LocalDateTime.now());this.strictInsertFill(metaObject,"updateTime",LocalDateTime.class,LocalDateTime.now());this.strictInsertFill(metaObject,"version",Integer.class,1);}@OverridepublicvoidupdateFill(MetaObjectmetaObject){this.strictUpdateFill(metaObject,"updateTime",LocalDateTime.class,LocalDateTime.now());}};}}

四、实体类与 Mapper

4.1 基础实体类

packagecom.example.demo.entity;importcom.baomidou.mybatisplus.annotation.*;importlombok.Data;importlombok.experimental.Accessors;importjava.io.Serializable;importjava.time.LocalDateTime;/** * 基础实体类 * 使用 Java 21 Record 模式(预览特性) */@Data@Accessors(chain=true)publicclassBaseEntityimplementsSerializable{/** * 主键ID - 使用虚拟线程安全的ID生成策略 */@TableId(type=IdType.ASSIGN_ID)privateLongid;/** * 创建时间 */@TableField(fill=FieldFill.INSERT)privateLocalDateTimecreateTime;/** * 更新时间 */@TableField(fill=FieldFill.INSERT_UPDATE)privateLocalDateTimeupdateTime;/** * 创建人 */@TableField(fill=FieldFill.INSERT)privateStringcreateBy;/** * 更新人 */@TableField(fill=FieldFill.INSERT_UPDATE)privateStringupdateBy;/** * 乐观锁版本号 */@Version@TableField(fill=FieldFill.INSERT)privateIntegerversion;/** * 逻辑删除标志 */@TableLogic@TableField(fill=FieldFill.INSERT)privateIntegerdeleted;}

4.2 用户实体类

packagecom.example.demo.entity;importcom.baomidou.mybatisplus.annotation.TableField;importcom.baomidou.mybatisplus.annotation.TableName;importlombok.Data;importlombok.EqualsAndHashCode;importlombok.experimental.Accessors;/** * 用户实体类 * 使用 Spring Boot 4.0 新特性:虚拟线程安全的序列化 */@Data@EqualsAndHashCode(callSuper=true)@Accessors(chain=true)@TableName("sys_user")publicclassUserextendsBaseEntity{/** * 用户名 */privateStringusername;/** * 密码 */privateStringpassword;/** * 邮箱 */privateStringemail;/** * 手机号 */privateStringphone;/** * 状态:0-禁用,1-启用 */privateIntegerstatus;/** * 虚拟线程安全的额外字段 * 使用 transient 避免序列化问题 */@TableField(exist=false)privatetransientStringvirtualThreadInfo;}

4.3 Mapper 接口

packagecom.example.demo.mapper;importcom.baomidou.mybatisplus.core.mapper.BaseMapper;importcom.example.demo.entity.User;importorg.apache.ibatis.annotations.Mapper;importorg.apache.ibatis.annotations.Select;importorg.springframework.data.repository.query.Param;importorg.springframework.r2dbc.core.DatabaseClient;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;/** * 用户 Mapper * 支持响应式查询(Spring Boot 4.0 新特性) */@MapperpublicinterfaceUserMapperextendsBaseMapper<User>{/** * 传统阻塞式查询 */@Select("SELECT * FROM sys_user WHERE username = #{username}")UserselectByUsername(@Param("username")Stringusername);/** * 响应式查询 - 返回单个结果 * 使用虚拟线程安全的方式 */@Select("SELECT * FROM sys_user WHERE id = #{id}")defaultMono<User>selectReactiveById(Longid,DatabaseClientdatabaseClient){returndatabaseClient.sql("SELECT * FROM sys_user WHERE id = :id").bind("id",id).map((row,metadata)->{Useruser=newUser();user.setId(row.get("id",Long.class));user.setUsername(row.get("username",String.class));user.setEmail(row.get("email",String.class));user.setStatus(row.get("status",Integer.class));returnuser;}).one();}/** * 响应式查询 - 返回多个结果 */@Select("SELECT * FROM sys_user WHERE status = #{status}")defaultFlux<User>selectReactiveByStatus(Integerstatus,DatabaseClientdatabaseClient){returndatabaseClient.sql("SELECT * FROM sys_user WHERE status = :status").bind("status",status).map((row,metadata)->{Useruser=newUser();user.setId(row.get("id",Long.class));user.setUsername(row.get("username",String.class));user.setEmail(row.get("email",String.class));user.setStatus(row.get("status",Integer.class));returnuser;}).all();}}

五、Service 层实现

5.1 接口定义

packagecom.example.demo.service;importcom.baomidou.mybatisplus.extension.service.IService;importcom.example.demo.entity.User;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;importjava.util.concurrent.CompletableFuture;/** * 用户服务接口 * 支持响应式和虚拟线程 */publicinterfaceUserServiceextendsIService<User>{/** * 虚拟线程方式查询用户 * Spring Boot 4.0 新特性 */CompletableFuture<User>findUserByUsernameVirtualThread(Stringusername);/** * 响应式查询用户 */Mono<User>findUserByIdReactive(Longid);/** * 响应式查询用户列表 */Flux<User>findUsersByStatusReactive(Integerstatus);/** * 使用结构化并发(Java 21 新特性) */UserfindUserWithStructuredConcurrency(Longid);}

5.2 服务实现

packagecom.example.demo.service.impl;importcom.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;importcom.baomidou.mybatisplus.extension.service.impl.ServiceImpl;importcom.example.demo.entity.User;importcom.example.demo.mapper.UserMapper;importcom.example.demo.service.UserService;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.r2dbc.core.DatabaseClient;importorg.springframework.stereotype.Service;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.StructuredTaskScope;importjava.util.concurrent.TimeUnit;/** * 用户服务实现 * 使用 Spring Boot 4.0 新特性:虚拟线程和响应式编程 */@Slf4j@Service@RequiredArgsConstructorpublicclassUserServiceImplextendsServiceImpl<UserMapper,User>implementsUserService{privatefinalUserMapperuserMapper;privatefinalDatabaseClientdatabaseClient;@OverridepublicCompletableFuture<User>findUserByUsernameVirtualThread(Stringusername){returnCompletableFuture.supplyAsync(()->{// 在虚拟线程中执行try{// 模拟耗时操作Thread.sleep(100);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}returnuserMapper.selectOne(newLambdaQueryWrapper<User>().eq(User::getUsername,username));},Thread.ofVirtual().factory());}@OverridepublicMono<User>findUserByIdReactive(Longid){returnuserMapper.selectReactiveById(id,databaseClient).doOnNext(user->log.info("Found user reactively: {}",user.getUsername()));}@OverridepublicFlux<User>findUsersByStatusReactive(Integerstatus){returnuserMapper.selectReactiveByStatus(status,databaseClient).doOnNext(user->log.info("Streaming user: {}",user.getUsername()));}@OverridepublicUserfindUserWithStructuredConcurrency(Longid){// Java 21 结构化并发try(varscope=newStructuredTaskScope.ShutdownOnFailure()){varuserFuture=scope.fork(()->userMapper.selectById(id));varuserDetailsFuture=scope.fork(()->// 模拟获取用户详情"User Details for ID: "+id);scope.join();scope.throwIfFailed();Useruser=userFuture.get();if(user!=null){user.setVirtualThreadInfo(userDetailsFuture.get());}returnuser;}catch(InterruptedExceptione){Thread.currentThread().interrupt();thrownewRuntimeException("Task interrupted",e);}catch(Exceptione){thrownewRuntimeException("Failed to fetch user",e);}}/** * 批量保存用户 - 使用虚拟线程优化 */publicvoidsaveUsersWithVirtualThreads(List<User>users){try(varscope=newStructuredTaskScope.ShutdownOnFailure()){List<StructuredTaskScope.Subtask<User>>tasks=users.stream().map(user->scope.fork(()->{// 每个用户保存操作在独立的虚拟线程中执行save(user);returnuser;})).toList();scope.join();scope.throwIfFailed();// 处理结果tasks.forEach(task->log.info("Saved user: {}",task.get().getUsername()));}catch(InterruptedExceptione){Thread.currentThread().interrupt();thrownewRuntimeException("Save interrupted",e);}catch(Exceptione){thrownewRuntimeException("Failed to save users",e);}}}

六、Controller 层

6.1 传统 REST Controller

packagecom.example.demo.controller;importcom.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;importcom.baomidou.mybatisplus.core.metadata.IPage;importcom.baomidou.mybatisplus.extension.plugins.pagination.Page;importcom.example.demo.entity.User;importcom.example.demo.service.UserService;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.http.ResponseEntity;importorg.springframework.web.bind.annotation.*;importjava.util.List;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;/** * 用户控制器 * 支持虚拟线程和传统阻塞模式 */@Slf4j@RestController@RequestMapping("/api/v1/users")@RequiredArgsConstructorpublicclassUserController{privatefinalUserServiceuserService;/** * 创建用户 */@PostMappingpublicResponseEntity<User>create(@RequestBodyUseruser){booleansaved=userService.save(user);returnsaved?ResponseEntity.ok(user):ResponseEntity.badRequest().build();}/** * 分页查询用户 * 使用虚拟线程优化 */@GetMapping("/page")publicResponseEntity<IPage<User>>page(@RequestParam(defaultValue="1")Integercurrent,@RequestParam(defaultValue="10")Integersize){Page<User>page=newPage<>(current,size);IPage<User>result=userService.page(page);returnResponseEntity.ok(result);}/** * 使用虚拟线程查询用户 * Spring Boot 4.0 新特性 */@GetMapping("/virtual/{username}")publicResponseEntity<User>findByUsernameVirtual(@PathVariableStringusername)throwsExecutionException,InterruptedException{CompletableFuture<User>future=userService.findUserByUsernameVirtualThread(username);returnResponseEntity.ok(future.get());}/** * 使用结构化并发查询用户 * Java 21 新特性 */@GetMapping("/structured/{id}")publicResponseEntity<User>findWithStructuredConcurrency(@PathVariableLongid){Useruser=userService.findUserWithStructuredConcurrency(id);returnResponseEntity.ok(user);}/** * 批量创建用户 - 使用虚拟线程 */@PostMapping("/batch/virtual")publicResponseEntity<Void>createBatchVirtual(@RequestBodyList<User>users){// 在新线程中执行批量操作Thread.ofVirtual().start(()->{userService.saveUsersWithVirtualThreads(users);});returnResponseEntity.accepted().build();}}

6.2 响应式 Controller

packagecom.example.demo.controller;importcom.example.demo.entity.User;importcom.example.demo.service.UserService;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.http.MediaType;importorg.springframework.web.bind.annotation.*;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;importjava.time.Duration;/** * 响应式用户控制器 * Spring Boot 4.0 响应式增强 */@Slf4j@RestController@RequestMapping("/api/v2/users")@RequiredArgsConstructorpublicclassUserReactiveController{privatefinalUserServiceuserService;/** * 响应式查询单个用户 */@GetMapping("/reactive/{id}")publicMono<ResponseEntity<User>>findByIdReactive(@PathVariableLongid){returnuserService.findUserByIdReactive(id).map(ResponseEntity::ok).defaultIfEmpty(ResponseEntity.notFound().build());}/** * 响应式查询用户列表 */@GetMapping(value="/reactive/stream",produces=MediaType.TEXT_EVENT_STREAM_VALUE)publicFlux<User>streamByStatus(@RequestParamIntegerstatus){returnuserService.findUsersByStatusReactive(status).delayElements(Duration.ofMillis(100))// 模拟流式处理.doOnNext(user->log.info("Streaming user: {}",user.getUsername()));}/** * SSE 流式传输 */@GetMapping(value="/sse",produces=MediaType.TEXT_EVENT_STREAM_VALUE)publicFlux<String>userEvents(){returnFlux.interval(Duration.ofSeconds(1)).map(sequence->String.format("User Event %d at %s",sequence,java.time.LocalTime.now()));}}

七、响应式 Repository

packagecom.example.demo.repository;importcom.example.demo.entity.User;importorg.springframework.data.r2dbc.repository.R2dbcRepository;importorg.springframework.data.r2dbc.repository.Query;importorg.springframework.stereotype.Repository;importreactor.core.publisher.Flux;importreactor.core.publisher.Mono;/** * 响应式用户仓库 * Spring Boot 4.0 响应式数据访问 */@RepositorypublicinterfaceUserReactiveRepositoryextendsR2dbcRepository<User,Long>{/** * 根据用户名查询 */@Query("SELECT * FROM sys_user WHERE username = :username")Mono<User>findByUsername(Stringusername);/** * 根据状态查询 */@Query("SELECT * FROM sys_user WHERE status = :status")Flux<User>findByStatus(Integerstatus);/** * 分页查询 */@Query("SELECT * FROM sys_user ORDER BY create_time DESC LIMIT :limit OFFSET :offset")Flux<User>findAllWithPagination(intlimit,intoffset);}

八、全局异常处理

packagecom.example.demo.handler;importcom.baomidou.mybatisplus.core.exceptions.MybatisPlusException;importlombok.extern.slf4j.Slf4j;importorg.springframework.http.HttpStatus;importorg.springframework.http.ResponseEntity;importorg.springframework.web.bind.annotation.ExceptionHandler;importorg.springframework.web.bind.annotation.RestControllerAdvice;importorg.springframework.web.bind.support.WebExchangeBindException;importreactor.core.publisher.Mono;importjava.util.HashMap;importjava.util.Map;/** * 全局异常处理器 * 支持响应式异常处理 */@Slf4j@RestControllerAdvicepublicclassGlobalExceptionHandler{/** * 处理 MyBatis-Plus 异常 */@ExceptionHandler(MybatisPlusException.class)publicResponseEntity<Map<String,Object>>handleMybatisPlusException(MybatisPlusExceptione){log.error("MyBatis-Plus Exception: {}",e.getMessage(),e);Map<String,Object>response=newHashMap<>();response.put("code",HttpStatus.INTERNAL_SERVER_ERROR.value());response.put("message","数据库操作失败");response.put("detail",e.getMessage());response.put("timestamp",System.currentTimeMillis());returnResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);}/** * 处理虚拟线程中断异常 */@ExceptionHandler(InterruptedException.class)publicResponseEntity<Map<String,Object>>handleInterruptedException(InterruptedExceptione){log.warn("Virtual thread interrupted: {}",e.getMessage());Map<String,Object>response=newHashMap<>();response.put("code",HttpStatus.SERVICE_UNAVAILABLE.value());response.put("message","请求被中断");response.put("timestamp",System.currentTimeMillis());Thread.currentThread().interrupt();// 恢复中断状态returnResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(response);}/** * 响应式异常处理 */@ExceptionHandler(WebExchangeBindException.class)publicMono<ResponseEntity<Map<String,Object>>>handleBindException(WebExchangeBindExceptione){returnMono.fromCallable(()->{Map<String,Object>response=newHashMap<>();response.put("code",HttpStatus.BAD_REQUEST.value());response.put("message","参数验证失败");Map<String,String>errors=newHashMap<>();e.getFieldErrors().forEach(error->errors.put(error.getField(),error.getDefaultMessage()));response.put("errors",errors);response.put("timestamp",System.currentTimeMillis());returnResponseEntity.badRequest().body(response);});}}

九、虚拟线程配置

packagecom.example.demo.config;importorg.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;importorg.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.task.AsyncTaskExecutor;importorg.springframework.core.task.support.TaskExecutorAdapter;importorg.springframework.scheduling.annotation.EnableAsync;importjava.util.concurrent.Executors;/** * 虚拟线程配置 * Spring Boot 4.0 核心新特性 */@Configuration@EnableAsyncpublicclassVirtualThreadConfig{/** * 配置 Tomcat 使用虚拟线程 */@BeanpublicTomcatProtocolHandlerCustomizer<?>protocolHandlerVirtualThreadExecutorCustomizer(){returnprotocolHandler->protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());}/** * 配置 Spring 异步任务执行器使用虚拟线程 */@Bean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)publicAsyncTaskExecutorasyncTaskExecutor(){returnnewTaskExecutorAdapter(Executors.newVirtualThreadPerTaskExecutor());}/** * 配置虚拟线程池用于数据库操作 */@Beanpublicjava.util.concurrent.ExecutorServicedatabaseExecutor(){returnExecutors.newThreadPerTaskExecutor(Thread.ofVirtual().name("db-virtual-thread-",0).factory());}}

十、AOT 和原生镜像支持

10.1 创建 AOT 处理类

packagecom.example.demo.aot;importorg.springframework.aot.hint.RuntimeHints;importorg.springframework.aot.hint.RuntimeHintsRegistrar;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.ImportRuntimeHints;/** * AOT 运行时提示注册 * Spring Boot 4.0 原生镜像支持 */@Configuration@ImportRuntimeHints(AotRuntimeHints.MybatisPlusRuntimeHints.class)publicclassAotRuntimeHints{staticclassMybatisPlusRuntimeHintsimplementsRuntimeHintsRegistrar{@OverridepublicvoidregisterHints(RuntimeHintshints,ClassLoaderclassLoader){// 注册反射hints.reflection().registerType(com.baomidou.mybatisplus.core.mapper.BaseMapper.class,hint->hint.withMembers(org.springframework.aot.hint.MemberCategory.INVOKE_PUBLIC_METHODS));// 注册资源hints.resources().registerPattern("mapper/*.xml");hints.resources().registerPattern("mybatis-config.xml");// 注册序列化hints.serialization().registerType(com.example.demo.entity.User.class);// 注册代理hints.proxies().registerJdkProxy(org.apache.ibatis.binding.MapperProxy.class);}}}

10.2 native-image.properties

Args = --enable-url-protocols=http,https \ -H:+ReportExceptionStackTraces \ -H:+ReportUnsupportedElementsAtRuntime \ --initialize-at-build-time=com.mysql.cj \ --initialize-at-run-time=io.netty.handler.codec.http.HttpObjectEncoder \ -H:IncludeResourceBundles=com.mysql.cj.LocalizedErrorMessages

十一、测试类

packagecom.example.demo;importcom.example.demo.entity.User;importcom.example.demo.service.UserService;importlombok.extern.slf4j.Slf4j;importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importreactor.core.publisher.Mono;importreactor.test.StepVerifier;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.TimeoutException;importstaticorg.assertj.core.api.Assertions.assertThat;/** * 集成测试 * 测试虚拟线程和响应式功能 */@Slf4j@SpringBootTestclassSpringBoot4MybatisPlusApplicationTests{@AutowiredprivateUserServiceuserService;/** * 测试虚拟线程查询 */@TestvoidtestVirtualThreadQuery()throwsExecutionException,InterruptedException,TimeoutException{// 准备测试数据Useruser=newUser().setUsername("test_virtual").setEmail("test@example.com").setStatus(1);userService.save(user);// 使用虚拟线程查询CompletableFuture<User>future=userService.findUserByUsernameVirtualThread("test_virtual");Userresult=future.get(5,TimeUnit.SECONDS);assertThat(result).isNotNull();assertThat(result.getUsername()).isEqualTo("test_virtual");log.info("Virtual thread test passed, user ID: {}",result.getId());}/** * 测试响应式查询 */@TestvoidtestReactiveQuery(){// 准备测试数据Useruser=newUser().setUsername("test_reactive").setEmail("reactive@example.com").setStatus(1);userService.save(user);// 使用响应式查询Mono<User>userMono=userService.findUserByIdReactive(user.getId());StepVerifier.create(userMono).assertNext(foundUser->{assertThat(foundUser).isNotNull();assertThat(foundUser.getUsername()).isEqualTo("test_reactive");}).verifyComplete();log.info("Reactive query test passed");}/** * 测试结构化并发 */@TestvoidtestStructuredConcurrency(){// 准备测试数据Useruser=newUser().setUsername("test_structured").setEmail("structured@example.com").setStatus(1);userService.save(user);// 使用结构化并发查询Userresult=userService.findUserWithStructuredConcurrency(user.getId());assertThat(result).isNotNull();assertThat(result.getUsername()).isEqualTo("test_structured");assertThat(result.getVirtualThreadInfo()).contains("User Details");log.info("Structured concurrency test passed");}/** * 测试批量虚拟线程操作 */@TestvoidtestBatchVirtualThreads(){// 准备测试数据List<User>users=newArrayList<>();for(inti=0;i<10;i++){users.add(newUser().setUsername("batch_user_"+i).setEmail("batch"+i+"@example.com").setStatus(1));}// 使用虚拟线程批量保存userService.saveUsersWithVirtualThreads(users);// 验证保存结果List<User>savedUsers=userService.list(newLambdaQueryWrapper<User>().likeRight(User::getUsername,"batch_user_"));assertThat(savedUsers).hasSize(10);log.info("Batch virtual threads test passed, saved {} users",savedUsers.size());}}

十二、性能监控

packagecom.example.demo.monitor;importio.micrometer.core.instrument.MeterRegistry;importlombok.RequiredArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.springframework.stereotype.Component;importorg.springframework.util.StopWatch;importjava.util.concurrent.atomic.AtomicInteger;/** * 虚拟线程性能监控 * Spring Boot 4.0 监控增强 */@Slf4j@Aspect@Component@RequiredArgsConstructorpublicclassVirtualThreadMonitor{privatefinalMeterRegistrymeterRegistry;privatefinalAtomicIntegeractiveVirtualThreads=newAtomicInteger(0);/** * 监控虚拟线程使用 */@Around("@annotation(com.example.demo.annotation.VirtualThreadMonitor)")publicObjectmonitorVirtualThread(ProceedingJoinPointjoinPoint)throwsThrowable{StopWatchstopWatch=newStopWatch();intcurrentThreads=activeVirtualThreads.incrementAndGet();try{stopWatch.start();Objectresult=joinPoint.proceed();stopWatch.stop();// 记录指标meterRegistry.timer("virtual.thread.execution.time").record(stopWatch.getTotalTimeNanos(),java.util.concurrent.TimeUnit.NANOSECONDS);meterRegistry.gauge("virtual.thread.active.count",activeVirtualThreads);log.info("Virtual thread executed: method={}, time={}ms, activeThreads={}",joinPoint.getSignature().getName(),stopWatch.getTotalTimeMillis(),currentThreads);returnresult;}finally{activeVirtualThreads.decrementAndGet();}}}

十三、启动类

packagecom.example.demo;importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.context.event.ApplicationReadyEvent;importorg.springframework.context.event.EventListener;@Slf4j@SpringBootApplicationpublicclassSpringBoot4MybatisPlusApplication{publicstaticvoidmain(String[]args){// 启用 AOT 优化System.setProperty("spring.aot.enabled","true");SpringApplication.run(SpringBoot4MybatisPlusApplication.class,args);}@EventListener(ApplicationReadyEvent.class)publicvoidonApplicationReady(){log.info("=========================================");log.info("Spring Boot 4.0 with MyBatis-Plus Started");log.info("Java Version: {}",System.getProperty("java.version"));log.info("Virtual Threads Available: {}",Thread.ofVirtual()!=null?"Yes":"No");log.info("Available Processors: {}",Runtime.getRuntime().availableProcessors());log.info("=========================================");}}

十四、部署和优化

14.1 Dockerfile(支持原生镜像)

# 构建阶段 FROM ghcr.io/graalvm/native-image:java21 AS builder WORKDIR /app COPY target/*.jar app.jar RUN native-image -jar app.jar --no-fallback -H:Name=app-native # 运行阶段 FROM alpine:latest RUN apk add --no-cache libstdc++ WORKDIR /app COPY --from=builder /app/app-native /app/app EXPOSE 8080 ENTRYPOINT ["/app/app"]

14.2 Docker Compose

version:'3.8'services:app:build:.ports:-"8080:8080"environment:-SPRING_PROFILES_ACTIVE=prod-JAVA_OPTS=-XX:+UseZGC-Xmx512mdepends_on:-mysqldeploy:resources:limits:memory:512Mmysql:image:mysql:8.0environment:MYSQL_ROOT_PASSWORD:123456MYSQL_DATABASE:mybatis_plus_demoports:-"3306:3306"volumes:-mysql_data:/var/lib/mysqlcommand:---default-authentication-plugin=mysql_native_password---character-set-server=utf8mb4---collation-server=utf8mb4_unicode_civolumes:mysql_data:

十五、总结

15.1 关键特性使用

  1. 虚拟线程:通过Thread.ofVirtual()和虚拟线程池优化并发性能
  2. 响应式编程:结合 MyBatis-Plus 和 R2DBC 实现非阻塞数据访问
  3. 结构化并发:使用 Java 21 的结构化并发 API
  4. AOT 编译:支持 GraalVM 原生镜像,提升启动速度
  5. 模块化:更好的 Java Module 支持

15.2 性能优化建议

  1. 对于 I/O 密集型操作,使用虚拟线程
  2. 对于高并发场景,使用响应式编程
  3. 使用 GraalVM 原生镜像减少内存占用和启动时间
  4. 合理配置连接池和线程池参数

15.3 整合事项

  1. Spring Boot 4.0 目前是预览版,API 可能会有变化
  2. 虚拟线程对阻塞操作敏感,避免在虚拟线程中执行长时间 CPU 操作
  3. 原生镜像编译需要处理反射和动态代理的注册
  4. 生产环境建议充分测试响应式和虚拟线程的稳定性

我的这个教程展示了如何利用 Spring Boot 4.0 的新特性(虚拟线程、响应式编程、AOT 编译等)来整合 MyBatis-Plus,构建高性能的现代 Java 应用程序。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!