Spring全局异常怎么处理你还不会?
项目中出现异常总是影响人的心情,当一大堆异常信息出现在用户使用界面的时候,用户一个投诉电话,这月绩效扣半,给老板白打工了,但是呢spring很好的替我们解决了这个问题。
我们在返回信息的时候大部分出现的是同样异常,为了扩展性和防止硬编码。先来个枚举。
public enum ExceptionsEnum {
EXCEPTIONS_Ex_ERROR(500,"服务内部错误,请稍后再试"),
EXCEPTIONS_Ex_NPE(10010,"空指针错误"),
EXCEPTIONS_Ex_PARA_ERROR(6666,"参数错误")
;
private final Integer code;
private final String mesg;
ExceptionsEnum(Integer code,String mesg){
this.code=code;
this.mesg=mesg;
}
public Integer getCode() {
return code;
}
public String getMesg() {
return mesg;
}
}
项目中可以创建全局响应对象,当然返回格式不统一也没问题,下面是全局返回对象。
@Data
public class ResultBodyPack<T> implements Serializable {
/**
* 返回码
*/
private Integer code;
/**
* 返回信息
*/
private String mesg;
/**
* 是否成功
*/
private Boolean success;
/**
* 返回数据
*/
private T data;
}
/**
* 公共返回结果
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResultBody<T> extends ResultBodyPack<T> {
/**
* 返回成功
* @param data
* @param <T>
* @return
*/
public static <T> ResultBody<T> success(T data){
ResultBody resultBody = new ResultBody();
resultBody.setCode(1);
resultBody.setData(data);
resultBody.setSuccess(true);
return resultBody;
}
/**
* 失败返回枚举里面写好的数据
* @param e
* @param <T>
* @return
*/
public static <T> ResultBody<T> fail(ExceptionsEnum e){
ResultBody resultBody = new ResultBody();
resultBody.setSuccess(false);
resultBody.setCode(e.getCode());
resultBody.setMesg(e.getMesg());
return resultBody;
}
/**
*
* @param code
* @param mesg
* @param <T>
* @return
*/
public static <T> ResultBody<T> fail(Integer code,String mesg){
ResultBody resultBody = new ResultBody();
resultBody.setSuccess(false);
resultBody.setCode(code);
resultBody.setMesg(mesg);
return resultBody;
}
}
响应数据格式写好了,下面是重头戏,全局异常+自定义异常,自定义异常呢,肯定没得跑是运行时异常,所以创建类继承RuntimeException。
@Data
public class CustomException extends RuntimeException {
private final Integer code;
private final String mesg;
public CustomException(ExceptionsEnum e) {
this.code = e.getCode();
this.mesg = e.getMesg();
}
}
自定义异常完成了,但是怎么去叫spring去搞它呢,也很简单,spring提供了两个注解
@ControllerAdvice(这是一个全局的异常处理)
@ExceptionHandler(会处理的异常及子异常)
@ControllerAdvice
@RestController
public class GlobalException {
/**
* 自定义异常返回特定的信息
* @param e
* @return
*/
@ExceptionHandler(CustomException.class)
public ResultBody customEx(CustomException e){
return ResultBody.fail(e.getCode(),e.getMesg());
}
/**
* 空指针返回特定的信息
* @param e
* @return
*/
@ExceptionHandler(NullPointerException.class)
public ResultBody npeEx(NullPointerException e){
return ResultBody.fail(ExceptionsEnum.EXCEPTIONS_Ex_NPE);
}
/**
* 所有的异常,除了上面两位
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public ResultBody allEx(Exception e){
return ResultBody.fail(ExceptionsEnum.EXCEPTIONS_Ex_ERROR);
}
}
这样全局异常处理就完成了,然后创建controller进行测试
@RestController
public class ExController {
/**
* 空指针异常
* @return
*/
@RequestMapping("npe")
public ResultBody npeTest(){
String name=null;
if(name.equals("name"));
return ResultBody.success("success");
}
/**
* 自定义异常
* @return
*/
@RequestMapping("ce")
public ResultBody customEx(){
if(true){
throw new CustomException(ExceptionsEnum.EXCEPTIONS_Ex_PARA_ERROR);
}
return ResultBody.success("success");
}
/**
* 全局异常
* @return
*/
@RequestMapping("ge")
public ResultBody globalEx(){
Integer.parseInt("asda");
return ResultBody.success("success");
}
}
上面测试了自定义异常,空指针异常指定输出,还有exception。
然后看看测试结果
但是这种全局异常解决不了404这种
所以我们还要加点东西
=@Controller
public class FourException implements ErrorController {
@Override
public String getErrorPath() {
return "error";
}
@RequestMapping("error")
public ModelAndView fof(ModelAndView m){
m.setViewName("404");
return m;
}
再次尝试,成功拦截404