1. 为什么需要整合Spring Boot 3.4与Swagger和MyBatis-Plus
在微服务架构盛行的当下,Spring Boot 3.4作为Java生态中最主流的开发框架,其与API文档工具Swagger和ORM框架MyBatis-Plus的组合已成为企业级开发的黄金三角。这个技术栈的典型应用场景包括:
- 快速构建RESTful API服务
- 自动化生成交互式API文档
- 实现高效数据库操作
我最近在金融支付系统中采用这个组合时,发现Spring Boot 3.4对Java 17的最低版本要求带来了不少新特性,比如记录类(Record)的支持、更强大的Null检查等。同时MyBatis-Plus 3.5+版本对Lambda表达式的优化,使得代码可读性大幅提升。而Swagger与Spring Boot 3.4的整合过程中,OpenAPI 3.0规范的完整支持让API文档更加规范。
重要提示:Spring Boot 3.x系列要求JDK 17+,这是与2.x系列最大的区别,也是许多开发者升级时遇到的第一个门槛。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与项目初始化
2.1 基础环境配置
首先需要确保开发环境满足以下要求:
- JDK 17或更高版本(推荐Amazon Corretto 17)
- Maven 3.6+或Gradle 7.x
- IDE推荐IntelliJ IDEA 2023+(对Java 17新语法支持最好)
创建项目时,建议使用Spring Initializr(https://start.spring.io/)生成基础骨架,关键依赖选择:
- Spring Web(用于RESTful接口开发)
- Lombok(简化实体类编写)
- MySQL Driver(或其他数据库驱动)
2.2 依赖版本管理
在pom.xml中需要明确定义各组件版本,这是避免兼容性问题的关键:
xml复制<properties>
<java.version>17</java.version>
<spring-boot.version>3.4.0</spring-boot.version>
<mybatis-plus.version>3.5.6</mybatis-plus.version>
<swagger.version>2.2.0</swagger.version>
</properties>
<dependencies>
<!-- Spring Boot基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${swagger.version}</version>
</dependency>
</dependencies>
3. MyBatis-Plus深度整合
3.1 基础配置与实体映射
在application.yml中配置数据源和MyBatis-Plus:
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/your_db?useSSL=false&serverTimezone=UTC
username: root
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启SQL日志
global-config:
db-config:
id-type: auto # 主键策略
logic-delete-field: deleted # 逻辑删除字段
logic-not-delete-value: 0
logic-delete-value: 1
实体类示例使用Java记录类(Record)新特性:
java复制public record User(
@TableId(type = IdType.AUTO)
Long id,
@TableField("user_name")
String username,
@TableField(fill = FieldFill.INSERT)
LocalDateTime createTime,
@TableField(fill = FieldFill.INSERT_UPDATE)
LocalDateTime updateTime
) {}
3.2 高级特性实战
3.2.1 字段加密处理
通过MyBatis-Plus的TypeHandler实现字段级加密:
java复制public class AESEncryptHandler implements TypeHandler<String> {
private static final String KEY = "your-secret-key-123";
@Override
public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) {
try {
String encrypted = AESUtil.encrypt(parameter, KEY);
ps.setString(i, encrypted);
} catch (Exception e) {
throw new RuntimeException("加密失败", e);
}
}
// 其他接口方法实现...
}
在实体字段上应用:
java复制@TableField(typeHandler = AESEncryptHandler.class)
private String mobile;
3.2.2 多租户实现
基于MyBatis-Plus的多租户插件:
java复制@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 多租户插件
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public Expression getTenantId() {
return new LongValue(1L); // 实际应从上下文中获取
}
@Override
public boolean ignoreTable(String tableName) {
return !Arrays.asList("user", "order").contains(tableName);
}
}));
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
4. Swagger集成与安全加固
4.1 基础配置
创建Swagger配置类:
java复制@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.your.package"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo())
.securitySchemes(Collections.singletonList(apiKey()))
.securityContexts(Collections.singletonList(securityContext()));
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API文档")
.description("Spring Boot 3.4 + Swagger集成")
.version("1.0")
.build();
}
private ApiKey apiKey() {
return new ApiKey("JWT", "Authorization", "header");
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.any())
.build();
}
List<SecurityReference> defaultAuth() {
AuthorizationScope scope = new AuthorizationScope("global", "accessEverything");
return Collections.singletonList(new SecurityReference("JWT", new AuthorizationScope[]{scope}));
}
}
4.2 解决Swagger未授权访问漏洞
在生产环境中,必须限制Swagger的访问:
java复制@Profile("!prod")
@Configuration
public class SwaggerConfig {
// 配置同上,但只在非生产环境生效
}
同时添加安全控制:
java复制@Configuration
public class WebSecurityConfig {
@Value("${swagger.enabled:false}")
private boolean swaggerEnabled;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
if (swaggerEnabled) {
http.authorizeRequests()
.antMatchers("/swagger-ui/**").authenticated()
.antMatchers("/v3/api-docs/**").authenticated();
}
return http.build();
}
}
5. 常见问题排查与性能优化
5.1 MyBatis-Plus更新null值问题
默认情况下,MyBatis-Plus的updateById方法会忽略null值字段。如果需要更新为null,有两种解决方案:
- 全局配置(application.yml):
yaml复制mybatis-plus:
global-config:
db-config:
strategy: not_null # 或ignored
- 字段级别注解:
java复制@TableField(updateStrategy = FieldStrategy.IGNORED)
private String remark;
5.2 Swagger文档缺失问题
当出现"No API definition provided"时,检查以下方面:
- 确保Controller类有@RestController或@Controller注解
- 方法上添加@ApiOperation注解
- 检查包扫描路径是否正确
- 确认没有拦截器拦截了/v3/api-docs请求
5.3 性能优化建议
- MyBatis-Plus二级缓存配置:
java复制@Configuration
@MapperScan("com.your.mapper")
@EnableCaching
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean
public CacheManager cacheManager() {
return new RedisCacheManager(...);
}
}
- Swagger分组加载:
java复制@Bean
public Docket adminApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("admin")
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(AdminController.class))
.build();
}
6. 实际项目中的经验分享
在电商系统开发中,我们遇到了几个值得分享的实践:
- 动态表名处理:通过MyBatis-Plus的动态表名插件实现分表查询
java复制public class DynamicTableNameParser implements ITableNameHandler {
@Override
public String dynamicTableName(String sql, String tableName) {
return tableName + "_" + LocalDate.now().getYear();
}
}
- Swagger枚举展示优化:使用@ApiModelProperty的allowableValues属性
java复制public enum OrderStatus {
@ApiModelProperty(value = "待支付", allowableValues = "UNPAID")
UNPAID,
@ApiModelProperty(value = "已支付", allowableValues = "PAID")
PAID
}
- 批量操作性能对比:
- 普通循环插入:1000条约1200ms
- MyBatis-Plus的saveBatch:1000条约800ms
- 手写批量SQL:1000条约200ms
关键建议:对于超大批量操作(万级以上),建议使用MyBatis-Plus的executeBatch模式或直接使用JDBC批量操作
最后,在微服务架构下,可以考虑将Swagger文档集中到API网关统一管理,使用Spring Cloud Gateway的Swagger聚合功能。同时,对于字段加密等敏感操作,建议结合Vault等密钥管理工具,避免硬编码密钥。
