前言
关于异常处理,是我们后端开发中,可以说是十分重要,这关系到我们和前端是否能够有效沟通。
这样一个场景:
xx前端:xx后台,你接口报错了,快来看。
xx后端:怎么可能,报的什么错
xx前端:不知道,就是显示服务器错误。我怎么知道。
xx后端默默的打开日志,开始搜寻错误起来。经过一番努力,终于发现,原来是前台传参错误了。
接着后台就又开始跟前端交流,开始讲解如何传参。。。
此时时间已过去大半个小时了
就这样的场景,我们可以说是经常发生,如何我们能够有效的返回错误类型,以及提示信息。这样我们的开发效率就会大大提高了。这样是不是我们就有更多时间去学习(摸鱼)了
spring中异常处理3大注解
- @ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度
- @ControllerAdvice:异常集中处理,更好的使业务逻辑与异常处理剥离开;其是对Controller层进行拦截
- @ResponseStatus:可以将某种异常映射为HTTP状态码
在springboot中,用到的是aop容器思想,简单的概括就是,通过注解加入容器、然后注入到所需的地方。不明白的同学,应该去了解了解一下。
有了这3大注解,我们就可以处理我们的异常了。
代码实操
UnifyResponse.java //这里定义的是我们返回给前台的内容
public class UnifyResponse {
private int code;
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public String getRequest() {
return request;
}
}
exception-code.properties // 配置错误类型,如下图
http.codes[30003] = 定义的错误类型1
http.codes[30005] = 定义的错误类型2
exception-code.properties 文件位置
ExceptionCodeConfiguration.java // 读取配置文件
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@ConfigurationProperties(prefix = "http") // 配置文件键值前缀,http.codes即可用codes代替
@PropertySource(value = "classpath:config/exception-code.properties") // 配置文件路径
@Component // 加入容器
public class ExceptionCodeConfiguration {
private Map<Integer, String> codes = new HashMap<>();
public Map<Integer, String> getCodes() {
return codes;
}
public void setCodes(Map<Integer, String> codes) {
this.codes = codes;
}
public String getMessage(int code){
String message = codes.get(code);
return message;
}
}
HttpException.java // 通用错误类型
public class HttpException extends RuntimeException {
protected Integer code;
public Integer getCode() {
return code;
}
public Integer getHttpStatusCode() {
return httpStatusCode;
}
protected Integer httpStatusCode = 500;
}
NotFoundException.java // 具体错误类型,可拓展其他具体错误
public class NotFoundException extends HttpException {
public NotFoundException(int code){
this.httpStatusCode = 404;
this.code = code;
}
}
GlobalExceptionAdvice.java // 全局错误处理文件
@ControllerAdvice // 可以捕获contrller的错误
public class GlobalExceptionAdvice {
@Autowired
private ExceptionCodeConfiguration codeConfiguration;
@ExceptionHandler(value=Exception.class) // 通用错误类型
@ResponseBody // 加上这个,才能返回给前端
@ResponseStatus(code= HttpStatus.INTERNAL_SERVER_ERROR) // 定义错误status
public UnifyResponse handleException(HttpServletRequest req, Exception e) {
String requestUrl = req.getRequestURI(); // 请求连接
String method = req.getMethod(); // 请求方法
System.out.println(e); // 打印出错误信息
UnifyResponse message = new UnifyResponse(9999, "服务器异常", method + " "+ requestUrl);
return message;
}
@ExceptionHandler(HttpException.class) // 捕获我们定义的http错误类型
public ResponseEntity<UnifyResponse> handleHttpException(HttpServletRequest req, HttpException e){
String requestUrl = req.getRequestURI();
String method = req.getMethod();
UnifyResponse message = new UnifyResponse(e.getCode(),codeConfiguration.getMessage(e.getCode()), method + " " + requestUrl);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpStatus httpStatus = HttpStatus.resolve(e.getHttpStatusCode());
// ResponseEntity包含了header信息,返回给前端,对UnifyResponse进行包裹了一层。
ResponseEntity<UnifyResponse> r = new ResponseEntity<>(message, headers, httpStatus);
return r;
}
}
那么如何来触发我们的错误呢。很简单,这里定义了一个简单的contrller接口,判断banner是否存在,不存在即可抛出错误。
最后把目录结构给大家看一看:
好了,今天的全局异常分享就到这里了,如果有任何问题可以和我一同交流哦。如果对你有用的话,感谢一键3连啦。拜┏(^0^)┛