Просмотр исходного кода

refactor(exception): 统一异常处理与日志记录

- 为所有控制器添加日志记录器,增强错误追踪能力
- 修改异常捕获逻辑,使用自定义异常替代原生异常
- 统一返回错误码和消息格式,提升接口一致性
- 完善自定义异常类,支持带错误码的构造方式
- 更新枚举转换方法,抛出自定义异常而非非法参数异常
- 强化安全工具类,针对无效用户身份抛出认证异常
- 数据服务层校验失败时,明确抛出数据不存在异常
- 全局异常处理器增加对多种异常类型的细致处理
- 日志级别调整,确保关键错误被有效记录和监控
mcbaiyun 1 месяц назад
Родитель
Сommit
85772b6c63
18 измененных файлов с 142 добавлено и 38 удалено
  1. 10 3
      src/main/java/work/baiyun/chronicdiseaseapp/controller/BloodGlucoseDataController.java
  2. 10 3
      src/main/java/work/baiyun/chronicdiseaseapp/controller/BloodPressureDataController.java
  3. 7 2
      src/main/java/work/baiyun/chronicdiseaseapp/controller/GeoController.java
  4. 10 3
      src/main/java/work/baiyun/chronicdiseaseapp/controller/HeartRateDataController.java
  5. 10 3
      src/main/java/work/baiyun/chronicdiseaseapp/controller/PhysicalDataController.java
  6. 14 5
      src/main/java/work/baiyun/chronicdiseaseapp/controller/UserBindingController.java
  7. 2 2
      src/main/java/work/baiyun/chronicdiseaseapp/controller/WeChatController.java
  8. 3 1
      src/main/java/work/baiyun/chronicdiseaseapp/enums/BloodGlucoseType.java
  9. 3 1
      src/main/java/work/baiyun/chronicdiseaseapp/enums/Gender.java
  10. 3 1
      src/main/java/work/baiyun/chronicdiseaseapp/enums/PermissionGroup.java
  11. 3 1
      src/main/java/work/baiyun/chronicdiseaseapp/enums/UserBindingType.java
  12. 12 0
      src/main/java/work/baiyun/chronicdiseaseapp/exception/CustomException.java
  13. 31 5
      src/main/java/work/baiyun/chronicdiseaseapp/exception/CustomExceptionHandler.java
  14. 3 1
      src/main/java/work/baiyun/chronicdiseaseapp/service/impl/BloodGlucoseDataServiceImpl.java
  15. 3 1
      src/main/java/work/baiyun/chronicdiseaseapp/service/impl/BloodPressureDataServiceImpl.java
  16. 3 1
      src/main/java/work/baiyun/chronicdiseaseapp/service/impl/HeartRateDataServiceImpl.java
  17. 3 1
      src/main/java/work/baiyun/chronicdiseaseapp/service/impl/PhysicalDataServiceImpl.java
  18. 12 4
      src/main/java/work/baiyun/chronicdiseaseapp/util/SecurityUtils.java

+ 10 - 3
src/main/java/work/baiyun/chronicdiseaseapp/controller/BloodGlucoseDataController.java

