소스 검색

fix: ErrorLoggingFilter 捕获链式异常并记录500日志; DimensionWeightController 参数校验; GlobalExceptionHandler 兜底异常处理

Xiaogang Liao 1 개월 전
부모
커밋
d9a4b2132b

+ 91 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/ErrorLoggingFilter.java

@@ -0,0 +1,91 @@
+package com.etotem.cfc.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+@Order(Integer.MIN_VALUE + 1)
+public class ErrorLoggingFilter implements Filter {
+
+    private static final Logger log = LoggerFactory.getLogger(ErrorLoggingFilter.class);
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
+
+        HttpServletRequest req = (HttpServletRequest) request;
+        HttpServletResponse resp = (HttpServletResponse) response;
+
+        if (!shouldLog(req)) {
+            chain.doFilter(request, response);
+            return;
+        }
+
+        StatusExposingHttpServletResponse wrapped = new StatusExposingHttpServletResponse(resp);
+        Throwable caught = null;
+
+        try {
+            chain.doFilter(request, wrapped);
+        } catch (Throwable t) {
+            caught = t;
+            log.error("HTTP {} {} {} - 异常: {} - 返回 500",
+                    req.getMethod(), req.getRequestURI(),
+                    req.getQueryString() != null ? "?" + req.getQueryString() : "",
+                    t.getClass().getName() + ": " + t.getMessage());
+            // 继续传播,让 Spring 处理异常
+            throw t;
+        }
+
+        int status = wrapped.getStatus();
+
+        if (caught == null && status >= 500) {
+            log.error("HTTP {} {} {} - 返回 {}", req.getMethod(), req.getRequestURI(),
+                    req.getQueryString() != null ? "?" + req.getQueryString() : "", status);
+        } else if (caught == null && status >= 400) {
+            log.warn("HTTP {} {} {} - 返回 {}", req.getMethod(), req.getRequestURI(),
+                    req.getQueryString() != null ? "?" + req.getQueryString() : "", status);
+        }
+    }
+
+    private boolean shouldLog(HttpServletRequest req) {
+        String uri = req.getRequestURI();
+        return uri.startsWith("/api/") && !"OPTIONS".equals(req.getMethod());
+    }
+
+    private static class StatusExposingHttpServletResponse extends javax.servlet.http.HttpServletResponseWrapper {
+        private int status = 200;
+
+        public StatusExposingHttpServletResponse(HttpServletResponse response) {
+            super(response);
+        }
+
+        @Override
+        public void setStatus(int code) {
+            this.status = code;
+            super.setStatus(code);
+        }
+
+        @Override
+        public void sendError(int code) throws IOException {
+            this.status = code;
+            super.sendError(code);
+        }
+
+        @Override
+        public void sendError(int code, String message) throws IOException {
+            this.status = code;
+            super.sendError(code, message);
+        }
+
+        public int getStatus() {
+            return status;
+        }
+    }
+}

+ 10 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/GlobalExceptionHandler.java

@@ -1,14 +1,24 @@
 package com.etotem.cfc.config;
 
 import com.etotem.cfc.common.Result;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
 
 @RestControllerAdvice
 public class GlobalExceptionHandler {
 
+    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
     @ExceptionHandler(IllegalArgumentException.class)
     public Result<Void> handleIllegalArgumentException(IllegalArgumentException e) {
         return Result.error(400, e.getMessage());
     }
+
+    @ExceptionHandler(Exception.class)
+    public Result<Void> handleException(Exception e) {
+        log.error("未捕获异常: {} - {}", e.getClass().getName(), e.getMessage(), e);
+        return Result.error("服务器内部错误: " + e.getMessage());
+    }
 }

+ 18 - 4
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/DimensionWeightController.java

@@ -21,9 +21,18 @@ public class DimensionWeightController {
 
     @PostMapping("/save")
     public Result<Void> save(@RequestBody Map<String, Object> params) {
-        String targetType = params.get("targetType").toString();
-        Long targetId = Long.valueOf(params.get("targetId").toString());
+        Object targetTypeObj = params.get("targetType");
+        Object targetIdObj = params.get("targetId");
+        if (targetTypeObj == null || targetIdObj == null) {
+            return Result.error("targetType 和 targetId 不能为空");
+        }
+        String targetType = targetTypeObj.toString();
+        Long targetId = Long.valueOf(targetIdObj.toString());
+        @SuppressWarnings("unchecked")
         List<Map<String, Object>> weightMaps = (List<Map<String, Object>>) params.get("weights");
+        if (weightMaps == null || weightMaps.isEmpty()) {
+            return Result.error("weights 不能为空");
+        }
         List<DimensionWeight> weights = weightMaps.stream().map(m -> {
             DimensionWeight w = new DimensionWeight();
             w.setDimension(m.get("dimension").toString());
@@ -37,8 +46,13 @@ public class DimensionWeightController {
 
     @PostMapping("/list")
     public Result<List<DimensionWeight>> list(@RequestBody Map<String, Object> params) {
-        String targetType = params.get("targetType").toString();
-        Long targetId = Long.valueOf(params.get("targetId").toString());
+        Object targetTypeObj = params.get("targetType");
+        Object targetIdObj = params.get("targetId");
+        if (targetTypeObj == null || targetIdObj == null) {
+            return Result.error("targetType 和 targetId 不能为空");
+        }
+        String targetType = targetTypeObj.toString();
+        Long targetId = Long.valueOf(targetIdObj.toString());
         List<DimensionWeight> list = dimensionWeightService.getByTarget(targetType, targetId);
         return Result.success(list);
     }