异常是什么
在计算机程序运行的过程中,总是会出现各种各样的错误。
有一些错误是用户造成的,比如,希望用户输入一个int类型的年龄,但是用户的输入是abc:
还有一些错误是随机出现,并且永远不可能避免的。比如:
网络突然断了,连接不到远程服务器;
内存耗尽,程序崩溃了;
用户点“打印”,但根本没有打印机;
……
所以,一个健壮的程序必须处理各种各样的错误。
所谓错误,就是程序调用某个函数的时候,如果失败了,就表示出错。
有什么用
异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。
怎么用
1.异常图解
分为2类
一类是错误error
- 代表不可避免的错误,比如硬件的内存不足等等没法处理的
另一类是异常exception
- 代表的一些可以预知的错误,比如用户输入字母,而我们可以捕获处理放回的错误
2.异常的使用
一般使用只需要这样
public class UserException extends RuntimeException{
public UserException(String msg) {
super(msg);
}
}
但是为了更好的应用等等,来搭配枚举来使用
枚举类
package com.java.liang.emun;
/**
* @author: 余亮亮
* @description:
* @create: 2020-03-28 20:45:16
**/
public enum ResultEnum {
USERNAME_NULL(201,"账号为空"),
;
private Integer code;
private String msg;
ResultEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
异常类
package com.java.liang.exception;
import com.java.liang.emun.ResultEnum;
/**
* @author: 余亮亮
* @description:
* @create: 2020-03-28 20:45:16
**/
public class UserException extends RuntimeException{
private Integer code;
private String msg;
public UserException(ResultEnum resultEnum) {
super(resultEnum.getMsg());
this.msg = resultEnum.getMsg();
this.code= resultEnum.getCode();
}
public UserException() {
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
自定义返回类型
public class Result<T> {
private Integer code;
private String msg;
private T data;
//...get,set,toString,构造方法不写了
}
业务逻辑中
@RestController
public class TestController {
@GetMapping("/get/{id}")
public Result get(@PathVariable("id") Integer id){
if (id.equals(1)){
throw new UserException(ResultEnum.USERNAME_NULL);
}
return new Result(200,"牛皮",id);
}
}
当我们故意运行让他出错
发现程序返回500错误
而且程序运行停止了
那该怎么办呢
这时候就可以进行异常捕捉
第一种方法是用try catch
@RestController
public class TestController {
@GetMapping("/get/{id}")
public Result get(@PathVariable("id") Integer id){
try {
if (id.equals(1)){
throw new UserException(ResultEnum.USERNAME_NULL);
}
}catch (UserException e){
return new Result(e.getCode(),e.getMsg(),id);
}
return new Result(200,"牛皮",id);
}
}
结果
结果很好,确实返回了我们想要的数据,那么如果我们异常类型很多呢?
不单单只有这一个了,那就需要全局捕获异常
package com.java.liang.handler;
import com.java.liang.exception.UserException;
import com.java.liang.vo.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author: 余亮亮
* @description:
* @create: 2020-03-28 21:28:07
**/
@ControllerAdvice//标识一个捕捉异常的控制层
public class UserHandler {
@ExceptionHandler(value = UserException.class)//捕获异常的类型
@ResponseBody//返回json格式
public Result handerSellException(UserException e){
return new Result(e.getCode(),e.getMsg(),null);
}
}
再一次故意报异常
完美结局,前提用户返回到了自己可以看得懂的数据
后台也没停止
当然后面可以在枚举里写很多
public enum ResultEnum {
USERNAME_NULL(201,"账号为空"),
PASSWORD_NULL(202,"密码为null"),
USERNAME_NOT_NULL(203,"账号不为null"),
PASSWORD_NOT_NULL(204,"密码不为null"),
;
private Integer code;
private String msg;
ResultEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
然后业务逻辑(这里只是模拟出错直接抛出异常,正常已改在业务逻辑里判断怎么怎么在抛出)
@RestController
public class TestController {
@GetMapping("/get/{id}")
public Result get(@PathVariable("id") Integer id){
if (id.equals(1)){
throw new UserException(ResultEnum.USERNAME_NULL);
}if (id.equals(2)){
throw new UserException(ResultEnum.PASSWORD_NULL);
}if (id.equals(3)){
throw new UserException(ResultEnum.USERNAME_NOT_NULL);
}if (id.equals(4)){
throw new UserException(ResultEnum.PASSWORD_NOT_NULL);
}
return new Result(200,"牛皮",id);
}
}
依依测试都可以捕获到
总结
这可能是我最常用的异常方式吧
当然可能还有更好的模式
毕竟时代在进步!