在项目开发过程中,不管是对底层数据库的操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。如果对每个过程都单独作异常处理,那系统的代码耦合度会变得很高,此外,开发工作量也会加大而且不好统一,这也增加了代码的维护成本。
针对这种实际情况,我们需要将所有类型的异常处理从各处理过程解耦出来,这样既保证了相关处理过程的功能单一,也实现了异常信息的统一处理和维护。同时,我们也不希望直接把异常抛给用户,应该对异常进行处理,对错误信息进行封装,然后返回一个友好的信息给用户。
方法如下:
1. 定义返回的统一 json 结构
import lombok.Data;
@Data
public class EJson {
/**
* 异常码
*/
protected String code;
/**
* 异常信息
*/
protected String msg;
public EJson() {
this.code = "200";
this.msg = "操作成功";
}
public EJson(String code, String msg) {
this.code = code;
this.msg = msg;
}
}2. 处理系统异常
新建一个 GlobalExceptionHandler 全局异常处理类,
@ControllerAdvice 注解即可拦截项目中抛出的异常
@ResponseBody 注解是为了异常处理完之后给调用方输出一个 json 格式的封装 数据。
如下:
第一个拦截异常:参数缺失的时候,会抛出 HttpMessageNotReadableException
第二个拦截异常:空指针异常, NullPointerException
以此类推: 可以定义更多的异常.....................
最后把再定义一个 Exception异常, 前边没有被拦截的异常,统统都会在这里被拦截
Exception 异常是父类,所有异常都会继承该异常,所以我们可以直接拦截 Exception 异常,一劳永逸
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
// 打印log
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 缺少请求参数异常
* @param ex HttpMessageNotReadableException
* @return
*/
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public EJson handleHttpMessageNotReadableException(
MissingServletRequestParameterException ex) {
logger.error("缺少请求参数,{}", ex.getMessage());
return new EJson("400", "缺少必要的请求参数");
}
/**
* 空指针异常
* @param ex NullPointerException
* @return
*/
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public EJson handleTypeMismatchException(NullPointerException ex) {
logger.error("空指针异常,{}", ex.getMessage());
return new EJson("500", "空指针异常了");
}
/**
* 系统异常 预期以外异常
* @param ex
* @return
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public EJson handleUnexpectedServer(Exception ex) {
logger.error("系统异常:", ex);
return new EJson("500", "系统发生异常,请联系管理员");
}
}定义控制器做个测试:
@RestController
@RequestMapping("/exception")
public class ExceptionController {
private static final Logger logger =
LoggerFactory.getLogger(ExceptionController.class);
@PostMapping("/test")
public EJson test(@RequestParam("name") String name,
@RequestParam("sex") String sex) {
logger.info("name:{}", name);
logger.info("sex:{}", sex);
return new EJson();
}
@RequestMapping("/null")
public EJson test1(String name,String sex){
if(sex.equals("男")){
logger.info("性别:{}",sex);
}
return new EJson();
}
@RequestMapping("/byzero")
public EJson test2(){
int result = 1 / 0;
return new EJson();
}
}通过Postman访问做个测试



