记录下系统异常到数据库中,方便查找定位,省去翻日志的麻烦。

将异常消息,产生时间,帧信息,操作信息等存入表中,方便查阅修改。适合小系统。大系统没试过。

在异常通知对象HandlerExceptionResolver解析完异常后,构建一个异常相关信息实体。存入表中。代码如下:

public class ExceptionAdvice implements HandlerExceptionResolver, Ordered {

    @AutowiredEnableNull
    private ExceptionLogHandler exceptionHandler;
    @AutowiredEnableNull
    private ExceptionViewCustomizer exceptionViewCustomizer;

    @Override
    public 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 {

    @Override
    public void handleExceptionLog(ExceptionWrapper exceptionWrapper) {
        ExceptionLog exceptionLog = new ExceptionLog();
        exceptionLog.setId(getLogId()); // 异常id
        exceptionLog.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()); // sessionId
        LoginUser 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);
    }

异常记录效果:
记录下系统异常到数据库中,方便查找定位,省去翻日志的麻烦。_第1张图片
记录下系统异常到数据库中,方便查找定位,省去翻日志的麻烦。_第2张图片
记录下系统异常到数据库中,方便查找定位,省去翻日志的麻烦。_第3张图片

你可能感兴趣的:(java)