1service层异常处理:
(1)常用@Transcational注解处理service层的异常,该注解可以设置在方法上,也可以设置在类上
(2)@Transactional遇到未被捕获的RuntimeException(运行时异常)默认会回滚,若使用try-catch捕获了异常,需要在catch中再抛出异常(throw new RuntimeException()),才能被捕获近而回滚 。controller层要继续捕获这个异常并处理
(3)@Transactional(rollbackFor=Exception.class)之后Exception异常也可回滚
(4)可以在catch块中使用
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常
2service层throw new RuntimeException("程序异常"),controller层使用Exception类的getMessage()方法输出异常信息原理
(1)首先调用RuntimeException构造器,传递message
(2)然后信息赋值到这里
(3)然后这里就有了数值
(4)由于是父类,所以Exception调用的时候getMessage()的时候,就会捕获这个信息
3controller层异常统一处理
(1)创建GlobalExceptionHandler类
- @ExceptionHandler:用于指定某一类异常处理的方法。
- @RestControllerAdvice是一个组合注解,由@ControllerAdvice、@ResponseBody组成
@ControllerAdvice
public class GlobalExceptionHandler {
//controller层遇到Exception返回
@ExceptionHandler(Exception.class)
@ResponseBody
public Result error(Exception e){
//打印在控制台
e.printStackTrace();
//返回到前端
return Result.fail();
}
//controller层遇到YyghException返回,需要先自定义YyghException异常
@ExceptionHandler(YyghException.class)
@ResponseBody
public Result error(YyghException e){
e.printStackTrace();
return Result.build(e.getCode(), e.getMessage());
}
}
(2)创建自定义异常类:YyghException类
代码语言:javascript复制@Data
@ApiModel(value = "自定义全局异常类")
public class YyghException extends RuntimeException {
@ApiModelProperty(value = "异常状态码")
private Integer code;
/**
* 通过状态码和错误消息创建异常对象
* @param message
* @param code
*/
public YyghException(String message, Integer code) {
super(message);
this.code = code;
}
}
(3)Result类
代码语言:javascript复制@Data
@ApiModel(value = "全局统一返回结果")
public class Result<T> {
@ApiModelProperty(value = "返回码")
private Integer code;
@ApiModelProperty(value = "返回消息")
private String message;
public Result(){}
public static <T> Result<T> build(Integer code, String message) {
Result<T> result = new Result<T>();
result.setCode(code);
result.setMessage(message);
return result;
}
public static<T> Result<T> ok(){
Result<T> result = new Result<T>();
result.setCode();
result.setMessage("成功");
return result;
}
public static<T> Result<T> fail(){
Result<T> result = new Result<T>();
result.setCode();
result.setMessage("失败");
return result;
}
}
(4)Controller中的方法
代码语言:javascript复制public Result test(){
//无需捕获,遇到Exception异常,直接调用GlobalExceptionHandler中@ExceptionHandler(Exception.class)注解下的方法
int a=/;
return Result.ok();
}
代码语言:javascript复制public Result test(){
//调用GlobalExceptionHandler中@ExceptionHandler(Exception.class)注解下的方法
try {
int a = / ;
}catch(Exception e){
throw new YyghException("自定义YyghException",);
}
return Result.ok();
}
4日志打印
代码语言:javascript复制try{
int a=/;
}catch(Exception e){
e.printStackTrace();
//这种写法只会输出逗号前面的内容,一般不这么写
logger.error("getMessage查看报错信息:",e.getMessage());
logger.error("getMessage查看报错信息:" e.getMessage());
logger.error("getMessage查看报错信息:{}",e.getMessage());
logger.error("toString查看报错信息:{}",e.toString());
logger.error("e查看报错信息:",e);
logger.error("e.getStackTrace().toString():{}",e.getStackTrace().toString());
logger.error("第一个Object参数:{},第二个Throwable:{}",hospitalSetService.getById(id),e);
logger.error("第一个Throwable:{},第二个Object参数:{}",e,hospitalSetService.getById(id));
}
e.printStackTrace();// 输出错误类型,详细信息以及行数,但是只能输出在控制台当中,日志文件看不到
代码语言:javascript复制java.lang.ArithmeticException: / by zero
at com.atguigu.yygh.hosp.controller.HospitalSetController.getHospSet(HospitalSetController.java:)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
logger.error("getMessage查看报错信息:" e.getMessage());和 logger.error("getMessage查看报错信息:{}",e.getMessage());;// 只能输出错误类型后面的简短信息,不便于排错
代码语言:javascript复制getMessage查看报错信息:/ by zero
logger.error("e.getStackTrace().toString():{}",e.getStackTrace().toString());// 不能输出错误信息,返回一个对象
代码语言:javascript复制e.getStackTrace().toString():[Ljava.lang.StackTraceElement;@ceeb7
logger.error("e查看报错信息:",e);// 可以在日志中输出完整的错误信息,""里要写内容,和e.printStackTrace()效果一样,只不过可以输出到日志中
代码语言:javascript复制java.lang.ArithmeticException: / by zero
at com.atguigu.yygh.hosp.controller.HospitalSetController.getHospSet(HospitalSetController.java:)
logger.error("toString查看报错信息:{}",e.toString());// 只能输出简短的错误信息,不能输出行数,不便于排错
代码语言:javascript复制toString查看报错信息:java.lang.ArithmeticException: / by zero
logger打印日志的时候:当参数被识别为Object对象的时候,logger中的占位符会生效,如果识别为Throwable则不会生效。
只要将异常信息e作为最后一个参数,不论使用还是不使用占位符,都不会影响异常信息的输出,只是占位符不起作用。异常信息e若不是最后一个参数,则占位符会起作用,但是异常信息可能会显示不全