在编写代码的时候,尤其是在服务类中,经常会报各种异常信息,比如空指针异常,数据角标越界异常和数据库数据异常。尤其是数据库数据异常信息最难控制,因为数据库添加的数据不一定受你控制,就容易导致脏数据。
针对上面情况通常采用trycatch捕获异常。但有以下缺点:
trycatch会占用很多行代码,影响代码的简洁。
由于你不知道会抛出哪个异常。只能捕获异常的根类Exception,返回的信息也只能知道出异常了,不利于排查问题。
不卖关子,直接复制我下面列举的四个类,放在异常包中就可以自动拦截异常,然后根据自己需要丰富异常拦截类。
解决方案用到了注解@RestControllerAdvice,这个注解会拦截所有的RequestMapping注解,从而对http请求的返回信息进行封装。类信息如下:
package com.casic.finance.exception;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletResponse;
/**
* @author: 董胜得
* @date: 2021/3/12 18:08
* 此类为:
* 主要提供的功能为:
*/
@RestControllerAdvice
public class CtrollerExceptionHandler {
/**
* 处理系统异常,当发生数组角标越界异常的时候,会执行此方法
*
* @param e
* @return
*/
@ExceptionHandler(ArrayIndexOutOfBoundsException.class)
public ExceptionMessage handleValidationBodyException(ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
return new ExceptionMessage(ExceptionEnum.ARRAY_INDEX_OUT_OF_BOUND.getExcepCode(), e.getMessage());
}
/**
* 主动throw的异常,主动抛出异常会执行此方法
*
* @param e
* @param response
* @return
*/
@ExceptionHandler(MyThrowException.class)
public ExceptionMessage handleUnProccessableServiceException(MyThrowException e, HttpServletResponse response) {
e.printStackTrace();
response.setStatus(e.getStatusCode().value());
return new ExceptionMessage(e.getErrorCode(), e.getMessage());
}
/**
* 其他异常,如果发生了异常,但不属于上面的异常类别,就会执行此方法
*
* @param e
* @param response
* @return
*/
@ExceptionHandler(Exception.class)
public ExceptionMessage handleAllException(Exception e, HttpServletResponse response) {
e.printStackTrace();
return new ExceptionMessage(ExceptionEnum.OTHER_EXCEPTION.getExcepCode(), e.getMessage());
}
}
此类主要分为了三类异常:
1、可能发生但没有识别判断的异常,如角标越界,空指针一类的,在类中我只写了一个,这个可以自定义添加。
2、可能发生进行抛出的异常,也就是对信息判断,然后抛出指定的异常种类和信息,这个方法是抛出异常通用的。
3、没有想到的异常,我们不能列举所有异常,所以总会有我们没有想到的异常,就执行此方法。
注意:打印返回的信息最好用异常信息,容易定位异常
下面附上2.1中用到的几个类的源码
package com.casic.finance.exception;
import java.io.Serializable;
/**
* @author: 董胜得
* @date: 2021/3/15 10:03
* 此类为:
* 主要提供的功能为:自定义异常的编码和信息类
*/
public enum ExceptionEnum implements Serializable {
ARRAY_INDEX_OUT_OF_BOUND("200001","数组角标越界异常"),
NULL_POINTER_EXCEPTION("200002","空指针异常"),
SQL_EXCEPTION("200010","sql语句查询异常"),
OTHER_EXCEPTION("200030","其他异常"),
;
/**
* 异常代码
*/
private String excepCode;
/**
* 异常信息
*/
private String excepMessage;
ExceptionEnum() {
}
ExceptionEnum(String excepCode, String excepMessage) {
this.excepCode = excepCode;
this.excepMessage = excepMessage;
}
public String getExcepCode() {
return excepCode;
}
public void setExcepCode(String excepCode) {
this.excepCode = excepCode;
}
public String getExcepMessage() {
return excepMessage;
}
public void setExcepMessage(String excepMessage) {
this.excepMessage = excepMessage;
}
}
package com.casic.finance.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author: 董胜得
* @date: 2021/3/12 18:09
* 此类为:
* 主要提供的功能为:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExceptionMessage implements Serializable {
private static final long serialVersionUID = 8065583911104112360L;
private String excepCode;
private String excepMessage;
}
package com.casic.finance.exception;
import org.springframework.http.HttpStatus;
/**
* @author: 董胜得
* @date: 2021/3/12 18:10
* 此类为:
* 主要提供的功能为:
*/
public class MyThrowException extends RuntimeException {
private static final long serialVersionUID = 8109469326798389194L;
protected HttpStatus statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
private String errorCode;
public HttpStatus getStatusCode() {
return statusCode;
}
public void setStatusCode(HttpStatus statusCode) {
this.statusCode = statusCode;
}
public MyThrowException(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
}
在我的工程中异常信息处理是放在一个包中,可以直接拷贝复用,如下:
package com.casic.finance.controller;
import com.casic.finance.exception.MyThrowException;
import com.casic.integrationFrame.common.http.HttpResult;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("test")
@CrossOrigin
public class TestController {
Logger logger = LoggerFactory.getLogger(TestController.class);
@GetMapping(value = "/exception")
@ApiOperation(value = "测试异常请求")
public HttpResult exception() {
if (1/0==3)
throw new MyThrowException("505","服务异常");
return HttpResult.ok("hello");
}
}
上面代码在执行1/0的时候抛出了异常,这个异常属于我们没有考虑到的异常,属于其他类别。返回结果如下:
{
"excepCode": "200030",
"excepMessage": "/ by zero"
}
package com.casic.finance.controller;
import com.casic.finance.exception.MyThrowException;
import com.casic.integrationFrame.common.http.HttpResult;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("test")
@CrossOrigin
public class TestController {
Logger logger = LoggerFactory.getLogger(TestController.class);
@GetMapping(value = "/exception")
@ApiOperation(value = "测试异常请求")
public HttpResult exception() {
if (true)
throw new MyThrowException("200050","服务异常");
return HttpResult.ok("hello");
}
}
上面代码执行throw new MyThrowException(“505”,“服务异常”),这个异常属于我们直接抛出的异常,我们可以自定义异常的代码和错误信息
以上就是本章内容了,欢迎大家一起讨论,共同学习