beyondsoft-exception-spring3-starter 开发文档
1. 项目概述
beyondsoft-exception-spring3-starter 是一个基于 Spring Boot 3.x 的全局异常处理 Starter,提供了统一的异常处理机制,能够捕获和处理系统中各种类型的异常,并返回标准化的错误响应。该模块依赖于 common-base 模块,旨在简化 Spring Boot 应用中的异常处理,提高系统的可维护性和用户体验。
2. 核心功能
2.1 全局异常处理
提供了全局异常处理器,能够捕获和处理系统中各种类型的异常,包括业务异常、参数异常、系统异常等。
2.2 标准化错误响应
所有异常都会被转换为标准化的错误响应格式,包含错误码、错误信息、时间戳等信息,便于前端统一处理。
2.3 自动配置
通过 Spring Boot 的自动配置机制,无需手动配置即可使用全局异常处理功能。
2.4 详细日志记录
对所有捕获的异常进行详细日志记录,包括请求 URI、异常信息、异常堆栈等,便于问题定位和排查。
3. 支持的异常类型
3.1 自定义异常
RequestEncryptException:请求加密异常RequestSqlInjectException:SQL 注入异常BusinessException:业务异常DataConflictException:数据冲突异常InternalServerException:内部服务器异常ParameterInvalidException:参数无效异常RemoteAccessException:远程访问异常ExcelException:Excel 操作异常
3.2 Spring 框架异常
NoResourceFoundException:资源不存在异常HttpMessageNotReadableException:HTTP 消息不可读异常MethodArgumentNotValidException:方法参数验证异常MultipartException:文件上传异常
3.3 认证授权异常
NotLoginException:未登录异常NotPermissionException:权限不足异常
3.4 系统异常
NullPointerException:空指针异常EOFException:文件结束异常IOFileUploadException:文件上传 IO 异常Throwable:其他所有异常
4. 错误响应格式
json
{
"status": 400,
"code": 10001,
"msg": "参数校验不通过",
"timestamp": 1634567890000,
"traceId": "1234567890abcdef",
"reason": "具体错误原因"
}5. 集成使用
5.1 添加依赖
在项目的 pom.xml 文件中添加以下依赖:
xml
<dependency>
<groupId>com.beyondsoft</groupId>
<artifactId>beyondsoft-exception-spring3-starter</artifactId>
<version>${beyondsoft.version}</version>
</dependency>5.2 自动配置
该 Starter 会自动配置全局异常处理器,无需手动配置。引入依赖后,全局异常处理功能会自动生效。
5.3 详细使用示例
5.3.1 抛出自定义业务异常
java
// 在 Service 层抛出自定义业务异常
@Service
public class UserServiceImpl implements UserService {
@Override
public User getUserById(Long id) {
User user = userMapper.selectById(id);
if (user == null) {
// 使用响应码枚举抛出异常
throw new BusinessException(ResponseCodeEnums.USER_NOT_EXIST);
}
return user;
}
@Override
public void updateUser(User user) {
// 检查用户是否存在
User existingUser = userMapper.selectById(user.getId());
if (existingUser == null) {
// 自定义异常信息
throw new BusinessException("用户不存在,无法更新");
}
// 检查用户名是否已被其他用户使用
User userByUsername = userMapper.selectByUsername(user.getUsername());
if (userByUsername != null && !userByUsername.getId().equals(user.getId())) {
// 带数据的异常
Map<String, Object> data = new HashMap<>();
data.put("username", user.getUsername());
throw new BusinessException(ResponseCodeEnums.USER_HAS_EXISTED, data);
}
userMapper.updateById(user);
}
}5.3.2 参数验证异常处理
java
// 定义请求参数DTO
@Data
public class UserCreateRequest {
@NotNull(message = "用户名不能为空")
@Size(min = 3, max = 20, message = "用户名长度必须在3-20个字符之间")
private String username;
@NotNull(message = "密码不能为空")
@Size(min = 6, max = 20, message = "密码长度必须在6-20个字符之间")
private String password;
@Email(message = "邮箱格式不正确")
private String email;
}
// 在 Controller 中使用 @Valid 注解进行参数验证
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public User createUser(@RequestBody @Valid UserCreateRequest request) {
// 业务逻辑
User user = userService.createUser(request);
return user;
}
}
// 当参数验证失败时,会抛出 MethodArgumentNotValidException
// 全局异常处理器会捕获并处理,返回以下格式的响应:
// {
// "status": 405,
// "code": 405,
// "msg": "用户名不能为空,密码长度必须在6-20个字符之间",
// "timestamp": 1634567890000,
// "traceId": "1234567890abcdef",
// "reason": "具体错误原因"
// }5.3.3 认证授权异常处理
java
// 在拦截器中进行认证检查
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 检查用户是否已登录
if (StpUtil.isLogin()) {
return true;
}
// 未登录,抛出 NotLoginException
throw new NotLoginException("用户未登录");
}
}
// 在 Controller 方法上使用权限注解
@RestController
@RequestMapping("/api/admin")
public class AdminController {
@SaCheckPermission("admin:user:list")
@GetMapping("/users")
public Page<User> listUsers(Page<User> page) {
// 业务逻辑
return userService.page(page);
}
}
// 当权限不足时,会抛出 NotPermissionException
// 全局异常处理器会捕获并处理,返回以下格式的响应:
// {
// "status": 403,
// "code": 20008,
// "msg": "用户接口权限不足",
// "timestamp": 1634567890000,
// "traceId": "1234567890abcdef",
// "reason": "具体错误原因"
// }5.3.4 文件上传异常处理
java
// 文件上传 Controller
@RestController
@RequestMapping("/api/files")
public class FileController {
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {
// 业务逻辑
String filePath = fileService.uploadFile(file);
return filePath;
}
}
// 当文件上传失败时(如文件过大、网络中断等),会抛出 MultipartException 或其他相关异常
// 全局异常处理器会捕获并处理,返回以下格式的响应:
// {
// "status": 408,
// "code": 30009,
// "msg": "用户取消上传",
// "timestamp": 1634567890000,
// "traceId": "1234567890abcdef",
// "reason": "具体错误原因"
// }5.3.5 SQL注入异常处理
java
// 在过滤器中进行 SQL 注入检测
@Component
public class SqlInjectFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 检测请求参数中是否包含 SQL 注入风险
if (SqlInjectUtils.checkRequest(request)) {
throw new RequestSqlInjectException("请求参数存在 SQL 注入风险");
}
filterChain.doFilter(request, response);
}
}
// 全局异常处理器会捕获 RequestSqlInjectException 并处理,返回以下格式的响应:
// {
// "status": 406,
// "code": 10001,
// "msg": "参数校验不通过",
// "timestamp": 1634567890000,
// "traceId": "1234567890abcdef",
// "reason": "具体错误原因"
// }5.3.6 Excel 操作异常处理
java
// Excel 导入导出 Service
@Service
public class ExcelService {
@Override
public List<User> importUsers(MultipartFile file) {
try {
// Excel 导入逻辑
return ExcelUtil.importExcel(file, 1, User.class);
} catch (Exception e) {
// 捕获 Excel 操作异常并转换为自定义异常
throw new ExcelException("Excel 导入失败:" + e.getMessage());
}
}
}
// 全局异常处理器会捕获 ExcelException 并处理,返回以下格式的响应:
// {
// "status": 405,
// "code": 10001,
// "msg": "参数校验不通过",
// "timestamp": 1634567890000,
// "traceId": "1234567890abcdef",
// "reason": "Excel 导入失败:文件格式不正确"
// }5.4 自定义异常扩展
如果需要扩展自定义异常类型,可以按照以下步骤进行:
java
// 1. 创建自定义异常类,继承 RequestException
public class CustomBusinessException extends RequestException {
private static final long serialVersionUID = 1L;
public CustomBusinessException() {
super();
}
public CustomBusinessException(ResponseCodeEnums responseCodeEnums) {
super(responseCodeEnums);
}
public CustomBusinessException(String msg) {
super(msg);
}
}
// 2. 在 GlobalExceptionHandler 中添加异常处理方法
// 注意:需要在自己的项目中创建全局异常处理器,或者扩展原有处理器
@RestControllerAdvice
public class CustomGlobalExceptionHandler extends GlobalExceptionHandler {
@ExceptionHandler(value = {CustomBusinessException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResult handleCustomBusinessException(CustomBusinessException e, HttpServletRequest request) {
log.error("Catch CustomBusinessException:
uri={}
message={}
code={}",
request.getRequestURI(), e.getMessage(), e.getCode(), e);
return ErrorResult.failure(ResponseCodeEnums.PARAM_IS_INVALID, e, HttpStatus.BAD_REQUEST);
}
}
// 3. 在业务代码中使用自定义异常
@Service
public class CustomService {
public void doSomething() {
// 业务逻辑
throw new CustomBusinessException("自定义业务异常");
}
}6. 核心代码实现
6.1 全局异常处理器
java
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
// 各种异常处理方法
@ExceptionHandler(value = {BusinessException.class})
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
public ErrorResult handleBusinessException(BusinessException e, HttpServletRequest request) {
// 异常处理逻辑
}
// 其他异常处理方法...
}6.2 自动配置类
java
@Configuration
public class BeyondsoftExceptionAutoConfig {
@Bean
public GlobalExceptionHandler globalExceptionHandler() {
return new GlobalExceptionHandler();
}
}7. 依赖说明
| 依赖项 | 版本 | 用途 |
|---|---|---|
| spring-boot-starter-web | - | Web 支持 |
| lombok | - | 简化 Java 代码 |
| common-base | - | 公共基础模块 |
| sa-token-spring-boot3-starter | - | 认证授权 |
| spring-boot-starter-validation | - | 参数验证 |
8. 注意事项
- 异常信息保密:避免在生产环境中返回详细的异常堆栈信息给前端,防止敏感信息泄露。
- 自定义异常扩展:如需扩展自定义异常类型,只需继承相应的异常基类并在全局异常处理器中添加对应的处理方法即可。
- 日志级别:异常日志记录使用 ERROR 级别,确保能够被及时发现和处理。
- 响应状态码:不同类型的异常会返回不同的 HTTP 响应状态码,便于前端根据状态码进行不同的处理。
9. 版本历史
- 初始版本:提供基础的全局异常处理功能
10. 联系方式
如有问题或建议,请联系开发团队。
文档更新时间:2025-12-30 文档版本:1.0.0