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();
    }

}
原文地址:https://www.cnblogs.com/zytcomeon/p/15516615.html