package com.thhy.general.exception; import com.alibaba.fastjson.JSONObject; import com.github.pagehelper.util.StringUtil; import com.thhy.general.common.BasicMessage; import com.thhy.general.utils.UUIDUtils; import com.thhy.general.common.BasicResult; import com.thhy.general.common.BasicStatus; import feign.FeignException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.io.StringWriter; /** * @Author: zhang_xiao_bo * @Date: 2022/3/22 16:43 * @description: controller 监听异常配置 */ @RestControllerAdvice public class ExceptionController { private static Logger log = LoggerFactory.getLogger(ExceptionController.class); @ExceptionHandler(Exception.class) public BasicResult handleException(HttpServletRequest request, HttpServletResponse response, Exception exception) { //如果有框架把自定义异常又封装成了系统异常,则需要重新指向自定义处理流程 if(exception instanceof BasicException){ return handleBusinessException(request,response,(BasicException)exception); } if(exception instanceof FeignException){ return handleFeignException(request,response,(FeignException) exception); } if(exception instanceof MethodArgumentNotValidException){ System.out.println("ssss"); } //异常日志ID String errorLogId= UUIDUtils.create(); //日志堆栈 String stackTrace=getInfo(exception); //装配异常消息,异步发送 ExceptionMessage exceptionMessage=new ExceptionMessage(); //exceptionMessage.setAddress(serverConfig.getUrl()); exceptionMessage.setRequestUri(request.getRequestURI()); exceptionMessage.setErrorLogId(errorLogId); exceptionMessage.setStatusCode(BasicStatus.ERROR.statusCode()); exceptionMessage.setStatusMsg(BasicStatus.ERROR.statusMsg()); exceptionMessage.setStackTraceMsg(stackTrace); log.error("请求: " + request.getRequestURI() + " 引起异常:"); log.error("日志编码:"+exceptionMessage.getErrorLogId()); log.error("状态码:"+exceptionMessage.getStatusCode()); log.error("状态说明:"+exceptionMessage.getStatusMsg()); log.error(stackTrace); response.setStatus(HttpStatus.OK.value()); return new BasicResult(false,BasicStatus.ERROR,new JSONObject()); } /** * 自定义业务异常处理 * @param request * @param response * @param exception * @return */ @ExceptionHandler(BasicException.class) public BasicResult handleBusinessException(HttpServletRequest request, HttpServletResponse response, BasicException exception) { //日志堆栈,方法体中主动抛出的,还是catch中抛出的,二者不同 String stackTrace= StringUtil.isEmpty(exception.getStackTraceMsg())?getInfo(exception):exception.getStackTraceMsg(); //装配异常消息,异步发送 ExceptionMessage exceptionMessage=new ExceptionMessage(); //exceptionMessage.setAddress(serverConfig.getUrl()); exceptionMessage.setRequestUri(request.getRequestURI()); exceptionMessage.setErrorLogId(exception.getErrorLogId()); exceptionMessage.setStatusCode(exception.getBasicStatus().statusCode()); exceptionMessage.setStatusMsg(exception.getBasicStatus().statusMsg()); exceptionMessage.setStackTraceMsg(stackTrace); log.error("请求: " + request.getRequestURI() + " 引起异常:"); log.error("日志编码:"+exception.getErrorLogId()); log.error("状态码:"+exception.getBasicStatus().statusCode()); log.error("状态说明:"+exception.getBasicStatus().statusMsg()); log.error(stackTrace); response.setStatus(HttpStatus.OK.value()); return new BasicResult(false,exception.getBasicStatus(),new JSONObject()); } /** * 自定义业务异常处理 * @param request * @param response * @param exception * @return */ @ExceptionHandler(FeignException.class) public BasicResult handleFeignException(HttpServletRequest request, HttpServletResponse response, FeignException exception) { //日志堆栈,方法体中主动抛出的,还是catch中抛出的,二者不同 /*String stackTrace= StringUtils.isBlank(exception.getStackTraceMsg())?getInfo(exception):exception.getStackTraceMsg(); //装配异常消息,异步发送 ExceptionMessage exceptionMessage=new ExceptionMessage(); exceptionMessage.setAddress(serverConfig.getUrl()); exceptionMessage.setRequestUri(request.getRequestURI()); exceptionMessage.setErrorLogId(exception.getErrorLogId()); exceptionMessage.setStatusCode(exception.getBasicStatus().statusCode()); exceptionMessage.setStatusMsg(exception.getBasicStatus().statusMsg()); exceptionMessage.setStackTraceMsg(stackTrace); log.error("请求: " + request.getRequestURI() + " 引起异常:"); log.error("日志编码:"+exception.get()); log.error("状态码:"+exception.getBasicStatus().statusCode()); log.error("状态说明:"+exception.getBasicStatus().statusMsg()); log.error(stackTrace);*/ String feignUrl = exception.request().url(); String suff = feignUrl.split("//")[1]; String serviceName = suff.substring(0,suff.indexOf("/")); String statusMsg = "feign调用"+serviceName+"出现异常"; if(exception.status()==503){ statusMsg=serviceName+"服务可能下线"; } response.setStatus(HttpStatus.OK.value()); return new BasicResult(false,new BasicMessage("00900",statusMsg),exception.getMessage()); } @ExceptionHandler(MethodArgumentNotValidException.class) public BasicResult handleValidException(HttpServletRequest request, HttpServletResponse response, BasicException exception) { //日志堆栈,方法体中主动抛出的,还是catch中抛出的,二者不同 String stackTrace= StringUtil.isEmpty(exception.getStackTraceMsg())?getInfo(exception):exception.getStackTraceMsg(); //装配异常消息,异步发送 ExceptionMessage exceptionMessage=new ExceptionMessage(); //exceptionMessage.setAddress(serverConfig.getUrl()); exceptionMessage.setRequestUri(request.getRequestURI()); exceptionMessage.setErrorLogId(exception.getErrorLogId()); exceptionMessage.setStatusCode(exception.getBasicStatus().statusCode()); exceptionMessage.setStatusMsg(exception.getBasicStatus().statusMsg()); exceptionMessage.setStackTraceMsg(stackTrace); log.error("请求: " + request.getRequestURI() + " 引起异常:"); log.error("日志编码:"+exception.getErrorLogId()); log.error("状态码:"+exception.getBasicStatus().statusCode()); log.error("状态说明:"+exception.getBasicStatus().statusMsg()); log.error(stackTrace); response.setStatus(HttpStatus.OK.value()); return new BasicResult(false,exception.getBasicStatus(),new JSONObject()); } /** * 获取异常的堆栈信息 * * @param t * @return */ public String getInfo(Throwable t) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); try { t.printStackTrace(pw); return sw.toString(); } finally { pw.close(); } } }