@@ -20,12 +20,16 @@ import work.baiyun.chronicdiseaseapp.model.vo.DeleteBloodGlucoseDataRequest;
 import work.baiyun.chronicdiseaseapp.service.BloodGlucoseDataService;
 import work.baiyun.chronicdiseaseapp.service.BloodGlucoseDataService;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 @RestController
 @RestController
 @RequestMapping("/blood-glucose")
 @RequestMapping("/blood-glucose")
 @Tag(name = "血糖 (Blood Glucose)", description = "血糖相关接口")
 @Tag(name = "血糖 (Blood Glucose)", description = "血糖相关接口")
 public class BloodGlucoseDataController {
 public class BloodGlucoseDataController {
 
 
+    private static final Logger logger = LoggerFactory.getLogger(BloodGlucoseDataController.class);
+
     @Autowired
     @Autowired
     private BloodGlucoseDataService service;
     private BloodGlucoseDataService service;
 
 
@@ -44,7 +48,8 @@ public class BloodGlucoseDataController {
             service.addBloodGlucoseData(req);
             service.addBloodGlucoseData(req);
             return R.success(200, "ok");
             return R.success(200, "ok");
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("add blood glucose data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -63,7 +68,8 @@ public class BloodGlucoseDataController {
             Page<BloodGlucoseDataResponse> page = service.listBloodGlucoseData(req);
             Page<BloodGlucoseDataResponse> page = service.listBloodGlucoseData(req);
             return R.success(200, "ok", page);
             return R.success(200, "ok", page);
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("list blood glucose data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -82,7 +88,8 @@ public class BloodGlucoseDataController {
             service.deleteBloodGlucoseData(req.getId());
             service.deleteBloodGlucoseData(req.getId());
             return R.success(200, "ok");
             return R.success(200, "ok");
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("delete blood glucose data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 }
 }

+ 10 - 3
src/main/java/work/baiyun/chronicdiseaseapp/controller/BloodPressureDataController.java

@@ -20,12 +20,16 @@ import work.baiyun.chronicdiseaseapp.model.vo.DeleteBloodPressureDataRequest;
 import work.baiyun.chronicdiseaseapp.service.BloodPressureDataService;
 import work.baiyun.chronicdiseaseapp.service.BloodPressureDataService;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 @RestController
 @RestController
 @RequestMapping("/blood-pressure")
 @RequestMapping("/blood-pressure")
 @Tag(name = "血压 (Blood Pressure)", description = "血压相关接口")
 @Tag(name = "血压 (Blood Pressure)", description = "血压相关接口")
 public class BloodPressureDataController {
 public class BloodPressureDataController {
 
 
+    private static final Logger logger = LoggerFactory.getLogger(BloodPressureDataController.class);
+
     @Autowired
     @Autowired
     private BloodPressureDataService service;
     private BloodPressureDataService service;
 
 
@@ -44,7 +48,8 @@ public class BloodPressureDataController {
             service.addBloodPressureData(req);
             service.addBloodPressureData(req);
             return R.success(200, "ok");
             return R.success(200, "ok");
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("add blood pressure data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -63,7 +68,8 @@ public class BloodPressureDataController {
             Page<BloodPressureDataResponse> page = service.listBloodPressureData(req);
             Page<BloodPressureDataResponse> page = service.listBloodPressureData(req);
             return R.success(200, "ok", page);
             return R.success(200, "ok", page);
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("list blood pressure data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -82,7 +88,8 @@ public class BloodPressureDataController {
             service.deleteBloodPressureData(req.getId());
             service.deleteBloodPressureData(req.getId());
             return R.success(200, "ok");
             return R.success(200, "ok");
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("delete blood pressure data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 }
 }

+ 7 - 2
src/main/java/work/baiyun/chronicdiseaseapp/controller/GeoController.java

@@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.client.RestTemplate;
 import work.baiyun.chronicdiseaseapp.common.R;
 import work.baiyun.chronicdiseaseapp.common.R;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
@@ -21,6 +23,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
 @Tag(name = "地理 (Geo)", description = "地理编码与位置信息接口")
 @Tag(name = "地理 (Geo)", description = "地理编码与位置信息接口")
 public class GeoController {
 public class GeoController {
 
 
+    private static final Logger logger = LoggerFactory.getLogger(GeoController.class);
+
     @Autowired
     @Autowired
     private RestTemplate restTemplate;
     private RestTemplate restTemplate;
 
 
@@ -40,8 +44,9 @@ public class GeoController {
             ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
             ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
             return R.success(200, "ok", response.getBody());
             return R.success(200, "ok", response.getBody());
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.GEO_REQUEST_FAILED.getCode(), 
-                         ErrorCode.GEO_REQUEST_FAILED.getMessage() + ": " + e.getMessage(), 
+            logger.error("geo nearest request failed", e);
+            return R.fail(ErrorCode.GEO_REQUEST_FAILED.getCode(),
+                         ErrorCode.GEO_REQUEST_FAILED.getMessage(),
                          null);
                          null);
         }
         }
     }
     }

+ 10 - 3
src/main/java/work/baiyun/chronicdiseaseapp/controller/HeartRateDataController.java

@@ -20,12 +20,16 @@ import work.baiyun.chronicdiseaseapp.model.vo.DeleteHeartRateDataRequest;
 import work.baiyun.chronicdiseaseapp.service.HeartRateDataService;
 import work.baiyun.chronicdiseaseapp.service.HeartRateDataService;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 @RestController
 @RestController
 @RequestMapping("/heart-rate")
 @RequestMapping("/heart-rate")
 @Tag(name = "心率 (Heart Rate)", description = "心率相关接口")
 @Tag(name = "心率 (Heart Rate)", description = "心率相关接口")
 public class HeartRateDataController {
 public class HeartRateDataController {
 
 
+    private static final Logger logger = LoggerFactory.getLogger(HeartRateDataController.class);
+
     @Autowired
     @Autowired
     private HeartRateDataService service;
     private HeartRateDataService service;
 
 
@@ -44,7 +48,8 @@ public class HeartRateDataController {
             service.addHeartRateData(req);
             service.addHeartRateData(req);
             return R.success(200, "ok");
             return R.success(200, "ok");
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("add heart rate data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -63,7 +68,8 @@ public class HeartRateDataController {
             Page<HeartRateDataResponse> page = service.listHeartRateData(req);
             Page<HeartRateDataResponse> page = service.listHeartRateData(req);
             return R.success(200, "ok", page);
             return R.success(200, "ok", page);
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("list heart rate data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -82,7 +88,8 @@ public class HeartRateDataController {
             service.deleteHeartRateData(req.getId());
             service.deleteHeartRateData(req.getId());
             return R.success(200, "ok");
             return R.success(200, "ok");
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("delete heart rate data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 }
 }

+ 10 - 3
src/main/java/work/baiyun/chronicdiseaseapp/controller/PhysicalDataController.java

@@ -20,12 +20,16 @@ import work.baiyun.chronicdiseaseapp.model.vo.DeletePhysicalDataRequest;
 import work.baiyun.chronicdiseaseapp.service.PhysicalDataService;
 import work.baiyun.chronicdiseaseapp.service.PhysicalDataService;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 @RestController
 @RestController
 @RequestMapping("/physical")
 @RequestMapping("/physical")
 @Tag(name = "体格 (Physical Data)", description = "体格数据相关接口")
 @Tag(name = "体格 (Physical Data)", description = "体格数据相关接口")
 public class PhysicalDataController {
 public class PhysicalDataController {
 
 
+    private static final Logger logger = LoggerFactory.getLogger(PhysicalDataController.class);
+
     @Autowired
     @Autowired
     private PhysicalDataService physicalDataService;
     private PhysicalDataService physicalDataService;
 
 
@@ -44,7 +48,8 @@ public class PhysicalDataController {
             physicalDataService.addPhysicalData(req);
             physicalDataService.addPhysicalData(req);
             return R.success(200, "ok");
             return R.success(200, "ok");
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("add physical data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -63,7 +68,8 @@ public class PhysicalDataController {
             Page<PhysicalDataResponse> page = physicalDataService.listPhysicalData(req);
             Page<PhysicalDataResponse> page = physicalDataService.listPhysicalData(req);
             return R.success(200, "ok", page);
             return R.success(200, "ok", page);
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("list physical data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -82,7 +88,8 @@ public class PhysicalDataController {
             physicalDataService.deletePhysicalData(req.getId());
             physicalDataService.deletePhysicalData(req.getId());
             return R.success(200, "ok");
             return R.success(200, "ok");
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("delete physical data failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 }
 }

+ 14 - 5
src/main/java/work/baiyun/chronicdiseaseapp/controller/UserBindingController.java

@@ -22,6 +22,8 @@ import work.baiyun.chronicdiseaseapp.model.vo.CheckUserBindingResponse;
 import work.baiyun.chronicdiseaseapp.model.vo.CheckUserBindingRequest;
 import work.baiyun.chronicdiseaseapp.model.vo.CheckUserBindingRequest;
 import work.baiyun.chronicdiseaseapp.model.vo.UserBindingPageResult;
 import work.baiyun.chronicdiseaseapp.model.vo.UserBindingPageResult;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
 import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import work.baiyun.chronicdiseaseapp.service.UserBindingService;
 import work.baiyun.chronicdiseaseapp.service.UserBindingService;
 
 
 @RestController
 @RestController
@@ -29,6 +31,8 @@ import work.baiyun.chronicdiseaseapp.service.UserBindingService;
 @Tag(name = "用户绑定 (User Binding)", description = "用户绑定关系相关接口")
 @Tag(name = "用户绑定 (User Binding)", description = "用户绑定关系相关接口")
 public class UserBindingController {
 public class UserBindingController {
 
 
+    private static final Logger logger = LoggerFactory.getLogger(UserBindingController.class);
+
     @Autowired
     @Autowired
     private UserBindingService userBindingService;
     private UserBindingService userBindingService;
 
 
@@ -47,7 +51,8 @@ public class UserBindingController {
             userBindingService.createUserBinding(req);
             userBindingService.createUserBinding(req);
             return R.success(200, "ok");
             return R.success(200, "ok");
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("create user binding failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -66,7 +71,8 @@ public class UserBindingController {
             userBindingService.deleteUserBinding(req.getPatientUserId(), req.getBoundUserId());
             userBindingService.deleteUserBinding(req.getPatientUserId(), req.getBoundUserId());
             return R.success(200, "ok");
             return R.success(200, "ok");
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("delete user binding failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -85,7 +91,8 @@ public class UserBindingController {
             Page<UserBindingResponse> page = userBindingService.listBindingsByPatient(patientUserId, bindingType, req);
             Page<UserBindingResponse> page = userBindingService.listBindingsByPatient(patientUserId, bindingType, req);
             return R.success(200, "ok", page);
             return R.success(200, "ok", page);
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("list bindings by patient failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -104,7 +111,8 @@ public class UserBindingController {
             Page<UserBindingResponse> page = userBindingService.listBindingsByBoundUser(boundUserId, bindingType, req);
             Page<UserBindingResponse> page = userBindingService.listBindingsByBoundUser(boundUserId, bindingType, req);
             return R.success(200, "ok", page);
             return R.success(200, "ok", page);
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage() + ": " + e.getMessage());
+            logger.error("list bindings by bound user failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 
 
@@ -123,7 +131,8 @@ public class UserBindingController {
             CheckUserBindingResponse response = userBindingService.checkUserBinding(req);
             CheckUserBindingResponse response = userBindingService.checkUserBinding(req);
             return R.success(200, "ok", response);
             return R.success(200, "ok", response);
         } catch (Exception e) {
         } catch (Exception e) {
-            return R.fail(500, e.getMessage());
+            logger.error("check user binding failed", e);
+            return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
         }
         }
     }
     }
 }
 }

+ 2 - 2
src/main/java/work/baiyun/chronicdiseaseapp/controller/WeChatController.java

@@ -76,7 +76,7 @@ public class WeChatController {
         PermissionGroup pg;
         PermissionGroup pg;
         try {
         try {
             pg = PermissionGroup.fromCode(req.getRole());
             pg = PermissionGroup.fromCode(req.getRole());
-        } catch (IllegalArgumentException e) {
+        } catch (work.baiyun.chronicdiseaseapp.exception.CustomException e) {
             return R.fail(ErrorCode.WECHAT_ROLE_INVALID.getCode(), 
             return R.fail(ErrorCode.WECHAT_ROLE_INVALID.getCode(), 
                          ErrorCode.WECHAT_ROLE_INVALID.getMessage());
                          ErrorCode.WECHAT_ROLE_INVALID.getMessage());
         }
         }
@@ -198,7 +198,7 @@ public class WeChatController {
             if (req.getSex() != null) {
             if (req.getSex() != null) {
                 try {
                 try {
                     ui.setSex(work.baiyun.chronicdiseaseapp.enums.Gender.fromCode(req.getSex()));
                     ui.setSex(work.baiyun.chronicdiseaseapp.enums.Gender.fromCode(req.getSex()));
-                } catch (IllegalArgumentException e) {
+                } catch (work.baiyun.chronicdiseaseapp.exception.CustomException e) {
                     return R.fail(ErrorCode.PARAMETER_ERROR.getCode(), 
                     return R.fail(ErrorCode.PARAMETER_ERROR.getCode(), 
                                  ErrorCode.PARAMETER_ERROR.getMessage() + ": Invalid sex value");
                                  ErrorCode.PARAMETER_ERROR.getMessage() + ": Invalid sex value");
                 }
                 }

+ 3 - 1
src/main/java/work/baiyun/chronicdiseaseapp/enums/BloodGlucoseType.java

@@ -39,6 +39,8 @@ public enum BloodGlucoseType {
         for (BloodGlucoseType t : BloodGlucoseType.values()) {
         for (BloodGlucoseType t : BloodGlucoseType.values()) {
             if (t.code.equals(code)) return t;
             if (t.code.equals(code)) return t;
         }
         }
-        throw new IllegalArgumentException("Unknown BloodGlucoseType code: " + code);
+    throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+        work.baiyun.chronicdiseaseapp.enums.ErrorCode.PARAMETER_ERROR.getCode(),
+        "Unknown BloodGlucoseType code: " + code);
     }
     }
 }
 }

+ 3 - 1
src/main/java/work/baiyun/chronicdiseaseapp/enums/Gender.java

@@ -29,7 +29,9 @@ public enum Gender {
         for (Gender g : Gender.values()) {
         for (Gender g : Gender.values()) {
             if (g.code == code) return g;
             if (g.code == code) return g;
         }
         }
-        throw new IllegalArgumentException("Unknown Gender code: " + code);
+    throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+        work.baiyun.chronicdiseaseapp.enums.ErrorCode.PARAMETER_ERROR.getCode(),
+        "Unknown Gender code: " + code);
     }
     }
 }
 }
 
 

+ 3 - 1
src/main/java/work/baiyun/chronicdiseaseapp/enums/PermissionGroup.java

@@ -32,6 +32,8 @@ public enum PermissionGroup {
         for (PermissionGroup g : PermissionGroup.values()) {
         for (PermissionGroup g : PermissionGroup.values()) {
             if (g.code == code) return g;
             if (g.code == code) return g;
         }
         }
-        throw new IllegalArgumentException("Unknown PermissionGroup code: " + code);
+    throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+        work.baiyun.chronicdiseaseapp.enums.ErrorCode.PARAMETER_ERROR.getCode(),
+        "Unknown PermissionGroup code: " + code);
     }
     }
 }
 }

+ 3 - 1
src/main/java/work/baiyun/chronicdiseaseapp/enums/UserBindingType.java

@@ -36,6 +36,8 @@ public enum UserBindingType {
         for (UserBindingType type : UserBindingType.values()) {
         for (UserBindingType type : UserBindingType.values()) {
             if (type.code.equals(code)) return type;
             if (type.code.equals(code)) return type;
         }
         }
-        throw new IllegalArgumentException("Unknown UserBindingType code: " + code);
+    throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+        work.baiyun.chronicdiseaseapp.enums.ErrorCode.PARAMETER_ERROR.getCode(),
+        "Unknown UserBindingType code: " + code);
     }
     }
 }
 }

+ 12 - 0
src/main/java/work/baiyun/chronicdiseaseapp/exception/CustomException.java

@@ -4,7 +4,19 @@ package work.baiyun.chronicdiseaseapp.exception;
  * 自定义运行时业务异常,交由全局异常处理器处理
  * 自定义运行时业务异常,交由全局异常处理器处理
  */
  */
 public class CustomException extends RuntimeException {
 public class CustomException extends RuntimeException {
+    private int code;
+
     public CustomException(String message) {
     public CustomException(String message) {
         super(message);
         super(message);
+        this.code = -1; // unknown
+    }
+
+    public CustomException(int code, String message) {
+        super(message);
+        this.code = code;
+    }
+
+    public int getCode() {
+        return code;
     }
     }
 }
 }

+ 31 - 5
src/main/java/work/baiyun/chronicdiseaseapp/exception/CustomExceptionHandler.java

@@ -2,7 +2,7 @@ package work.baiyun.chronicdiseaseapp.exception;
 
 
 import jakarta.validation.*;
 import jakarta.validation.*;
 import work.baiyun.chronicdiseaseapp.common.R;
 import work.baiyun.chronicdiseaseapp.common.R;
-import work.baiyun.chronicdiseaseapp.enums.ExceptionResultCode;
+import work.baiyun.chronicdiseaseapp.enums.ErrorCode;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.validation.BindException;
 import org.springframework.validation.BindException;
@@ -31,13 +31,14 @@ public class CustomExceptionHandler {
      */
      */
     @ExceptionHandler(value = BindException.class)
     @ExceptionHandler(value = BindException.class)
     public R<Void> errorHandler(BindException ex) {
     public R<Void> errorHandler(BindException ex) {
+        log.error("BindException occurred", ex);
         BindingResult result = ex.getBindingResult();
         BindingResult result = ex.getBindingResult();
         StringBuilder errorMsg = new StringBuilder();
         StringBuilder errorMsg = new StringBuilder();
         for (ObjectError error : result.getAllErrors()) {
         for (ObjectError error : result.getAllErrors()) {
             errorMsg.append(error.getDefaultMessage()).append(", ");
             errorMsg.append(error.getDefaultMessage()).append(", ");
         }
         }
         errorMsg.delete(errorMsg.length() - 2, errorMsg.length());
         errorMsg.delete(errorMsg.length() - 2, errorMsg.length());
-        return R.fail(ExceptionResultCode.VALID_EXCEPTION.getCode(), errorMsg.toString());
+    return R.fail(ErrorCode.PARAMETER_ERROR.getCode(), errorMsg.toString());
     }
     }
     /**
     /**
      * 参数校验异常
      * 参数校验异常
@@ -47,12 +48,31 @@ public class CustomExceptionHandler {
      */
      */
     @ExceptionHandler(ConstraintViolationException.class)
     @ExceptionHandler(ConstraintViolationException.class)
     public R<Void> validationErrorHandler(ConstraintViolationException ex) {
     public R<Void> validationErrorHandler(ConstraintViolationException ex) {
+        log.error("ConstraintViolationException occurred", ex);
         List<String> errorInformation = ex.getConstraintViolations()
         List<String> errorInformation = ex.getConstraintViolations()
                 .stream()
                 .stream()
                 .map(ConstraintViolation::getMessage)
                 .map(ConstraintViolation::getMessage)
                 .collect(Collectors.toList());
                 .collect(Collectors.toList());
         String message = errorInformation.toString().substring(1, errorInformation.toString().length() - 1);
         String message = errorInformation.toString().substring(1, errorInformation.toString().length() - 1);
-        return R.fail(ExceptionResultCode.VALID_EXCEPTION.getCode(), message);
+    return R.fail(ErrorCode.PARAMETER_ERROR.getCode(), message);
+    }
+
+    /**
+     * 非受检的参数非法异常
+     */
+    @ExceptionHandler(IllegalArgumentException.class)
+    public R<Void> illegalArgumentHandler(IllegalArgumentException ex) {
+        log.warn("IllegalArgumentException: {}", ex.getMessage());
+        return R.fail(ErrorCode.PARAMETER_ERROR.getCode(), ErrorCode.PARAMETER_ERROR.getMessage() + ": " + ex.getMessage());
+    }
+
+    /**
+     * 非法状态异常 -> 映射为系统异常(不可预期),记录日志
+     */
+    @ExceptionHandler(IllegalStateException.class)
+    public R<Void> illegalStateHandler(IllegalStateException ex) {
+        log.error("IllegalStateException", ex);
+        return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
     }
     }
     /**
     /**
      * 自定义异常
      * 自定义异常
@@ -63,7 +83,13 @@ public class CustomExceptionHandler {
     @ExceptionHandler(value = CustomException.class)
     @ExceptionHandler(value = CustomException.class)
     public R<Void> customExceptionHandler(CustomException customException) {
     public R<Void> customExceptionHandler(CustomException customException) {
         String message = customException.getMessage();
         String message = customException.getMessage();
-        return R.fail(ExceptionResultCode.EXCEPTION.getCode(), message);
+        int code = customException.getCode();
+        if (code > 0) {
+            return R.fail(code, message);
+        }
+        // fallback to common system error
+        log.error("CustomException occurred", customException);
+        return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), message);
     }
     }
     /**
     /**
      * 未知异常
      * 未知异常
@@ -74,6 +100,6 @@ public class CustomExceptionHandler {
     @ExceptionHandler(value = Exception.class)
     @ExceptionHandler(value = Exception.class)
     public R<Void> exceptionHandler(Exception exception) {
     public R<Void> exceptionHandler(Exception exception) {
         log.error("Unhandled exception", exception);
         log.error("Unhandled exception", exception);
-        return R.fail(ExceptionResultCode.EXCEPTION.getCode(), ExceptionResultCode.EXCEPTION.getMsg());
+        return R.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
     }
     }
 }
 }

+ 3 - 1
src/main/java/work/baiyun/chronicdiseaseapp/service/impl/BloodGlucoseDataServiceImpl.java

@@ -63,7 +63,9 @@ public class BloodGlucoseDataServiceImpl implements BloodGlucoseDataService {
         Long recordId = Long.parseLong(id);
         Long recordId = Long.parseLong(id);
         BloodGlucoseData record = bloodGlucoseDataMapper.selectById(recordId);
         BloodGlucoseData record = bloodGlucoseDataMapper.selectById(recordId);
         if (record == null || !record.getUserId().equals(userId)) {
         if (record == null || !record.getUserId().equals(userId)) {
-            throw new RuntimeException("记录不存在或无权限删除");
+            throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+                    work.baiyun.chronicdiseaseapp.enums.ErrorCode.DATA_NOT_FOUND.getCode(),
+                    work.baiyun.chronicdiseaseapp.enums.ErrorCode.DATA_NOT_FOUND.getMessage());
         }
         }
         bloodGlucoseDataMapper.deleteById(recordId);
         bloodGlucoseDataMapper.deleteById(recordId);
     }
     }

+ 3 - 1
src/main/java/work/baiyun/chronicdiseaseapp/service/impl/BloodPressureDataServiceImpl.java

@@ -63,7 +63,9 @@ public class BloodPressureDataServiceImpl implements BloodPressureDataService {
         Long recordId = Long.parseLong(id);
         Long recordId = Long.parseLong(id);
         BloodPressureData record = bloodPressureDataMapper.selectById(recordId);
         BloodPressureData record = bloodPressureDataMapper.selectById(recordId);
         if (record == null || !record.getUserId().equals(userId)) {
         if (record == null || !record.getUserId().equals(userId)) {
-            throw new RuntimeException("记录不存在或无权限删除");
+            throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+                    work.baiyun.chronicdiseaseapp.enums.ErrorCode.DATA_NOT_FOUND.getCode(),
+                    work.baiyun.chronicdiseaseapp.enums.ErrorCode.DATA_NOT_FOUND.getMessage());
         }
         }
         bloodPressureDataMapper.deleteById(recordId);
         bloodPressureDataMapper.deleteById(recordId);
     }
     }

+ 3 - 1
src/main/java/work/baiyun/chronicdiseaseapp/service/impl/HeartRateDataServiceImpl.java

@@ -63,7 +63,9 @@ public class HeartRateDataServiceImpl implements HeartRateDataService {
         Long recordId = Long.parseLong(id);
         Long recordId = Long.parseLong(id);
         HeartRateData record = heartRateDataMapper.selectById(recordId);
         HeartRateData record = heartRateDataMapper.selectById(recordId);
         if (record == null || !record.getUserId().equals(userId)) {
         if (record == null || !record.getUserId().equals(userId)) {
-            throw new RuntimeException("记录不存在或无权限删除");
+            throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+                    work.baiyun.chronicdiseaseapp.enums.ErrorCode.DATA_NOT_FOUND.getCode(),
+                    work.baiyun.chronicdiseaseapp.enums.ErrorCode.DATA_NOT_FOUND.getMessage());
         }
         }
         heartRateDataMapper.deleteById(recordId);
         heartRateDataMapper.deleteById(recordId);
     }
     }

+ 3 - 1
src/main/java/work/baiyun/chronicdiseaseapp/service/impl/PhysicalDataServiceImpl.java

@@ -64,7 +64,9 @@ public class PhysicalDataServiceImpl implements PhysicalDataService {
         Long userId = work.baiyun.chronicdiseaseapp.util.SecurityUtils.getCurrentUserId();
         Long userId = work.baiyun.chronicdiseaseapp.util.SecurityUtils.getCurrentUserId();
         PhysicalData record = physicalDataMapper.selectById(id);
         PhysicalData record = physicalDataMapper.selectById(id);
         if (record == null || !record.getUserId().equals(userId)) {
         if (record == null || !record.getUserId().equals(userId)) {
-            throw new RuntimeException("记录不存在或无权限删除");
+            throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+                    work.baiyun.chronicdiseaseapp.enums.ErrorCode.DATA_NOT_FOUND.getCode(),
+                    work.baiyun.chronicdiseaseapp.enums.ErrorCode.DATA_NOT_FOUND.getMessage());
         }
         }
         physicalDataMapper.deleteById(id);
         physicalDataMapper.deleteById(id);
     }
     }

+ 12 - 4
src/main/java/work/baiyun/chronicdiseaseapp/util/SecurityUtils.java

@@ -12,7 +12,9 @@ public class SecurityUtils {
     public static Long getCurrentUserId() {
     public static Long getCurrentUserId() {
         org.springframework.web.context.request.RequestAttributes attrs = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();
         org.springframework.web.context.request.RequestAttributes attrs = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();
         if (attrs == null || !(attrs instanceof org.springframework.web.context.request.ServletRequestAttributes)) {
         if (attrs == null || !(attrs instanceof org.springframework.web.context.request.ServletRequestAttributes)) {
-            throw new work.baiyun.chronicdiseaseapp.exception.CustomException("No valid userId");
+        throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+            work.baiyun.chronicdiseaseapp.enums.ErrorCode.UNAUTHORIZED.getCode(),
+            work.baiyun.chronicdiseaseapp.enums.ErrorCode.UNAUTHORIZED.getMessage());
         }
         }
         jakarta.servlet.http.HttpServletRequest request = ((org.springframework.web.context.request.ServletRequestAttributes) attrs).getRequest();
         jakarta.servlet.http.HttpServletRequest request = ((org.springframework.web.context.request.ServletRequestAttributes) attrs).getRequest();
         Object attr = request.getAttribute("currentUserId");
         Object attr = request.getAttribute("currentUserId");
@@ -25,7 +27,9 @@ public class SecurityUtils {
             try { userId = Long.parseLong((String) attr); } catch (NumberFormatException ignored) {}
             try { userId = Long.parseLong((String) attr); } catch (NumberFormatException ignored) {}
         }
         }
         if (userId == null) {
         if (userId == null) {
-            throw new work.baiyun.chronicdiseaseapp.exception.CustomException("No valid userId");
+        throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+            work.baiyun.chronicdiseaseapp.enums.ErrorCode.UNAUTHORIZED.getCode(),
+            work.baiyun.chronicdiseaseapp.enums.ErrorCode.UNAUTHORIZED.getMessage());
         }
         }
         return userId;
         return userId;
     }
     }
@@ -37,7 +41,9 @@ public class SecurityUtils {
     public static work.baiyun.chronicdiseaseapp.enums.PermissionGroup getCurrentUserRole() {
     public static work.baiyun.chronicdiseaseapp.enums.PermissionGroup getCurrentUserRole() {
         org.springframework.web.context.request.RequestAttributes attrs = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();
         org.springframework.web.context.request.RequestAttributes attrs = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();
         if (attrs == null || !(attrs instanceof org.springframework.web.context.request.ServletRequestAttributes)) {
         if (attrs == null || !(attrs instanceof org.springframework.web.context.request.ServletRequestAttributes)) {
-            throw new work.baiyun.chronicdiseaseapp.exception.CustomException("No valid user role");
+        throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+            work.baiyun.chronicdiseaseapp.enums.ErrorCode.UNAUTHORIZED.getCode(),
+            work.baiyun.chronicdiseaseapp.enums.ErrorCode.UNAUTHORIZED.getMessage());
         }
         }
         jakarta.servlet.http.HttpServletRequest request = ((org.springframework.web.context.request.ServletRequestAttributes) attrs).getRequest();
         jakarta.servlet.http.HttpServletRequest request = ((org.springframework.web.context.request.ServletRequestAttributes) attrs).getRequest();
         Object attr = request.getAttribute("currentUserRole");
         Object attr = request.getAttribute("currentUserRole");
@@ -57,7 +63,9 @@ public class SecurityUtils {
             }
             }
         }
         }
         if (role == null) {
         if (role == null) {
-            throw new work.baiyun.chronicdiseaseapp.exception.CustomException("No valid user role");
+        throw new work.baiyun.chronicdiseaseapp.exception.CustomException(
+            work.baiyun.chronicdiseaseapp.enums.ErrorCode.UNAUTHORIZED.getCode(),
+            work.baiyun.chronicdiseaseapp.enums.ErrorCode.UNAUTHORIZED.getMessage());
         }
         }
         return role;
         return role;
     }
     }