Springboot中的异常处理
@ControllerAdvice
虽然只是在处理@Controller
注解的类,在@Service
层抛出的异常如果没有在@Service
层被处理的话,会向上抛出到到@Controller
层,再被异常处理器捕获
1. 全局异常处理
@ControllerAdvice
:全局处理器,处理有@Controller
注解的类,这里是处理了异常,还可以处理别的东西
@RestControllerAdvice
:@ControllerAdvice
+ @ResponseBody
@ExceptionHandler
:异常处理器,它的参数可以指定具体的异常类型
import com.example.common.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice // 注解的作用:应用与所有@Controller注解的类,并结合了@ResponseBody
public class GlobalExceptionHandler {
// 处理全局异常
@ExceptionHandler // 处理什么异常取决与此注解的value,此处是处理所有异常
public Result<String> handler(Exception e){ // 参数是异常的类型
return Result.error("500","服务器异常"); // 直接返回给前端
}
}
2. 处理主动抛出的自定义异常
- 自定义异常类
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
// 自定义异常,继承RuntimeException,表示这是一个运行时异常,需要在代码中手动抛出
public class CustomException extends RuntimeException{
private String msg;
}
- 处理自定义异常
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理自定义异常
@ExceptionHandler(CustomException.class) // 指定处理的异常类型为CustomException
public Result<String> handler(CustomException e){
return Result.error("100",e.getMsg()); // 直接返回给前端
}
}
- 如何抛出自定义异常
throw new CustomException("自定义异常");
3. 异常处理的完整代码(方便拷贝)
import com.example.common.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice // 注解的作用:应用与所有@Controller注解的类,并结合了@ResponseBody
public class GlobalExceptionHandler {
// 处理全局异常
@ExceptionHandler // 处理异常,处理什么异常取决与此注解的value,此处是处理所有异常
public Result<String> handler(Exception e){ // 参数是异常的类型
return Result.error("500","服务器异常");
}
// 处理自定义异常
@ExceptionHandler(CustomException.class) // 处理自定义异常
public Result<String> handler(CustomException e){
return Result.error("100",e.getMsg());
}
}
4. 自定义sql异常处理(方便拷贝)
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error("异常信息:{}", ex.getMessage());
String message = ex.getMessage(); // Duplicate entry 'lisi' for key 'employee.idx_username'
// 从异常信息中分析具体错误原因
if (message.contains("Duplicate entry")){
String[] split = message.split(" ");
String username = split[2];
return Result.error(username + MessageConstant.ALREADY_EXISTS);
}
return Result.error(MessageConstant.UNKNOWN_ERROR);
}
5. 代码中用到的Result类
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Result<T> {
private String code; // 代码
private String msg; // 信息
private T data; // 数据
public static <T> Result<T> ok(){
return new Result<T>("1", "success", null);
}
public static <T> Result<T> ok(T data){
return new Result<>("1", "success", data);
}
public static <T> Result<T> error(String msg){
return new Result<T>("0", msg, null);
}
public static <T> Result<T> error(String code, String message){
return new Result<>(code, message, null);
}
}