一、项目结构
二、全局异常
(1)启动类
package com.mgx;import com.mgx.common.dto.Result;
import com.mgx.utils.ErrorUtil;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;/*** @author mgx*/
@ControllerAdvice
@MapperScan("com.mgx.mapper")
@SpringBootApplication
public class SpringbootMgxApplication {public static void main(String[] args) {System.out.println("开始启动");SpringApplication.run(SpringbootMgxApplication.class, args);System.out.println("启动成功");}/*** 全局异常处理** @param exception Exception* @return R*/@ExceptionHandler(value = Exception.class)@ResponseBodypublic Result<String> defaultExceptionHandler(Exception exception) {return ErrorUtil.handleException(exception);}}
⚠️注意:@ControllerAdvice是@Controller 的增强版。@ControllerAdvice主要用来处理全局数据,一般搭配@ExceptionHandler、@ModelAttribute以及@InitBinder使用。全局异常处理,将配合@ExceptionHandler定义全局异常捕获机制。
(2)CuzException类
package com.mgx.exception;import com.mgx.common.enums.MsgCode;/*** @author mgx*/
public class CuzException extends RuntimeException {private MsgCode msgCode;@Overridepublic String getMessage() {return msgCode.getMsg();}public CuzException(MsgCode msgCode) {this.msgCode = msgCode;}public MsgCode getMsgCode() {return msgCode;}public void setMsgCode(MsgCode msgCode) {this.msgCode = msgCode;}
}
(3)ErrorUtil
package com.mgx.utils;import com.mgx.common.dto.Result;
import com.mgx.common.enums.MsgCode;
import com.mgx.exception.CuzException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
import java.util.Enumeration;/*** @author mgx*/
@Slf4j
public class ErrorUtil {private static Result<String> getParamErrorMessage(MethodArgumentNotValidException e) {//按需重新封装需要返回的错误信息StringBuilder stringBuilder = new StringBuilder();//解析原错误信息,封装后返回,此处返回非法的字段名称,错误信息for (FieldError error : e.getBindingResult().getFieldErrors()) {if (stringBuilder.length() > 1) {stringBuilder.append("; ");}stringBuilder.append(error.getDefaultMessage());}return Result.failure().code(MsgCode.Code_500.getCode()).message(stringBuilder.toString()).build();}public static Result<String> handleException(Exception exception) {try {// 打印全部异常信息log.error("系统异常:", exception);throw exception;} catch (CuzException e) {MsgCode msgCode = e.getMsgCode();return Result.failure().code(msgCode == null ? MsgCode.Code_500.getCode() : msgCode.getCode()).message(msgCode == null ? e.getMessage() : msgCode.getMsg()).build();} catch (IllegalAccessException e) {return Result.failure().code(MsgCode.Code_503.getCode()).build();} catch (MethodArgumentNotValidException e) {printException();return getParamErrorMessage(e);} catch (HttpMessageNotReadableException e) {printException();return Result.failure().code(MsgCode.Code_2002.getCode()).build();} catch (HttpRequestMethodNotSupportedException e) {return Result.failure().code(MsgCode.Code_2004.getCode()).build();} catch (MissingServletRequestParameterException e) {return Result.failure().code(MsgCode.Code_2003.getCode()).build();} catch (IllegalArgumentException e) {return Result.failure().code(MsgCode.Code_2001.getCode()).build();} catch (BindException e) {return Result.failure().code(MsgCode.Code_500.getCode()).message(e.getAllErrors().get(0).getDefaultMessage()).build();} catch (SQLException | DataIntegrityViolationException | BadSqlGrammarException e) {return Result.failure().code(MsgCode.Code_2005.getCode()).build();} catch (Exception e) {return Result.failure().code(MsgCode.Code_500.getCode()).build();}}private static void printException(){ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if(attributes == null){return;}HttpServletRequest request = attributes.getRequest();// 记录下请求内容log.error("URL : " + request.getRequestURL().toString());log.error("HTTP_METHOD : " + request.getMethod());log.error("IP : " + request.getRemoteAddr());Enumeration<String> enu = request.getParameterNames();while (enu.hasMoreElements()) {String name = enu.nextElement();log.error("name:{},value:{}", name, request.getParameter(name));}}
}
三、测试
(1)下面的SQL明显是错误的,那么我们调用含该SQL的接口,看会返给我们什么
接口调用测试
(2)没有该数据,接口逻辑中抛异常,看会返给我们什么
接口调用测试
(3)自定义SQL语法错误的全局异常,与返回一致,全局异常处理成功。