在上一篇 SpringBoot 入门教程中,我们掌握了项目搭建、HelloWorld 开发和项目发布的基础操作,本次将聚焦 SpringBoot 实际开发中的四大核心工程能力:异常统一处理、整合 Junit 单元测试、多环境配置切换、Logback 日志配置,这些都是企业开发中必备的技能,也是 SpringBoot 项目规范化开发的关键,本文将通过实战代码 + 详细解析的方式,让你快速上手并落地使用!
一、SpringBoot 异常统一处理
在项目开发中,异常处理如果散落在各个业务代码中,会导致代码冗余、维护困难。SpringBoot 提供了多种优雅的异常处理方式,可适配传统页面跳转 和前后端分离 AJAX 请求两种场景。
1.1 基础方式:自定义统一错误页面
SpringBoot 内置了异常处理机制,程序抛出未捕获异常时,会自动向/error发送请求,由BasicErrorController处理并跳转到默认错误页。我们只需在指定目录创建固定名称的错误页,即可替换默认页面。
实现步骤
- 在
src/main/resources/templates目录下创建error.html(名称不可修改); - 页面中可通过 Thymeleaf 表达式
${error}获取异常信息;
核心代码
Controller(模拟抛出异常)
java
@Controller
public class DemoController {
// 抛出空指针异常
@RequestMapping("/show")
public String showInfo(){
String str = null;
str.length();
return "index";
}
// 抛出算术异常
@RequestMapping("/show2")
public String showInfo2(){
int a = 10/0;
return "index";
}
}
错误页面 error.html
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>系统错误</title>
</head>
<body>
系统出错啦,请联系管理员处理!<br>
异常信息:<span th:text="${error}"></span>
</body>
</html>
1.2 传统项目:按异常类型自定义错误页(实现 HandlerExceptionResolver)
针对传统非 AJAX 项目,可实现HandlerExceptionResolver接口创建全局异常处理器,根据不同的异常类型,跳转到对应的专属错误页,实现异常的精细化处理。
实现步骤
- 创建异常处理器类,添加
@Component注解交给 Spring 容器管理,实现HandlerExceptionResolver接口; - 重写
resolveException方法,判断异常类型,指定跳转的视图名,并传递异常信息; - 为不同异常类型创建对应的错误页(如
error1.html、error2.html)。
核心代码
全局异常处理器
java
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) {
ModelAndView mv = new ModelAndView();
// 按异常类型跳转不同页面
if(ex instanceof ArithmeticException){
mv.setViewName("error1"); // 算术异常跳error1.html
}else if(ex instanceof NullPointerException){
mv.setViewName("error2"); // 空指针异常跳error2.html
}
mv.addObject("error", ex.toString()); // 传递异常信息
return mv;
}
}
1.3 前后端分离:AJAX 请求全局异常处理(@ControllerAdvice+@ExceptionHandler)
前后端分离项目中,前端通过 AJAX 请求接口,异常处理不能跳转页面,需返回JSON 格式的异常信息 。使用@ControllerAdvice+@ExceptionHandler组合是最优方案,可全局捕获异常并返回自定义 JSON 数据。
核心注解说明
@ControllerAdvice:全局控制器增强,作用于所有 Controller;@ExceptionHandler:指定捕获的异常类型,可写多个方法捕获不同异常;@ResponseBody:将返回的 Map 自动转为 JSON 格式。
核心代码
java
@ControllerAdvice
public class AjaxGlobalExceptionHandler {
// 捕获所有Exception类型异常
@ResponseBody
@ExceptionHandler(value = Exception.class)
public Map<String, Object> errorHandler(Exception exception) {
Map<String, Object> map = new HashMap<>();
map.put("status", 500); // 自定义状态码
map.put("msg", exception.getMessage()); // 异常详情
map.put("success", false); // 前端判断标识
return map;
}
}
前端处理 :可根据返回的status或success字段,统一弹出错误提示,无需每个接口单独处理异常。
二、SpringBoot 整合 Junit4 单元测试
单元测试是验证业务代码正确性的关键,SpringBoot 提供了专门的 Junit 启动器,可快速整合 Spring 环境,无需手动加载容器,直接注入 Bean 进行测试,极大简化测试代码。
2.1 第一步:引入 Junit 启动器依赖
SpringBoot 的spring-boot-starter-test已整合 Junit4、SpringTest 等相关依赖,直接引入即可:
XML
<!-- SpringBoot整合Junit启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <!-- 仅测试环境生效 -->
</dependency>
2.2 第二步:编写待测试的业务代码
以用户新增业务为例,编写简单的 DAO 和 Service 层代码(模拟数据库操作):
DAO 层
java
@Repository
public class UserDaoImpl {
// 模拟用户入库
public void saveUser(){
System.out.println("=====用户数据插入成功=====");
}
}
Service 层
java
@Service
public class UserServiceImpl {
@Autowired
private UserDaoImpl userDaoImpl;
// 业务方法:调用DAO层
public void addUser(){
this.userDaoImpl.saveUser();
}
}
SpringBoot 启动类
java
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
2.3 第三步:编写单元测试代码
测试类需放在src/test/java目录下,通过两个核心注解整合 Spring 环境,直接注入 Service/DAO 层 Bean 进行测试。
核心注解说明
@RunWith(SpringJUnit4ClassRunner.class):让 Junit 运行在 Spring 环境中,加载 Spring 容器;@SpringBootTest(classes={App.class}):指定 SpringBoot 的启动类,确定容器加载的配置范围。
测试代码
java
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes={App.class})
public class UserServiceTest {
// 自动注入待测试的Service Bean
@Autowired
private UserServiceImpl userServiceImpl;
// 测试方法,添加@Test注解
@Test
public void testAddUser(){
userServiceImpl.addUser(); // 调用业务方法
}
}
运行结果 :控制台打印=====用户数据插入成功=====,说明测试通过,业务代码正常执行。
三、SpringBoot 多环境配置(开发 / 测试 / 生产)
实际开发中,开发、测试、生产环境 的配置(如端口、数据库地址、redis 地址)往往不同,如果手动修改配置文件,容易出错且效率低。SpringBoot 提供了优雅的多环境配置方案,支持多文件配置 和单文件多文档块配置,一键切换环境。
3.1 核心规则
配置文件命名遵循固定语法:application-{profile}.yml/properties,其中profile为环境标识(如 dev:开发、test:测试、prod:生产)。
3.2 方式 1:多文件配置(推荐,结构清晰)
为每个环境创建独立的配置文件,主配置文件中指定激活的环境。
步骤 1:创建多环境配置文件
application-dev.yml:开发环境,端口 8090
java
server:
port: 8090
application-test.yml:测试环境,端口 8091
java
server:
port: 8091
application-prod.yml:生产环境,端口 8092
java
server:
port: 8092
步骤 2:主配置文件激活指定环境
在application.yml(主配置文件,全局生效)中通过spring.profiles.active指定要激活的环境,只需修改该值即可一键切换:
java
# 激活开发环境,可改为test/prod切换
spring:
profiles:
active: dev
3.3 方式 2:单文件多文档块配置(适合简单配置)
如果配置内容较少,可将所有环境的配置写在同一个 application.yml 中,通过---分割不同环境的配置块,spring.profiles指定环境名称。
java
# 全局配置:激活生产环境
spring:
profiles:
active: prod
---
# 开发环境:profiles指定环境名dev
spring:
profiles: dev
server:
port: 8090
---
# 测试环境:profiles指定环境名test
spring:
profiles: test
server:
port: 8091
---
# 生产环境:profiles指定环境名prod
spring:
profiles: prod
server:
port: 8092
注意 :---是 YAML 格式的文档分隔符,必须单独一行,不可省略。
四、SpringBoot 日志配置(Logback)
日志是项目排错、运行监控的重要工具,SpringBoot默认集成 Logback (Log4j 的改良版本,性能更高、配置更灵活),无需额外引入依赖,只需编写logback.xml配置文件,即可实现控制台输出 、文件滚动存储 、日志级别控制等功能。
4.1 Logback 核心优势
相比传统的 Log4j,Logback 有以下显著优势:
- 性能提升:内核重写,运行速度更快,内存占用更小;
- 动态配置:配置文件修改后,自动重新加载,无需重启项目;
- 多环境适配:通过
<if>/<else>标签,一个配置文件适配所有环境; - 异步压缩:日志文件自动按时间 / 大小分割,压缩过程异步执行,不影响主程序;
- 原生支持:SpringBoot 默认内置,无需额外引入依赖。
4.2 经典 Logback.xml 配置(可直接复用)
配置文件需放在src/main/resources目录下,SpringBoot 会自动加载。以下是企业开发中最常用的配置,包含控制台输出 和按天滚动的文件输出,并限制日志文件大小和保存天数。
XML
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!-- 定义日志存储根路径,不存在则自动创建 -->
<property name="LOG_HOME" value="./logs" />
<!-- 1. 控制台输出配置:Stdout -->
<appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<!-- 日志输出格式:时间 线程 级别 类名 日志信息 换行 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 控制台编码 -->
</layout>
</appender>
<!-- 2. 文件滚动输出配置:RollingFile -->
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志滚动策略:按天分割,保留30天 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/server.%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>30</MaxHistory> <!-- 日志保存30天 -->
</rollingPolicy>
<!-- 单文件大小限制:超过10MB自动分割 -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
<!-- 日志输出格式 -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</layout>
</appender>
<!-- 全局日志级别:DEBUG(开发)/INFO(测试/生产),级别从低到高:TRACE<DEBUG<INFO<WARN<ERROR -->
<root level="INFO">
<!-- 关联控制台和文件输出appender -->
<appender-ref ref="Stdout" />
<appender-ref ref="RollingFile" />
</root>
</configuration>
4.3 日志级别说明
日志级别用于控制日志的输出粒度,开发环境一般用DEBUG(打印详细调试信息),测试 / 生产环境用INFO(仅打印关键运行信息),级别越高,输出的日志越少:
- TRACE:最细粒度,几乎不用;
- DEBUG:调试信息,开发排错用;
- INFO:常规运行信息,如项目启动、接口调用;
- WARN:警告信息,如配置缺失、资源不足;
- ERROR:错误信息,如程序异常、接口调用失败。
4.4 代码中使用日志
在类中注入Logger对象,即可打印不同级别的日志,替代传统的System.out.println:
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl {
// 创建Logger对象,指定当前类
private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
public void addUser(){
logger.debug("=====开始执行用户新增业务=====");
logger.info("=====用户新增业务执行成功=====");
// logger.error("=====用户新增业务执行失败=====");
}
}
五、总结
本次教程全面讲解了 SpringBoot 开发中的四大核心工程能力,核心要点总结如下:
- 异常处理 :页面项目用
HandlerExceptionResolver,前后端分离用@ControllerAdvice+@ExceptionHandler,拒绝零散 try-catch; - 单元测试 :引入
spring-boot-starter-test,通过@RunWith+@SpringBootTest整合 Spring 环境,直接注入 Bean 测试; - 多环境配置 :遵循
application-{profile}.yml命名规则,主配置文件通过spring.profiles.active一键切换环境; - Logback 日志 :SpringBoot 默认集成,编写
logback.xml实现控制台 + 文件输出,按时间 / 大小分割,合理设置日志级别。
这些技能是 SpringBoot 项目从「入门」到「实战」的关键,也是企业开发中规范化、工程化的基础。掌握后可大幅提升开发效率,让项目更易维护、更稳定。