springboot 全局异常处理类

发布时间 2023-07-18 10:30:32作者: 蜗牛无敌

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