一、前言
在 SpringBoot 开发过程中,异常处理、单元测试、多环境配置和日志管理是保障项目稳定性、可维护性的核心技能。本文将从实战角度出发,详细讲解这四大核心模块的实现方式,帮助开发者快速掌握并应用到实际项目中。
二、SpringBoot 异常处理
SpringBoot 默认提供了异常处理机制,当程序出现异常时,会向/error路径发送请求,由BasicErrorController处理并跳转至默认异常页面。我们可以通过自定义错误页面、全局异常处理器等方式实现更灵活的异常处理。

2.1 整合 AJAX 全局异常处理(重点)
对于 AJAX 请求,通常需要返回 JSON 格式的异常信息,可通过@ControllerAdvice和@ExceptionHandler实现。前后端分离
java
java
package com.hg.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionResolver {
//ajax全局异常处理 前后端分离【重点】 适合次数少的
@ExceptionHandler(Exception.class)
@ResponseBody
public Map ExceptionResolver(){
HashMap<String, Object> map = new HashMap<>();
map.put("status",500);
map.put("msg","操作失败!");
return map;
}
// 自定义Result返回值,适合调用次数多的
// @ExceptionHandler(Exception.class)
// @ResponseBody
// public Result ExceptionResolver(){
// Result result = new Result();
// result.setStatus(500);
// result.setMsg("出错了!");
// return result;
// }
}
//class Result{
// private Integer status;
// private String msg;
//
// public Integer getStatus() {
// return status;
// }
//
// public void setStatus(Integer status) {
// this.status = status;
// }
//
// public String getMsg() {
// return msg;
// }
//
// public void setMsg(String msg) {
// this.msg = msg;
// }
//
// public Result() {
// }
//
// public Result(Integer status, String msg) {
// this.status = status;
// this.msg = msg;
// }
//}
模拟controller层错误:
java
package com.hg.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
public class ExceptionController {
@RequestMapping("/exception")
@ResponseBody
public Map showInfo2(){
HashMap<String, Object> map = new HashMap<>();
map.put("status",200);
map.put("msg","ks开播了!");
int a = 10/0;
return map;
}
}
2.2 整合非 AJAX 全局异常处理器(了解)
通过实现HandlerExceptionResolver接口,可针对不同异常类型跳转不同错误页面。非前后端分离
2.2.1 全局异常处理器实现
/**
* 通过实现HandlerExceptionResolver接口做全局异常处理
*/
@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");
}else if(ex instanceof NullPointerException){
mv.setViewName("error2");
}
mv.addObject("error", ex.toString());
return mv;
}
}
2.2.2 对应错误页面
error1.html(处理算术异常):
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>错误提示页面-ArithmeticException</title>
</head>
<body>
出错了,请与管理员联系。。。
<span th:text="${error}"></span>
</body>
</html>
error2.html(处理空指针异常):
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>错误提示页面-NullPointerException</title>
</head>
<body>
出错了,请与管理员联系。。。
<span th:text="${error}"></span>
</body>
</html>
三、SpringBoot 整合 Junit
SpringBoot 提供了专门的 Junit 启动器,简化了单元测试的配置流程。
3.1 引入 Junit 启动器依赖
xml
<!--junit启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
3.2 编写业务代码
3.2.1 DAO 层
java
@Repository
public class UserDaoImpl {
public void saveUser(){
System.out.println("insert into users.....");
}
}
3.2.2 Service 层
@Service
public class UserServiceImpl {
@Autowired
private UserDaoImpl userDaoImpl;
public void addUser(){
this.userDaoImpl.saveUser();
}
}
3.2.3 启动类
java
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
3.3 编写单元测试
运行
java
import com.hg.junitApp;
import com.hg.service.UserServiceImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
/*
1、main方法启动spring
new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
2、spring整合junit
@RunWith(SpringJUnit4ClassRunner.class)
@Contextconfiguartion("classpath:applicationContext.xml")
3、spring boot 整合junit
①
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes={junitApp.class})
②
@RunWith(SpringRunner.class)
@SpringBootTest(classes={junitApp.class})
③
@RunWith(SpringRunner.class)
@SpringBootTest
④
@SpringBootTest
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes={junitApp.class})
public class UserServiceTest {
@Autowired
private UserServiceImpl userServiceImpl;
@Test
public void testAddUser(){
this.userServiceImpl.addUser();
}
}
四、SpringBoot 多环境配置
在实际开发中,项目需要适配开发、测试、生产等不同环境,SpringBoot 支持通过多配置文件或单 YML 多文档块实现环境切换。
4.1 多配置文件方式
4.1.1 配置文件命名规范
- 开发环境:
application-dev.yml(端口 8090) - 测试环境:
application-test.yml(端口 8091) - 生产环境:
application-prod.yml(端口 8092)
4.1.2 激活指定环境
在application.yml中配置:
#激活指定的配置文件
spring.profiles.active=dev
4.2 单 YML 多文档块方式(了解)
YML 支持多文档块分隔(---),可在单个文件中定义所有环境配置:
yml
spring:
profiles:
active: prod #激活prod环境
---
#开发环境
spring:
profiles: dev #环境名称
server:
port: 8090 #端口号
---
#测试环境
spring:
profiles: test #环境名称
server:
port: 8091 #端口号
---
#生产环境
spring:
profiles: prod #环境名称
server:
port: 8092 #端口号
4.3 多 YML 文档方式(推荐)

application-dev.yml
java
spring:
profiles: dev #环境名称
server:
port: 8090 #端口号
以此类推...
五、SpringBoot 日志(logback)
logback 是 log4j 的改良版本,性能更优、功能更丰富,是 SpringBoot 默认的日志框架。
5.1 logback 核心优势
- 性能提升:内核重写,内存占用更小,执行速度更快;
- 动态配置:支持自动重新加载配置文件;
- 环境适配:通过
<if><else><then>标签适配不同环境,无需多配置文件; - 异步压缩:RollingFileAppender 可异步压缩日志文件,不影响主线程。
5.2 logback.xml 配置示例
xml
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="${catalina.base:-.}/logs/" />
<!-- 控制台输出 -->
<appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender">
<!-- 日志输出编码 -->
<layout class="ch.qos.logback.classic.PatternLayout">
<!--
日志输出格式:
%d表示日期时间,
%thread表示线程名,
%-5level:级别从左显示5个字符宽度
%logger{50} 表示class的全名最长50个字符,否则按照句点分割
%msg:日志消息
%n是换行符
-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
</pattern>
</layout>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/server.%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<!--
日志输出格式:
%d表示日期时间,
%thread表示线程名,
%-5level:级别从左显示5个字符宽度
%logger{50} 表示class的全名最长50个字符,否则按照句点分割
%msg:日志消息
%n是换行符
-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
</pattern>
</layout>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 日志输出级别 -->
<root level="DEBUG">
<appender-ref ref="Stdout" />
<appender-ref ref="RollingFile" />
</root>
<!--日志异步到数据库 -->
<!-- <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
日志异步到数据库
<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
连接池
<dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
<driverClass>com.mysql.jdbc.Driver</driverClass>
<url>jdbc:mysql://127.0.0.1:3306/databaseName</url>
<user>root</user>
<password>root</password>
</dataSource>
</connectionSource>
</appender> -->
</configuration>
六、总结
本文详细讲解了 SpringBoot 中异常处理(自定义页面、全局处理器)、Junit 单元测试、多环境配置(多文件 / 单 YML)、logback 日志配置四大核心技能。这些技能是 SpringBoot 开发的基础,掌握后能有效提升项目的健壮性和可维护性。在实际项目中,可根据业务需求灵活调整配置,比如异常处理器可扩展更多异常类型、日志可配置异步写入数据库等。