默认情况,SpringBoot 提供两种不同响应方式
一般我们不会将错误信息返回前端,自己去try catch
捕获异常,但有个问题:每个方法都这样捕获异常,肯定是不合适,这是我们就需要全局的异常处理了。
@RestController
public class ExceptionController {
@GetMapping("exceptionA")
public void methodA() {
try {
int a = 100 / 0;
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用@EceptionHandle
注解实现某个类的局部异常处理
@RestController
public class ExceptionController {
@GetMapping("exceptionA")
public void methodA() {
int a = 100 / 0;
}
/**
* 局部异常处理
*/
@ExceptionHandler(Exception.class)
public String exHandler(Exception e) {
// 判断发生异常的类型是除0异常则做出响应
if (e instanceof ArithmeticException) {
return "发生了除0异常";
}
// 未知的异常做出响应
return "发生了未知异常";
}
}
使用@ControllerAdvice
+@ExceptionHandler
注解实现全局异常处理
自定义一个异常类
@RestControllerAdvice
public class DefaultException {
@ExceptionHandler({NullPointerException.class})
public String exception(NullPointerException exception) {
return "空指针异常";
}
@ExceptionHandler({IndexOutOfBoundsException.class})
public String exception(IndexOutOfBoundsException exception) {
return "数组越界异常";
}
}
增加一个异常方法测试,由于局部异常优先级更高先注释掉了
@RestController
public class ExceptionController {
@GetMapping("exceptionA")
public void methodA() {
int a = 100 / 0;
}
@GetMapping("exceptionB")
public void methodB() {
List list = new ArrayList<>();
System.out.println(list.get(0));
}
/**
* 局部异常处理
*/
//@ExceptionHandler(Exception.class)
//public String exHandler(Exception e) {
// // 判断发生异常的类型是除0异常则做出响应
// if (e instanceof ArithmeticException) {
// return "发生了除0异常";
// }
// // 未知的异常做出响应
// return "发生了未知异常";
//}
}
全局异常注解已生效
自定义异常只需要继承exception
类或其子类
@Data
@NoArgsConstructor
public class CustomException extends Exception {
private static final long serialVersionUID = 1L;
private Integer code;
private String mes;
/**
* @param code 状态码
* @param msg 异常返回信息
* @description 构造器
*/
public CustomException(Integer code, String msg) {
super(msg);
this.code = code;
}
}
使用时可以直接抛出异常对象
@GetMapping("exceptionC")
public void methodC() throws CustomException {
int a = 1;
if (a == 1) {
throw new CustomException(10086, "自定义异常");
}
}
实际开发中我们需要封装统一的响应对象,区分状态码和信息,以便前端处理。
一般包含状态码,错误信息,数据等。
自定义一些方法用来返回信息,比如我定义的success(),failed()方法
@Data
@NoArgsConstructor
@AllArgsConstructor
public class R {
/**
* 返回状态码
*/
private Integer code;
/**
* 返回信息
*/
private String msg;
/**
* 数据
*/
private T data;
public static R success() {
return new R(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), null);
}
public static R success(Object data) {
return new R(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), data);
}
public static R failed() {
return new R(ResultCode.FAILED.getCode(), ResultCode.FAILED.getMsg(), null);
}
public static R failed(String msg) {
return new R(ResultCode.FAILED.getCode(), msg, null);
}
public static R failed(int code, String msg) {
return new R(code, msg, null);
}
}
枚举一些常用的状态信息
我就举个例子,只枚举2个,根据需要去自定义
@NoArgsConstructor
@AllArgsConstructor
public enum ResultCode {
SUCCESS(200, "请求成功"),
FAILED(500, "服务器错误");
private int code;
private String msg;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
使用时直接返回定义的对象类型就行了,将定义的全局异常返回类型也改成统一的响应对象
@RestControllerAdvice
public class DefaultException {
@ExceptionHandler({CustomException.class})
public R exception(CustomException e) {
return R.failed(e.getCode(),e.getMessage());
}
@ExceptionHandler({Exception.class})
public R exception(Exception e) {
return R.failed(e.getMessage());
}
}
一直想整理出一份完美的面试宝典,但是时间上一直腾不开,这套一千多道面试题宝典,结合今年金三银四各种大厂面试题,以及 GitHub 上 star 数超 30K+ 的文档整理出来的,我上传以后,毫无意外的短短半个小时点赞量就达到了 13k,说实话还是有点不可思议的。
需要完整版的小伙伴,可以一键三连后,点击这里!
内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、SpringBoot、SpringCloud、RabbitMQ、Kafka、Linux等技术栈(485页)
内容涵盖:Java基础、JVM、高并发、多线程、分布式、设计模式、Spring全家桶、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Netty、Tomcat、数据库、云计算等
由于篇幅限制,详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
需要完整版的小伙伴,可以一键三连后,点击这里!