异常介绍
异常有编译期异常(Exception)和运行期(RuntimeException)异常
运行期异常可以解决也可以不解决。
如果我们不处理,会抛给JVM处理,JVM的默认处理方式,是打印异常信息,并终止虚拟机
自己处理,用try,catch 处理,try里放的是有可能会出现问题的代码,捕捉异常时,多个异常可以并列,如果这些异常之间有继承关系,那么大的异常要放在后面。编译期异常必须解决,编译期的异常出现在编译期,异常不处理,程序无法执行
处理方式:
1.throw向上抛出,谁调用,谁处理
2.自己用try catch处理
3.一般我们在finally里面做一些善后处理,释放内存,不管有没有异常,finally里面都会执行异常处理流程图(按自己理解画的 , 有不对的地方欢迎评论 , 及时修改)
代码实现
1.首先说明一下异常处理的流程 , 在开发过程中 , 出现异常之后 , 一般都会统一处理, 所有 从dao层开始 , 如果出现异常 , 逐级向上抛.最后有springmvc统一处理
场景预设
我们预设这样一个场景,假如我们做新增商品item,需要接收下面的参数
price:价格(不能为空)
name:名称
@RestController
@RequestMapping("item")
public class ItemController {
@Autowired
private ItemService itemService;
@PostMapping("save")
public ResponseEntity<Item> save(Item item) {
if (item.getPrice() == null) {
// return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
throw new MyException(ExceptionEnum.INSERT_OPERATION_FAIL);
}
Item result = itemService.saveItem(item);
return ResponseEntity.status(HttpStatus.CREATED).body(result);
}
}
假设我们用户增加商品时 , 价格没有写 . 此时就应该响应给客户 , 价格没有写 , 停止后续的操作;
为了使我们给页面返回的异常结果更加规范 , 通常情况下, 我们会统一对异常进行捕捉
/**
* 统一异常处理类
*/
@ControllerAdvice //默认情况下,会拦截所有加了@Controller的类
public class BasicExceptionAdvice {
//对无法预知的异常进行统一处理
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(RuntimeException e){
return ResponseEntity.status(500).body(e.getMessage());
}
//捕捉自定义异常进行处理
@ExceptionHandler(LyException.class)
public ResponseEntity<ExceptionResult> handleLyException(LyException e){
return ResponseEntity.status(e.getStatus()).body(new ExceptionResult(e));
}
}
此时,我们需要定义一个自定义异常类 , 专门用来处理业务中的异常信息 , 并作出响应
@Getter
public class MyException extends RuntimeException {
private int status;//响应的状态码
//提供构造方法
public MyException(ExceptionEnum em) {
super(em.getMessage());
this.status = em.getStatus();
}
//提供构造方法
public MyException(ExceptionEnum em, Throwable cause) {
super(em.getMessage(), cause);
this.status = em.getStatus();
}
}
自定义异常枚举(简单的几条, 一般公司会提前规定好)
@Getter
public enum ExceptionEnum {
INVALID_FILE_TYPE(400, "无效的文件类型!"),
INVALID_PARAM_ERROR(400, "无效的请求参数!"),
INVALID_PHONE_NUMBER(400, "无效的手机号码"),
INVALID_VERIFY_CODE(400, "验证码错误!"),
INVALID_USERNAME_PASSWORD(400, "无效的用户名和密码!"),
INVALID_SERVER_ID_SECRET(400, "无效的服务id和密钥!"),
INVALID_NOTIFY_PARAM(400, "回调参数有误!"),
INVALID_NOTIFY_SIGN(400, "回调签名有误!"),
private int status;
private String message;
ExceptionEnum(int status, String message) {
this.status = status;
this.message = message;
}
}
自定义异常结果
@Getter
public class ExceptionResult {
private int status;
private String message;
private String timestamp;
public ExceptionResult(LyException e) {
this.status = e.getStatus();
this.message = e.getMessage();
this.timestamp = DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
}
}
以后,我们无论controller还是service层的业务处理,出现异常情况,都抛出自定义异常,方便统一处理。