SpringBoot 统一异常处理
2018-10-10 本文已影响0人
weisen
一、什么是异常处理
异常(exception) 是程序运行过程中发生的事件, 该事件可以中断程序指令的正常执行流程.
1当Java程序运行时出现问题时,系统会自动检测到该错误,并立即生成一个与该错误对应的异常对象
2:然后把该异常对象提交给JAVA虚拟机
3:JAVA虚拟机会自动寻找相应的处理代码来处理这个异常,如果没有找到,则程序终止
4:程序员可以自己编写代码来扑捉可能出现的异常,并编写代码来处理相应的异常.
二、实现方法
1、通过@ControllerAdvice
和@ExceptionHandler
实现处理controller层的异常
@ControllerAdvice
@ResponseBody //表示返回的对象,Spring会自动把该对象进行json转化,最后写入到Response中。
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class) //表示让Spring捕获到所有抛出的SignException异常,并交由这个被注解的方法处理。
@ResponseStatus(HttpStatus.BAD_REQUEST) //表示设置状态码。
String handleException(){
return "Exception Deal!";
}
}
这样方法 handleException() 就会处理所有 Controller 层抛出的 Exception 及其子类的异常。
又因为service层的异常会抛出到controller层,所以service层抛出的异常也会被handleException处理.
2、异常是处理了,但是希望前端页面能够看到统一的返回结果,如下:
{
"code": "33316",
"msg": "This is NullPointerException.",
"data": null
}
创建统一的JSON返回对象,code:消息类型,message:消息内容,url:请求的url,data:请求返回的数据
如创建类ResponseDto,无论正确的返回还是异常返回,都返回这个类对象
public class ResponseDto<T> {
//错误码
private String code;
//提示信息
private String msg;
//具体的内容
private T data;
public ResponseDto() {
}
public ResponseDto(String code, String msg) {
this.code = code;
this.msg = msg;
this.data = null;
}
//getter和setter方法。。。
}
controller中,都返回这个对象,如下:
@RequestMapping(value = "/getUser")
public ResponseDto getUser(String id){
ResponseDto dto = new ResponseDto();
dto.setCode("10000");
dto.setMsg("操作成功");
dto.setData(userServiceImpl.getUser(id));
return dto;
}
@RequestMapping(value = "/listUser")
public ResponseDto getUser(){
ResponseDto dto = new ResponseDto();
dto.setCode("10000");
dto.setMsg("操作成功");
dto.setData(userServiceImpl.listUser());
return dto;
}
看到有重复代码,那就需要将重复代码提取出来,写一个工具类ResultUtil,在类中定义方法
public static ResponseDto success(Object object){
ResponseDto result = new ResponseDto();
result.setCode("10000");
result.setMsg("操作成功");
result.setData(object);
return result;
}
这样controller中的方法就可以改为:
@RequestMapping(value = "/getUser")
public ResponseDto getUser(String id){
return ResultUtil.success(userServiceImpl.getUser(id));
}
@RequestMapping(value = "/listUser")
public ResponseDto getUser(){
return ResultUtil.success(userServiceImpl.listUser());
}
异常处理的handleException方法也要做出对应的修改,这样处理异常的返回才能是对应的格式
@ExceptionHandler(Exception.class) //表示让Spring捕获到所有抛出的SignException异常,并交由这个被注解的方法处理。
@ResponseBody //表示返回的对象,Spring会自动把该对象进行json转化,最后写入到Response中。
@ResponseStatus(HttpStatus.BAD_REQUEST) //表示设置状态码。
String handleException(){
logger.error("Exception Deal!") ;
return ResultUtil.error(CommonConstant.RESPONSE_CODE_UNKNOW_EXCEPTION,e.getMessage());
}
三、对参数进行校验。
//添加全局异常处理流程,根据需要设置需要处理的异常,本文以MethodArgumentNotValidException为例
@ExceptionHandler(value=MethodArgumentNotValidException.class)
public Object MethodArgumentNotValidHandler(HttpServletRequest request,
MethodArgumentNotValidException exception) {
List<ObjectError> errors =exception.getBindingResult().getAllErrors();
StringBuffer errorMsg=new StringBuffer();
errors.stream().forEach(x -> errorMsg.append(x.getDefaultMessage()).append(";"));
logger.error("---MethodArgumentNotValidException Handler--- ERROR: {}", errorMsg.toString());
respBean.setRespCode(RespCodeConstant.VALIDATE_ERROR);
respBean.setRespDesc(RespCodeConstant.VALIDATE_ERROR_DESC);
respBean.setRespData(errorMsg.toString());
return respBean;
}
在contorller中的方法中添加@Validated
校验
public RespBean getWeeklyVisitTrend(@RequestBody @Validated ParamsDto dto) {
在ParamsDto 里面的字段添加上具体的校验,以及出错时打印的信息
@NotBlank(message = "params.dto.begin.date.null")
private String begin_date;