将异常消息,产生时间,帧信息,操作信息等存入表中,方便查阅修改。适合小系统。大系统没试过。
在异常通知对象HandlerExceptionResolver解析完异常后,构建一个异常相关信息实体。存入表中。代码如下:
public class ExceptionAdvice implements HandlerExceptionResolver, Ordered {@AutowiredEnableNullprivate ExceptionLogHandler exceptionHandler;@AutowiredEnableNullprivate ExceptionViewCustomizer exceptionViewCustomizer;@Overridepublic ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) {ModelAndView mv = new ModelAndView();FastJsonJsonView jsonView = new FastJsonJsonView();boolean isMethod = handler instanceof HandlerMethod;if (!isMethod) {jsonView.addStaticAttribute("code", 500);jsonView.addStaticAttribute("message", "访问异常" + request.getRequestURI());mv.setView(jsonView);ZYResponseUtils.allowOrigin(response, request);return mv;}// 格式化记录日志并打印prettyError(ex, request);Integer code = Resp.R_500.getCode();String message;String data = ex.getClass().getSimpleName();if (ex instanceof LocalException) {LocalException localException = (LocalException) ex;code = localException.getCode();message = localException.getMessage();} if (ex instanceof NullPointerException) {message = "空数据异常,请联系系统管理员";} else if (ex instanceof BadSqlGrammarException) {message = "数据语法有误,请联系管理员";} else if (ex instanceof SQLException) {message = "数据库异常,请联系管理员";} else if (ex instanceof DataIntegrityViolationException) {message = "数据库异常,请联系管理员";} else if (ex instanceof UncategorizedSQLException) {message = "数据库异常,请联系管理员";}else if (ex instanceof DuplicatioKeyException) {message = "唯一键冲突,请联系管理员";} else if (ex instanceof MyBatisSystemException) {message = "数据库异常,请联系管理员";} else if (ex instanceof NestedServletException) {NestedServletException ne = (NestedServletException) ex;message = "类加载异常或静态块逻辑执行异常!";data = ne.getMessage();} else if (ex instanceof RuntimeException) {RuntimeException localException = (RuntimeException) ex;message = localException.getMessage();} else {switch (response.getStatus()) {case 400:code = Resp.R_400.getCode();message = "参数异常,请检查您的参数";data = "请比对您的参数,如接收的类型、日期格式检查或麻烦您友善的找后台开发解决问题,谢谢!!";break;case 403:code = Resp.R_403.getCode();message = "您没有访问本接口的权限";data = "麻烦您友善的找后台开发解决问题,谢谢!!";break;case 404:code = Resp.R_404.getCode();message = "您所请求的接口并没有找到";data = "请检查您的开发文档或麻烦您友善的找后台开发解决问题,谢谢!!";break;case 405:code = Resp.R_405.getCode();message = "您的访问方式GET/POST等不符合接口定义的方法";data = "请检查您的开发文档或麻烦您友善的找后台开发解决问题,谢谢!!";break;default:code = Resp.R_500.getCode();message = getExceptionMessage(ex);data = "麻烦您友善的找后台开发解决问题,谢谢!!";break;}}ExceptionWrapper exceptionWrapper = new ExceptionWrapper();exceptionWrapper.setRequest(request); // 请求对象exceptionWrapper.setResponse(response); // 响应对象exceptionWrapper.setMessage(message); // 响应消息exceptionWrapper.setCode(code); // 响应码exceptionWrapper.setHandler((HandlerMethod) handler);exceptionWrapper.setEx(ex); // 异常if (null != exceptionHandler) {// 记录异常日志exceptionHandler.handleExceptionLog(exceptionWrapper);}if (null != exceptionViewCustomizer) {// 自定义异常视图View view = exceptionViewCustomizer.customize(exceptionWrapper);mv.setView(view);} else {// 默认视图jsonView.addStaticAttribute("code", code);jsonView.addStaticAttribute("message", null == message ? Resp.R_500.getMessage() : message);jsonView.addStaticAttribute("data", null != data ? data : "");mv.setView(jsonView);}return mv;}
public class ExceptionLogRecordProcessor implements ExceptionLogHandler {@Overridepublic void handleExceptionLog(ExceptionWrapper exceptionWrapper) {ExceptionLog exceptionLog = new ExceptionLog();exceptionLog.setId(getLogId()); // 异常idexceptionLog.setCaseLookTime(ZYDateUtils.formart(new Date(), ZYDateUtils.YYYY_MM_DD_HH_MM_SS)); // 异常发生时间Exception ex = exceptionWrapper.getEx();exceptionLog.setCaseMessage(ex.getMessage()); // 异常引发消息exceptionLog.setShowMessage(exceptionWrapper.getMessage()); // 返回页面消息exceptionLog.setUrl(ZYRequestUtils.getApiFromRequest(exceptionWrapper.getRequest())); // 访问路径exceptionLog.setCode(exceptionWrapper.getCode()); // 异常码exceptionLog.setExceptionClass(ex.getClass().getName());// 异常类名exceptionLog.setSessionId(ZYUserHelper.getLoginSessionId()); // sessionIdLoginUser loginUser= ZYUserHelper.getLoginUser();exceptionLog.setUserId(loginUser.getId()); // 访问人exceptionLog.setUserName(loginUser.getUserName()); // 访问用户StackTraceElement[] stackTraces = ex.getStackTrace();List<String> stackInfos = new ArrayList<>();// 只挑选与项目大目录有关的类的栈信息for (StackTraceElement stackTrace : stackTraces) {String className = stackTrace.getClassName();if (className.contains("xxx")) {stackInfos.add(toStackMessage(stackTrace));}}// 没有获取到取帧信息的前10个差不多了if (stackInfos.isEmpty()) {int i = 0;for (StackTraceElement stackTrace : stackTraces) {if (i < 10) {stackInfos.add(toStackMessage(stackTrace));}i++;}}exceptionLog.setStackInfos(ZYStrUtils.join(stackInfos, "\r\n"));// 记录异常至队列或直接存表,按七天一张表存入动态表中LoggingBootstrap.putExceptionLog(exceptionLog);}
异常记录效果: