package com.emergencyrepair.system.log; import com.emergencyrepair.common.audit.CurrentUserContext; import com.emergencyrepair.system.entity.SysErrorLog; import com.emergencyrepair.system.mapper.SysErrorLogMapper; import lombok.RequiredArgsConstructor; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; import java.io.PrintWriter; import java.io.StringWriter; import java.time.LocalDateTime; import java.util.List; /** * Persists unhandled server exceptions so administrators can inspect runtime bugs. */ @Component @RequiredArgsConstructor public class ErrorLogRecorder { private static final int MAX_MESSAGE_LENGTH = 2000; private static final int MAX_STACK_LENGTH = 60000; private final SysErrorLogMapper errorLogMapper; private final JdbcTemplate jdbcTemplate; public void record(Exception exception, HttpServletRequest request) { if (exception == null) { return; } try { String username = CurrentUserContext.get(); Long userId = resolveUserId(username); SysErrorLog log = new SysErrorLog(); log.setUserId(userId); log.setUserName(username); log.setNickName(resolveNickName(userId)); log.setModule(resolveModule(request)); log.setRequestMethod(request == null ? null : limit(request.getMethod(), 10)); log.setRequestUri(request == null ? null : limit(request.getRequestURI(), 500)); log.setExceptionType(limit(exception.getClass().getName(), 300)); log.setMessage(limit(resolveMessage(exception), MAX_MESSAGE_LENGTH)); log.setStackTrace(limit(stackTrace(exception), MAX_STACK_LENGTH)); log.setErrorTime(LocalDateTime.now()); errorLogMapper.insert(log); } catch (Exception ignored) { // Error logging must never interfere with the original error response. } } private Long resolveUserId(String username) { if (!StringUtils.hasText(username)) { return null; } List ids = jdbcTemplate.query( "SELECT USER_ID FROM CSICZB_ZB.SYS_USER WHERE USER_NAME = ? AND (DEL_FLAG = '0' OR DEL_FLAG IS NULL)", new Object[]{username}, (rs, rowNum) -> rs.getLong(1)); return ids.isEmpty() ? null : ids.get(0); } private String resolveNickName(Long userId) { if (userId == null) { return null; } List names = jdbcTemplate.query( "SELECT NICK_NAME FROM CSICZB_ZB.SYS_USER WHERE USER_ID = ?", new Object[]{userId}, (rs, rowNum) -> rs.getString(1)); return names.isEmpty() ? null : names.get(0); } private String resolveMessage(Exception exception) { String message = exception.getMessage(); return StringUtils.hasText(message) ? message : exception.getClass().getSimpleName(); } private String stackTrace(Exception exception) { StringWriter writer = new StringWriter(); exception.printStackTrace(new PrintWriter(writer)); return writer.toString(); } private String resolveModule(HttpServletRequest request) { if (request == null || !StringUtils.hasText(request.getRequestURI())) { return "其他"; } String uri = request.getRequestURI(); if (uri.startsWith("/api/faults") || uri.startsWith("/api/fault")) return "故障管理"; if (uri.startsWith("/api/work-orders") || uri.startsWith("/api/completion")) return "完工管理"; if (uri.startsWith("/api/acceptances")) return "完工验收"; if (uri.startsWith("/api/reports")) return "统计报表"; if (uri.startsWith("/api/system/users")) return "用户管理"; if (uri.startsWith("/api/system/roles")) return "角色管理"; if (uri.startsWith("/api/system/menu")) return "菜单管理"; if (uri.startsWith("/api/system/contractors")) return "承修单位管理"; if (uri.startsWith("/api/system")) return "系统管理"; return "其他"; } private String limit(String value, int maxLength) { if (value == null || value.length() <= maxLength) { return value; } return value.substring(0, maxLength); } }