1、全局异常处理

import lombok.extern.slf4j.Slf4j;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
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.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 全局异常处理器
 *
 *
 */
@Slf4j
@ControllerAdvice
public class AdminGlobalExceptionHandler {

    @ExceptionHandler(value = DecorateException.class)
    @ResponseBody
    public SvResult<String> decorateException(HttpServletRequest req, HttpServletResponse resp, DecorateException e) {
        log.error("异常消息:{}, msgVariableArr={}", e.getMessage(), e.getMsgVariableArr(), e);
        SvResult<String> result = new SvResult<>(e.getCode(), e.getMessage());
        if(e.getMsgVariableArr() != null && i18nReplaceService != null){
            result.setMsg(String.format(e.getMessage(), e.getMsgVariableArr()));
            result.setExt(new HashMap<>(2));
            result.getExt().put(SvResultConstant.EXT_KEY_MSG_VRIABLE_ARR, e.getMsgVariableArr());
        }

        return result;
    }
// 处理单个参数校验失败抛出的异常
    @ResponseBody
    @ExceptionHandler(ConstraintViolationException.class)
    public SvResult<String> constraintViolationExceptionHandler(ConstraintViolationException e) {
        log.error("[PARAM] handle param not valid exception, msg:{}", e.getMessage(), e);
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        String error = constraintViolations.stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.joining(","));
        log.error("constraintViolationExceptionHandler, {}", error);

        return new SvResult<>(SvResultEnum.SYSTEM_ERROR);
    }

    // 处理 form 方式调用接口校验失败抛出的异常
    @ResponseBody
    @ExceptionHandler(BindException.class)
    public SvResult<String> bindExceptionHandler(BindException e) {
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        String errorMsg = objectError.getDefaultMessage();
        String field = e.getBindingResult().getFieldError().getField();
        log.error("[PARAM] handle param not valid exception, field={} msg={}", field, errorMsg, e);
        return new SvResult<>(SvResultEnum.SYSTEM_ERROR);
    }

    // 处理 post 方式提交的 json 数据的参数验证抛出的异常
    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public SvResult<String> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        String errorMsg = objectError.getDefaultMessage();
        String field = e.getBindingResult().getFieldError().getField();
        log.error("[PARAM] handle param not valid exception, field={} msg={}", field, errorMsg, e);
        return new SvResult<>(SvResultEnum.SYSTEM_ERROR);
    }
// http方法不支持的异常
    @ResponseBody
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public SvResult<String> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException exception) {

        log.error("[SYSTEM] handle HttpRequestMethodNotSupportedException,msg: {}", exception.getMessage(), exception);
        String message = MessageFormatter.format("当前接口的HTTP请求不支持 {} 方法!", exception.getMethod()).getMessage();
        log.error("handleHttpRequestMethodNotSupportedException {}", message);
        return new SvResult<>(SvResultEnum.CLIENT_ERROR);
    }


    // 兜底异常拦截
    @ResponseBody
    @ExceptionHandler(Throwable.class)
    public SvResult<String> allHandler(Throwable e) {
        log.error("全局异常(系统异常),异常消息:{},异常类:", e.getMessage(), e);
        return new SvResult<>(SvResultEnum.SYSTEM_ERROR);
    }
}

2、全局异常处理

package com.example.demo.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public Object handleException(Exception ex) {
        if (isJsonRequest()) {
            // 返回JSON格式的错误信息
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal Server Error");
        } else {
            // 返回错误页面
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("error");
            modelAndView.addObject("errorMessage", "Internal Server Error");
            return modelAndView;
        }
    }


    private boolean isJsonRequest() {
        // 判断请求的Accept头部信息是否包含JSON类型
        String acceptHeader = getRequest().getHeader("Accept");
        log.warn("accept:"+acceptHeader);
        return acceptHeader != null && acceptHeader.contains(MediaType.APPLICATION_JSON_VALUE);
    }

    private HttpServletRequest getRequest() {
        // 获取当前请求的HttpServletRequest对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return requestAttributes.getRequest();
    }
}

 3、全局异常处理

 

import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.omg.CORBA.portable.ApplicationException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
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.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.stream.Collectors;

/**
 * @Description: controller不同类型异常统一处理类
 * @Date: 2020/11/5 8:43 下午
 */
@Log4j2
@ControllerAdvice
public class ErrorControllerAdvice {

    /**
     * 处理应用层参数错误
     */
    @ExceptionHandler(value = ApplicationException.class)
    @ResponseBody
    public ResultModel<String> applicationException(HttpServletRequest req, HttpServletResponse resp, ApplicationException e) {
        log.error("applicationException: ", e);
        return ResultModel
                .failure(ResultCodeEnum.INVALID_PARA.getCode(), ResultCodeEnum.INVALID_PARA.getDesc());
    }

    /**
     * 处理controller中直接在参数中添加Validation注解的异常
     */
    @ExceptionHandler(value = ValidationException.class)
    @ResponseBody
    public ResultModel<String> constraintViolationException(HttpServletRequest req, HttpServletResponse resp,
                                                            ConstraintViolationException e) {
        log.error("ConstraintViolationException detail : ", e);
        String messages = e.getConstraintViolations().stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.toList()).toString();
        return ResultModel.failure(ResultCodeEnum.INVALID_PARA.getCode(), messages);
    }

    /**
     * 处理controller中直接在参数中添加Validation注解的异常
     */
    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public ResultModel<String> bindException(HttpServletRequest req, HttpServletResponse resp, BindException e) {
        log.error("BindException detail:", e);
        return ResultModel
                .failure(ResultCodeEnum.INVALID_PARA.getCode(), ResultCodeEnum.INVALID_PARA.getDesc());
    }

    /**
     * 处理controller中参数实体带Validation注解的异常
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseBody
    public ResultModel<String> methodArgumentNotValidException(HttpServletRequest req, HttpServletResponse resp,
                                                               MethodArgumentNotValidException e) {
        log.error("MethodArgumentNotValidException detail : ", e);
        String messages = e.getBindingResult().getAllErrors().stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.toList()).toString();
        return ResultModel.failure(ResultCodeEnum.INVALID_PARA.getCode(), messages);
    }

    /**
     * 统一处理非法参数异常
     */
    @ExceptionHandler(value = IllegalArgumentException.class)
    @ResponseBody
    public ResultModel<String> illegalArgumentException(HttpServletRequest req, HttpServletResponse resp, Exception e) {
        log.error("IllegalArgumentException detail: ", e);
        return ResultModel.failure(ResultCodeEnum.INVALID_PARA.getCode(), ResultCodeEnum.INVALID_PARA.getDesc());
    }

    @ExceptionHandler(value = BizBaseException.class)
    @ResponseBody
    public ResultModel<String> bizException(HttpServletRequest req, HttpServletResponse resp, BizBaseException e) {
        log.error("bizException,code=[{}],msg=[{}]:", e.getCode(), e.getMessage(), e);
        return ResultModel.failure(e.getCode(), e.getMessage());
    }

    /**
     * 统一处理controller中Exception异常
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResultModel<String> exception(HttpServletRequest req, HttpServletResponse resp, Exception e) {
        log.error("Global Exception detail: ", e);
        if (e instanceof HttpMessageNotReadableException) {
            return ResultModel.failure(ResultCode.SC_BAD_REQUEST, "参数错误");
        }
        return ResultModel.failure(ResultCodeEnum.INTERNAL_SERVER_ERROR.getCode(), ResultCodeEnum.INTERNAL_SERVER_ERROR.getDesc());
    }

}