springmvc学习指南 之---第30篇 异常的全局处理
对于异常的处理,现在写的这个小项目,每次都在调用方法加上一个try catch(),上午在写dongabo商城项目就发现他的调用方法时没有trycatch的,那依据经验他就是有全局处理@ControllerAdvice
那么对于全局处理的布局应该怎么写呢?这就要依据会出现的异常情况,有以下异常情况
- 自定义异常 BusinessException
- 方法参数校验@NotNull 的校验异常,分两种情况一种是Post请求 一种是Get请求
- 参数json解析异常,比如说DTO中的成员变量类型是Integer,参数中是String,那么就解析异常,或者 post 请求,没有携带参数
那么就会对应相应的异常处理
- 自定义简单 @ExceptionHandler({BusinessException.class})
- 方法参数分给POST 用 @ExceptionHandler(MethodArgumentNotValidException.class)
- 方法参数分配GET,校验单个参数,用 @ExceptionHandler(HttpMessageConversionException.class)
- json解析异常使用,@ExceptionHandler(HttpMessageConversionException.class)
那么就粘贴一下dongbao的全局异常处理代码
package com.msb.dongbao.portal.exception; import com.google.common.collect.Lists; import com.msb.dongbao.common.base.dto.ResultWrapper; import com.msb.dongbao.common.base.enums.StateCodeEnum; import com.msb.dongbao.common.base.exception.BusinessException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.converter.HttpMessageConversionException; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import java.util.List; /** * 统一异常处理 */ @Slf4j @ControllerAdvice public class GlobalExceptionAdvice { @ResponseBody @ExceptionHandler({BusinessException.class}) public ResultWrapper bizException(BusinessException e) { log.error("出现异常:{}", e); return ResultWrapper.builder().code(e.getErrorCode()).msg(e.getMessage()).build(); } @ResponseBody @ExceptionHandler(MethodArgumentNotValidException.class) public ResultWrapper methodArgumentNotValidException(MethodArgumentNotValidException e) { log.error("出现异常:{}", e); List<ObjectError> errors = e.getBindingResult().getAllErrors(); // 已经设置了快速失败,可以默认取首个错误即可 StringBuffer sb = new StringBuffer(); List<String> errorArr = Lists.newArrayList(); for (ObjectError error : errors) { if (error instanceof FieldError) { FieldError fieldError = (FieldError) error; errorArr.add(fieldError.getField() + fieldError.getDefaultMessage()); } else { errorArr.add(error.getObjectName() + error.getDefaultMessage()); } } String errMsg = String.join(";", errorArr.toArray(new String[]{})); return ResultWrapper.builder().code(StateCodeEnum.METHOD_ARGUMENT_NOT_VALID.getCode()).msg(errMsg).build(); } @ResponseBody @ExceptionHandler(ConstraintViolationException.class) public ResultWrapper constraintViolationException(ConstraintViolationException e) { // 拦截单个参数校验异常捕获 log.error("出现异常:{}", e); // @RequestParam 参数校验失败 StringBuffer sb = new StringBuffer(); List<String> errorArr = Lists.newArrayList(); for (ConstraintViolation constraint : e.getConstraintViolations()) { errorArr.add(constraint.getInvalidValue() + "非法" + constraint.getMessage()); } String errMsg = String.join(";", errorArr.toArray(new String[]{})); return ResultWrapper.builder().code(StateCodeEnum.CONSTRAINT_VIOLATION.getCode()).msg(errMsg).build(); } @ResponseBody @ExceptionHandler(Exception.class) public ResultWrapper exception(Exception e) { log.error("出现异常:{}", e); return ResultWrapper.builder().code(StateCodeEnum.ERROR.getCode()).msg(e.getMessage()).build(); } /** * 参数错误类型转换 * * @param e * @return */ @ResponseBody @ExceptionHandler(HttpMessageConversionException.class) public ResultWrapper parameterTypeConvertException(HttpMessageConversionException e) { return ResultWrapper.builder().code(StateCodeEnum.ERROR.getCode()).msg(e.getMessage()).build(); } }