SpringBoot 异常处理的最佳实践

news/2024/12/23 14:19:55/

SpringBoot 异常处理的最佳实践

在 Web 开发中,异常处理是非常重要的一环。在 SpringBoot 框架中,异常处理方式有很多种,但是如何选择最佳实践呢?本文将介绍 SpringBoot 异常处理的最佳实践,并附带代码示例。

在这里插入图片描述

异常处理的最佳实践

异常处理的最佳实践包括以下几个方面:

  1. 统一异常处理

在 SpringBoot 中,我们可以使用 @ControllerAdvice 注解实现全局异常处理。使用 @ControllerAdvice 注解,我们可以集中处理所有 Controller 层抛出的异常,而不必在每个 Controller 中单独处理。在 GlobalExceptionHandler 类中定义异常处理方法,并根据具体的业务需求对异常进行相应的处理,可以大大提高代码的可维护性和可读性。

  1. 自定义异常

在 SpringBoot 中,我们可以通过自定义异常类来处理特定的异常情况,并在 GlobalExceptionHandler 类中定义对应的异常处理方法。自定义异常类可以继承 RuntimeException 或 Exception 类,根据具体的业务需求进行选择。自定义异常类可以包含异常码、异常信息等属性,方便我们对异常进行更加细致的处理。

  1. 统一返回结果

在 SpringBoot 中,我们可以定义一个统一的返回结果类,用于封装接口返回结果。在接口返回时,我们可以使用该类作为返回值,并根据具体的业务需求封装返回结果的状态码、消息和数据等信息。

  1. 参数校验

在 SpringBoot 中,我们可以使用 javax.validation.constraints 包中的注解对参数进行校验。在 Controller 层中,我们可以使用 @Validated 注解对参数进行校验,并在对应的 Service 层方法中进行处理。如果参数校验失败,会抛出 MethodArgumentNotValidException 异常,在 GlobalExceptionHandler 类中的 handleMethodArgumentNotValidException 方法中进行处理。

  1. 日志记录

在 SpringBoot 中,我们可以使用日志框架记录系统运行时的异常信息。在 GlobalExceptionHandler 类中的异常处理方法中,我们可以使用日志框架记录异常发生的时间、异常类型、异常信息等相关信息,方便我们进行排查和问题定位。

完整代码示例

下面是一个完整的使用 SpringBoot 异常处理的示例代码:

@ControllerAdvice
public class GlobalExceptionHandler {private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);@ExceptionHandler(Exception.class)@ResponseBodypublic ErrorResponse handleException(Exception e) {logger.error("系统异常", e);return new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统异常");}@ExceptionHandler(UserNotFoundException.class)@ResponseBodypublic ErrorResponse handleUserNotFoundException(UserNotFoundException e) {logger.warn("用户不存在", e);return new ErrorResponse(HttpStatus.NOT_FOUND.value(), "用户不存在");}@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseBodypublic ErrorResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {BindingResult bindingResult = e.getBindingResult();List<ObjectError> allErrors = bindingResult.getAllErrors();List<String> errorMessages = new ArrayList<>();for (ObjectError error : allErrors) {errorMessages.add(error.getDefaultMessage());}String errorMessage = String.join(",", errorMessages);logger.warn("参数无效", e);return new ErrorResponse(HttpStatus.BAD_REQUEST.value(), errorMessage);}
}@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@PostMapping("/add")public Result addUser(@Validated @RequestBody User user) {userService.addUser(user);return Result.success();}@GetMapping("/{id}")public Result getUserById(@PathVariable("id") Long id) {User user = userService.getUserById(id);if (user == null) {throw new UserNotFoundException();}return Result.success(user);}
}@Service
public class UserService {@Autowiredprivate UserDao userDao;public void addUser(User user) {userDao.save(user);}public User getUserById(Long id) {return userDao.findById(id).orElse(null);}
}@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {@NotNull(message = "用户名不能为空")privateLong id;@NotBlank(message = "用户名不能为空")private String username;@NotBlank(message = "密码不能为空")private String password;
}@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {private Integer code;private String message;private T data;public static <T> Result<T> success() {return new Result<>(HttpStatus.OK.value(), "成功", null);}public static <T> Result<T> success(T data) {return new Result<>(HttpStatus.OK.value(), "成功", data);}public static <T> Result<T> error(Integer code, String message) {return new Result<>(code, message, null);}
}@Data
@NoArgsConstructor
@AllArgsConstructor
public class ErrorResponse {private Integer code;private String message;
}public class UserNotFoundException extends RuntimeException {
}@Repository
public interface UserDao extends JpaRepository<User, Long> {
}

