1.全局异常处理器
在开发springboot项目过程中,我们不可避免的需要处理各种异常,spring mvc架构中各层会出现大量的try-catch代码块,不仅有大量的冗余代码,而且还影响代码的可读性。
同时,通常来说,我们对于业务的期望,是有一条明确的主线的。而我们后期的处理原则很简单,只要出现不符合主线预期的情况,我们就可以通过手动控制抛出异常的方式,来控制程序执行。
【使用思路】:
我们之前碰到请求结果不符合预期的时候,解决方案是在service层手动抛出异常(比如,密码错误,用户被禁用,信息未找到,用户越权访问等),然后在controller层统一解决异常。而我们在controller层的解决方式,也无非就是try-catch,如果发现异常,就返回给客户端一个请求失败的响应信息。
而全局异常处理器,它的功能就是捕捉并处理Controller中指定的异常。
这样,我们只需要定义一个业务异常的父类BusinessException
,然后创建多个具体的业务异常,且都继承自BusinessException。这样,我们只需要在全局异常处理器中处理BusinessException这个业务异常的父类,就能捕捉并统一处理所有具体的业务异常。
2. 代码实现
目录结构如下
config
└─ GlobalExceptionHandler # 全局异常处理器
exception
└─ BusinessException # 业务异常父类
└─ XXXException # 具体的业务异常1
└─ XXXException # 具体的业务异常2
........
我们以登录模块全局异常处理为例子
在登录的功能中,我们期望的结果是,用户名密码正确,登录成功,服务器返回给客户端登陆成功的信息。
在下面的例子中,我们可能碰到的请求失败的结果,大概分为以下三类:
1. 用户名不存在
2. 密码错误
3. 用户被禁用
GlobalExceptionHandler.java
全局异常处理器。我们主要通过注解@RestControllerAdvice
标明这是一个全局异常处理类。在方法上通过@ExceptionHandler
注解指明你需要处理的异常类型
/**
* 全局异常处理器类
* @Author Mosfield
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理异常BusinessException及其子异常
@ExceptionHandler(BusinessException.class)
public Result handleException(BusinessException exception){
// 统一返回请求失败结果
return Result.error(exception.getMessage());
}
}
BusinessException.java
业务异常父类
/**
* 业务异常父类
* @Author Mosfield
*/
public class BusinessException extends RuntimeException{
public BusinessException() {
super();
}
public BusinessException(String message) {
super(message);
}
}
UserNotFoundException.java
业务异常例子:用户未找到异常,继承自业务异常父类
/**
* 未找到用户异常
* @Author Mosfield
*/
public class UserNotFoundException extends BusinessException{
public UserNotFoundException() {
super();
}
public UserNotFoundException(String message) {
super(message);
}
}
Service
具体实现登录逻辑的service
/**
* 具体登录方法
*/
@Override
public User login(User user) {
// 根据用户名获取对应的用户数据
User result = userMapper.findUserByUserName(user.getUsername());
// 判断用户是否存在
if(result == null){
throw new UserNotFoundException("用户名不存在");
}
// 计算md5加密后的密码
String md5Pass = DigestUtils.md5DigestAsHex(user.getPassword().getBytes(StandardCharsets.UTF_8));
// 判断密码是否正确
if(!result.getPassword().equals(md5Pass)){
throw new PasswordMismatchException("密码错误");
}
// 判断用户是否被禁用
if(result.getStatus() == 0){
throw new UserDisableException("用户已禁用");
}
return result;
}
Comments NOTHING