🎉🎉《Spring Boot实战案例合集》目前已更新145个案例,我们将持续不断的更新。文末有电子书目录。
💪💪永久更新承诺
我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务。
💌💌如何获取
订阅我们的合集《点我订阅》,并通过私信联系我们,我们将第一时间将电子书发送给您。
环境:SpringBoot3.4.2
1. 简介
别再在低效开发中苦苦挣扎啦!本文为你精心搜罗 20 个超实用的 Spring Boot 技巧,个个都是提升效率的“秘密武器”。从巧妙管理复杂配置、灵活自定义启动 Banner,到精准排除不必要的自动配置、高效执行启动任务,再到利用 DevTools 加速开发、借助 Actuator 监控应用状态……这些技巧涵盖 Spring Boot 开发的方方面面。掌握它们,能让你在开发过程中少走弯路,轻松应对各种难题,开发效率瞬间翻倍,快速打造出高质量的应用程序,赶紧学起来吧!
2.1 @ConfigurationProperties简化配置
在项目开发中各种自定义的配置少不了,大量配置项可能分散各处难以管理。这时@ConfigurationProperties 注解就派上用场了,它能将多个相关配置映射到一个类中,使代码更简洁。
(prefix = "pack.app")public class RemoteProperties {private String host;private int port ;private String schema ;// getters, setters}
配置文件
pack:app:schema: ftphost: localhostport: 22
在上面的示例中,我们可以使用@Component也可以使用@EnableConfigurationProperties,不过该注解更适合用在自定义开发的starter。
2.2 自定义Banner
Spring Boot项目启动时有默认的Banner,要想使用自己的Banner我们可以在src/main/resources目录下新建banner.txt文件写入你想显示的内容,比如公司logo、项目名称或版本号。如下:
我们可以通过如下地址生成自己喜欢的:
https://www.bootschool.net/ascii
我们在banner.tx文件中还可以使用如下的变量:
|
|
|
|---|---|
${application.version} |
MANANIFEST.MF 文件中声明。例如,若声明为 Implementation-Version: 1.0,则显示为 1.0。
|
${application.formatted-version} |
MANANIFEST.MF 文件中声明,并且经过格式化以便显示(用括号括起来,并在前面加上 v)。例如,显示为 (v1.0)。
|
${spring-boot.version} |
3.5.3。
|
${spring-boot.formatted-version} |
v)。例如,显示为 (v3.5.3)。
|
${Ansi.NAME}
${AnsiColor.NAME}、${AnsiBackground.NAME}、${AnsiStyle.NAME})
|
NAME 是 ANSI 转义码的名称。详情参见 AnsiPropertySource。
|
2.3 配置无用的自动配置
Spring Boot的自动配置功能非常强大,但有时我们不需要加载所有自动配置的组件。这时可以使用 @SpringBootApplication 的exclude属性来排除不需要的模块,从而加快启动速度并减少内存占用。如下示例:
(exclude = {DataSourceAutoConfiguration.class})public class App {public static void main(String[] args) {SpringApplication.run(App .class, args);}}
也可以在配置文件中排除:
spring:autoconfigure:exclude:- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
2.4 使用Runner执行启动任务
Spring Boot 应用启动后,有时我们需要执行一些初始化任务,比如初始化数据库或加载默认数据。我们可以使用 CommandLineRunner 或 ApplicationRunner 接口,如下示例:
public class LoadCacheRunner implements CommandLineRunner {private final StringRedisTemplate restTemplate ;public void run(String... args) throws Exception {// ...}}
注意:这两种Runner除了接收应用程序的参数形式不一样外,功能都是一样的,他们的执行顺序会根据你配置的 @Order 或者实现的 Ordered 接口决定。
2.5 使用SpringApplicationBuilder自定义启动
SpringApplicationBuilder 为我们提供了更灵活的方式来配置应用启动。通过流畅的API(链式方法调用),可以方便地在代码层面设置各种应用属性。如下示例:
public class App {public static void main(String[] args) {new SpringApplicationBuilder(App.class).profiles("dev").properties("server.port=6666").run(args);}}
这种方式对于需要根据不同条件灵活配置启动参数的场景特别有用,相比在配置文件中设置,通过代码控制更加直观方便。
2.6 @Profile切换环境配置
在开发、测试和生产等不同环境中,应用的配置往往不同,比如数据库连接、日志级别等。Spring Boot的 @Profile 注解可以方便地切换不同环境配置。如下示例:
public class DataSourceConfig {public DataSource devDataSource() {HikariDataSource dataSource = ... ;// ...return dataSource;}public DataSource prodDataSource() {HikariDataSource dataSource = ... ;// ...return dataSource;}}
配置文件
spring:profiles:active:- dev
2.7 使用@Conditional控制Bean加载
有时我们希望根据配置文件中的某个属性值来决定是否加载某个Bean。@ConditionalOnProperty 注解可以满足这一需求,实现按需加载Bean。如下示例:
public class PackCacheConfig {(name = "pack.cache.enabled", havingValue = "true")public PackCache cache() {return new PackCache() ;}}
配置文件
pack:cache:enabled: true
当 pack.cache.enabled 配置为true时才会注册PackCache bean。
关于条件注解,更多内容请查看下面内容:
2.8 使用DevTools加速开发
Spring Boot DevTools是专门为开发提供便利的工具,包含代码热重载、禁用缓存等功能,可以极大提高开发和调试速度。
首先,引入依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency>
当你修改并保存代码时,应用会自动重启,无需手动重启,节省大量开发时间。(其实我一定都不希望这功能)
2.9 使用Actuator监控应用
Spring Boot Actuator是一个强大的监控管理工具。通过它,我们可以轻松了解应用的运行状态、性能指标等信息。
首先,引入依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
如果仅仅是引入上面的依赖,那么仅仅会暴露如下接口:
我们可以通过如下配置,进行更多的设置:
2.10 使用@Validated进行数据验证
Spring Boot集成了Java Validation API,配合 @Validated 注解,我们可以轻松实现数据验证。通过在方法参数前添加 @Validated,并结合各种验证注解(如@NotNull、@Size、@Pattern等),Spring Boot会自动验证输入数据。如果验证失败会抛出异常,我们可以统一处理。如下示例:
public class UserDTO {private String username;private String email;}
Controller接口定义
("/create")public ResponseEntity<?> createUser( UserDTO userDTO) {// 注册业务逻辑return ResponseEntity.ok("success") ;}
注意,不要忘记引入下面依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
2.11 使用@ControllerAdvice统一异常处理
在Spring Boot应用中,统一的异常处理对于提高应用的健壮性和用户体验非常重要。我们可以创建一个全局异常处理器来捕获并处理应用中抛出的各种异常。如下示例:
public class GlobalExceptionHandler {private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);public ResponseEntity<ErrorResponse> handleException(Exception ex, HandlerMethod handlerMethod,HttpServletRequest request) {// 统一异常处理}}
注意,在Controller中,我们可以直接在当前的Controller类中定义@ExceptionHandler 方法。
2.12 使用AOP实现日志和性能监控
AOP(面向切面编程)是Spring Boot中非常强大的特性。我们可以利用它来处理日志记录、性能监控等横切关注点,避免在业务代码中重复这些逻辑。如下示例:
public class LoggingAndPerformanceAspect {private static final Logger logger = LoggerFactory.getLogger(LoggingAndPerformanceAspect.class);public Object logAndMeasurePerformance(ProceedingJoinPoint joinPoint, RequestMapping requestMapping) throws Throwable {String methodName = joinPoint.getSignature().getName();String className = joinPoint.getTarget().getClass().getSimpleName();// 如果是 debug 级别才记录参数详情boolean isDebugEnabled = logger.isDebugEnabled();if (isDebugEnabled) {logger.debug("准备执行 {}.{}()", className, methodName);Object[] args = joinPoint.getArgs();for (int i = 0; i < args.length; i++) {logger.debug("参数 {}: {}", i, args[i]);}}StopWatch stopWatch = new StopWatch();try {stopWatch.start();Object result = joinPoint.proceed();stopWatch.stop();logger.info("{}.{}() 执行完成,耗时 {} 毫秒", className, methodName, stopWatch.getTotalTimeMillis());if (isDebugEnabled) {logger.debug("返回结果: {}", result);}return result;} catch (Throwable throwable) {stopWatch.stop();logger.error("{}.{}() 执行出错,耗时 {} 毫秒,错误信息: {}",className, methodName, stopWatch.getTotalTimeMillis(), throwable.getMessage(), throwable);throw throwable;}}}
关于日志记录的更多内容,请查看下面文章:
Spring Boot 记录Controller接口请求日志7种方式,第六种性能极高
高级开发!性能优化,Spring Boot 不使用AOP也能优雅的记录日志
2.13 配置嵌入式Servlet容器
Spring Boot默认使用嵌入式Servlet容器(如Tomcat)来运行应用。我们可以通过配置文件或编程方式自定义其配置,以优化性能或满足特定需求。如下示例:
server:tomcat:max-threads: 200max-connections: 1000
如下编程方式:
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();Connector connector = new Connector(Http11NioProtocol.class.getName());connector.setPort(8080);Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();protocol.setMaxThreads(200);protocol.setMaxConnections(1000);factory.addAdditionalTomcatConnectors(connector);return factory;}
2.14 使用缓存提升性能
在Spring Boot中,合理使用缓存可以显著提升性能,减少数据库查询次数,提高响应速度。Spring Boot提供了强大的缓存支持,通过 @EnableCaching 注解启用缓存,并使用 @Cacheable 等注解标记需要缓存的方法。
开启缓存
@Configuration@EnableCachingpublic class AppConfig {}
使用缓存注解
public class UserService {public User getUserById(Long id) {return this.userRepository.findById(id).orElse(null) ;}}
有关缓存的更多内容,请查看下面内容:
2.15 异步任务处理
在Spring Boot中,有些任务可能比较耗时,如果在主线程中执行会影响应用的响应性。通过 @Async 注解,我们可以将这些任务异步执行,让主线程快速返回,提高用户体验。
开启异步功能
@Configuration@EnableAsyncpublic class AppConfig {}
定义异步任务
public class TaskService {public void processLongTask() {// 耗时的任务}}
2.16 外部化配置文件
在生产环境中,我们经常需要在不重新打包应用的情况下修改配置。Spring Boot支持外部化配置文件,可以方便地在不同环境中调整设置。常见做法是将配置文件放在应用运行目录的config文件夹中,或通过命令行参数指定配置文件路径。
在运行的jar目录下新建config文件夹,在该文件夹下放我们的配置文件application.yml。
注意:不止这一种方式。
使用命令行指定配置文件:
java -jar app.jar --spring.config.location=file:/xxx/config/
关于配置文件的,更多内容请查看下面内容:
2.17 动态切换数据源
当我们的应用需要连接多个数据源,并根据不同业务需求动态切换。Spring Boot提供了灵活的机制来实现这一点。如下示例:
配置多数据源
import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.boot.jdbc.DataSourceBuilder;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.jdbc.core.JdbcTemplate;import javax.sql.DataSource;public class DataSourceConfig {public DataSource firstDataSource() {return DataSourceBuilder.create().build();}public DataSource secondDataSource() {return DataSourceBuilder.create().build();}}
自定义路由数据源
public class DynamicDataSource extends AbstractRoutingDataSource {protected Object determineCurrentLookupKey() {return DataSourceContextHolder.getDataSourceType();}}public class DataSourceContextHolder {private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();public static void setDataSourceType(String type) {CONTEXT_HOLDER.set(type);}public static String getDataSourceType() {return CONTEXT_HOLDER.get();}public static void clearDataSourceType() {CONTEXT_HOLDER.remove();}}
定义数据源Bean
public DataSource dynamicDataSource(DataSource firstDataSource, DataSource secondDataSource) {AbstractRoutingDataSource ds = new DynamicDataSource();Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put("first", firstDataSource);targetDataSources.put("second", secondDataSource);ds.setTargetDataSources(targetDataSources);ds.setDefaultTargetDataSource(firstDataSource); // 默认数据源return ds;}
使用示例
private JdbcTemplate jdbcTemplate;public void queryFromFirst() {DataSourceContextHolder.setDataSourceType(DataSourceNames.FIRST);try {jdbcTemplate.queryForList("SELECT 1");} finally {DataSourceContextHolder.clearDataSourceType();}}
以上是最为简单的实现方式。
2.18 自定义Jackson格式化
Spring Boot默认使用Jackson库处理JSON数据的序列化和反序列化。在实际开发中,我们可能需要根据业务需求自定义Jackson的行为,比如修改日期格式或忽略某些属性。要自定义日期格式,可以创建一个Jackson2ObjectMapperBuilderCustomizer Bean:
public class JacksonConfig {public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {return builder -> {JavaTimeModule module = new JavaTimeModule();module.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).modules(module);};}}
在上面的代码中,我们创建了一个JavaTimeModule并自定义了LocalDateTime类型的序列化格式,然后将其添加到Jackson2ObjectMapperBuilder中。这样,当LocalDateTime数据被序列化为JSON时,会按照指定格式输出。
此外,还可以使用 @JsonIgnore 注解忽略某些属性,使用 @JsonProperty 注解重命名属性,灵活定制JSON数据处理,满足各种复杂业务需求。
2.19 使用@Scheduled进行任务调度
在Spring Boot中,我们经常会遇到定时任务的需求,比如定期清理过期数据或发送提醒邮件。Spring Boot通过@Scheduled注解可以轻松实现任务调度,只需在方法上添加该注解并设置调度规则,Spring Boot就会按照指定的时间间隔或特定时间点执行任务。如下示例:
public class ScheduledTask {(cron = "0 0 1 * * ?")public void cleanExpiredData() {// ...}}
上面的代码中,cron表达式"0 0 1 * * ?"表示每天凌晨1点触发任务。
2.20 使用Testcontainers进行测试
在编写单元测试和集成测试时,模拟真实环境(如数据库、消息队列等)非常有用。Testcontainers是一个开源库,可以让我们在测试中轻松创建和管理容器化的测试环境,如MySQL、Redis、Kafka等。
如下以测试使用MySQL数据库的Spring Boot应用为例:
<dependency><groupId>org.testcontainers</groupId><artifactId>testcontainers</artifactId><scope>test</scope></dependency><dependency><groupId>org.testcontainers</groupId><artifactId>mysql</artifactId><scope>test</scope></dependency>
测试类
public class DatabaseTest {public static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0.26").withDatabaseName("testdb").withUsername("root").withPassword("root");private JdbcTemplate jdbcTemplate;public void testDatabaseInsert() {jdbcTemplate.execute("INSERT INTO users (name, age) VALUES ('John', 30)");int count = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM users", Integer.class);assertEquals(1, count);}}
在上面的测试类中,MySQLContainer会在测试启动时创建一个MySQL容器实例,并自动配置Spring Boot应用使用的数据源连接信息。测试完成后,容器会自动销毁,确保每次测试都有一致且隔离的环境,大大提高了测试的可靠性和可重复性。
2.21 使用@Retry注解实现重试
当我们的业务执行发生错误时,可以使用这个注解在操作失败时自动进行重试。
首先,引入依赖
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId></dependency>
开启重试功能
@Configuration@EnableRetrypublic class AppConfig {}
使用示例
public class RemoteService {(maxAttempts = 3, backoff = (delay = 1000, multiplier = 2))public ApiResponse callRemoteService(String request) {// ...业务方法}// 当重试后最终还是失败,则调用该方法public ApiResponse recoverRemoteServiceCall(Exception e, String request) {return new ApiResponse("调用失败");}}
推荐文章
Jackson 5 大逆天神技,搞定双向关联输出 JSON 问题
Spring Boot 监控 API 请求耗时,这 8 种方案你知道几个?
技术专家:零代码,Spring Boot存储加密解密,支持JDBC、MyBatis及JPA
高级开发!Spring Boot + JsonNode 动态处理请求/响应属性值
神器!基于 Spring Boot 处理 CSV 超强工具,太方便了
Jackson才是王!SpringBoot优雅的控制JSON数据
告别内存溢出!Spring StreamingResponseBody 三大实战案例,性能提升100%
SpringBoot冷门但逆天的5个神级注解,老司机都在偷偷用!