在上面的代码示例中,我们定义了一个 GlobalExceptionHandler 类,用于处理全局异常。在该类中,我们定义了三个异常处理方法:handleException、handleUserNotFoundException 和 handleMethodArgumentNotValidException。分别用于处理系统异常、用户不存在异常和参数无效异常。在每个方法中,我们都使用日志框架记录异常信息,并返回封装好的 ErrorResponse 对象。

在 UserController 类中,我们使用 @Validated 注解对 addUser 方法中的 User 参数进行了校验。如果校验失败,会抛出 MethodArgumentNotValidException 异常,在 GlobalExceptionHandler 类中的 handleMethodArgumentNotValidException 方法中进行处理。

在 UserService 类中,我们使用了 JpaRepository 接口,对 User 数据进行了持久化操作。

最后,我们定义了 User、Result、ErrorResponse 和 UserNotFoundException 四个类,分别用于封装用户信息、接口返回结果、错误信息和用户不存在异常。

结论

在本文中,我们介绍了 SpringBoot 异常处理的最佳实践,并附带了完整的代码示例。在使用 SpringBoot 进行 Web 开发时,我们应该充分考虑异常处理的方方面面,以保证代码的可维护性和可读性。通过使用统一异常处理、自定义异常、统一返回结果、参数校验和日志记录等技术手段,我们可以更加高效地进行异常处理,提高系统的稳定性和可靠性。


http://www.ppmy.cn/news/517407.html

相关文章

法兰克焊接机器人编程入门_焊接机器人编程入门基本常识

众所周知&#xff0c;机器人是一个非常复杂的构造&#xff0c;要想能够操作机器人完成各项作业&#xff0c;对机器人的操作者有很高的要求。随着机器人的大范围普及&#xff0c;参与机器人行业的人也是越来越多&#xff0c;下面就为大家科普一些焊接机器人编程入门基本常识。 焊…

法兰克机器人循环编程_FANUC机器人循环指令介绍

如果我们想在Fanuc机器人编程中对一定的内容进行多次重复执行&#xff0c;可以用什么指令来满足&#xff1f;一般来讲&#xff0c;介于FOR和ENDFOR指令中间的程序内容可以实现多次重复执行&#xff0c;FOR和ENDFOR是一组成对出现的指令&#xff0c;缺一不可&#xff0c;在专业上…

数控铣削图案及编程_数控铣床漂亮编程图案 数控铣床编程100例

求80*60的木板上用数控铣床刻一个漂亮图案&#xff0c;求编程程序&#xff1f; 你学什么样的机床&#xff1f;如果是farak&#xff0c;则使用M98调用子例程。格式为m98p ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^因…

FANUC机器人的码垛堆积功能(二)示教编程

FANUC机器人的码垛堆积功能(二)示教编程 示教码垛堆积 码垛堆积的示教,按照如下步骤进行: 码垛堆积的示教,在码垛堆积编辑画面上进行。选择码垛堆积指令时,自动出现一个码垛堆积编辑画面。通过码垛堆积的示教,自动插入码垛堆积指令、码垛堆积动作指令、码垛堆积结束指令…

SpringBoot 如何使用 @RequestBody 进行数据校验

SpringBoot 如何使用 RequestBody 进行数据校验 在 Web 开发中&#xff0c;前台向后台发送数据是非常常见的场景。而在 SpringBoot 框架中&#xff0c;我们通常使用 RequestBody 注解来接收前台发送的 JSON 数据&#xff0c;并将其转化为 Java 对象。但是&#xff0c;接收到的…

数控铣床法兰克系统代码完整版

数控铣床法兰克系统代码 G00 01 定位&#xff08;快速移动&#xff09; G01 01 直线插补&#xff08;进给速度&#xff09; *G00和G01为一组&#xff0c;选其一 G02 01 顺时针圆弧插补 G03 01 逆时针圆弧插补 *G02和G03为一组&#xff0c;选其一 G04 00 暂停&#xff0…

计算机仿真实验报告实验原理简述,数控编程实验报告总结

数控车床是目前使用最广泛的数控机床之一。以下是数控编程实验报告总结范文,希望对大家有所帮助。 篇一:数控编程实验报告总结 实训一 数控车床认识及基本操作实训 一. 实训目的:了解数控车床掌握基本操作 二. 实训内容:用数控车床车一零件 三. 实训设备:数控车床 四. 实训…

fastadmin页面手动添加选项卡

需求&#xff1a;手动添加如图的选项卡 解决方案&#xff1a; 1、在对应的html页面&#xff0c;添加&#xff1a; <div class"panel-heading"><ul class"nav nav-tabs" data-field"status"><li class"active"><…