package com.vci.starter.web.exception; import com.vci.starter.web.constant.TokenKeyConstant; import com.vci.starter.web.enumpck.ResultCodeEnum; import com.vci.starter.web.pagemodel.BaseResult; import com.vci.starter.web.util.LangBaseUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.beans.TypeMismatchException; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.util.CollectionUtils; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; 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 org.springframework.web.multipart.MultipartException; import javax.servlet.ServletException; import java.util.List; /** * 提供给spring mvc的统一的错误处理 * @author weidy */ @ControllerAdvice public class ExceptionAdviceHandler { /** * 日志对象 */ private Logger logger = LoggerFactory.getLogger(getClass()); /** * 当抓取到Throwable异常的时候,返回错误信息 * @param e 异常对象 * @return JSON对象,不论是树,列表,还是post的方法,前端都可以获取success,code和msg属性 */ @ResponseBody @ExceptionHandler(value = Throwable.class) public BaseResult defaultErrorHandler(Exception e){ BaseResult baseResult = this.handler(e); String traceId = MDC.get(TokenKeyConstant.TRACE_ID); baseResult.setTraceId(traceId); baseResult.setFinishTime(System.currentTimeMillis()); if(logger.isErrorEnabled()) { logger.error(baseResult.toString(), e); } return baseResult; } /** * 从异常上获取信息并返回 * @param e 异常对象 * @return JSON对象 */ private BaseResult handler(Exception e) { //不支持的http方法 if(e instanceof VciBaseException){ BaseResult baseResult = BaseResult.error(LangBaseUtil.getErrorMsg(e)); baseResult.setExceptionClassName(e.getClass().getName()); return baseResult; } else if (e instanceof HttpRequestMethodNotSupportedException) { return this.httpRequestMethodNotSupportedException(e); } else if (e instanceof HttpMessageNotReadableException) { return this.httpMessageNotReadableException(e); } else if (e instanceof TypeMismatchException || e instanceof MultipartException ||e instanceof ServletException) { return this.parameterException(e); } else if (e instanceof MethodArgumentNotValidException) { return this.methodArgumentNotValidException(e); } else if (e.getClass().getName().equalsIgnoreCase("org.springframework.jdbc.BadSqlGrammarException")) { return this.badSqlGrammarException(e); } else if(e instanceof BindException){ return this.bindException((BindException) e); }else { //其他的 return BaseResult.error(LangBaseUtil.getErrorMsg(e)); } } /** * 不支持的http方法 * @param e 异常的对象 * @return JSON对象 */ private BaseResult httpRequestMethodNotSupportedException(Exception e){ String message = "请开发人员检查,不支持的http方法"; BaseResult baseResult = BaseResult.error(message); baseResult.setExceptionClassName(e.getClass().getName()); return baseResult; } /** * 参数不能被读取 * @param e 异常对象 * @return json对象 */ private BaseResult httpMessageNotReadableException(Exception e){ String message = "请开发人员检查你请求的参数和参数的类型是否符合后台接口的要求"; BaseResult baseResult = BaseResult.makeResult(ResultCodeEnum.BAD_PARAM.code,message,null); baseResult.setExceptionClassName(e.getClass().getName()); return baseResult; } /** * 参数的类型异常 * @param e 异常对象 * @return json对象 */ private BaseResult parameterException(Exception e){ String message = "请开发人员检查你参数的类型"; BaseResult baseResult = BaseResult.makeResult(ResultCodeEnum.BAD_PARAM.code,message,null); baseResult.setExceptionClassName(e.getClass().getName()); return baseResult; } /** * 方法的参数无效 * @param e 异常状态 * @return json对象 */ private BaseResult methodArgumentNotValidException(Exception e){ StringBuffer buffer = new StringBuffer(); List list = ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors(); list.forEach(error -> { if (error instanceof FieldError) { buffer.append(((FieldError) error).getField()).append(":"); } buffer.append(error.getDefaultMessage()).append(","); }); buffer.append("请开发人员检查请求方法的参数"); BaseResult baseResult = BaseResult.makeResult(ResultCodeEnum.BAD_PARAM.code,buffer.toString(),null); baseResult.setExceptionClassName(e.getClass().getName()); return baseResult; } /** * 绑定参数错误 * @param e 异常状态 * @return json对象 */ private BaseResult bindException(BindException e){ String message = "请开发人员检查参数,参数绑定出现了错误"; List objectErrorList = e.getBindingResult().getAllErrors(); if(!CollectionUtils.isEmpty(objectErrorList)){ ObjectError objectError = objectErrorList.get(0); if(objectError instanceof FieldError){ FieldError fieldError = (FieldError) objectError; message = "[" + fieldError.getField() + "]" + fieldError.getDefaultMessage(); } } BaseResult baseResult = BaseResult.makeResult(ResultCodeEnum.BAD_PARAM.code,message,null); baseResult.setExceptionClassName(e.getClass().getName()); return baseResult; } /** * SQL语句错误 * @param e 异常对象 * @return json对象 */ private BaseResult badSqlGrammarException(Exception e){ String message = "请开发人员检查参数或者后台sql语句," + LangBaseUtil.getErrorMsg(e); BaseResult baseResult = BaseResult.error(message); baseResult.setExceptionClassName(e.getClass().getName()); return baseResult; } }