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

fix(backend): 参数校验与错误处理强化 - 控制器参数判空/可选 + MultipartException处理 + 异常语义化

Xiaogang Liao 4 недель назад
Родитель
Сommit
76d09aa1d7

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

@@ -1,10 +1,12 @@
 package com.etotem.cfc.config;
 
 import com.etotem.cfc.common.Result;
+import javax.servlet.http.HttpServletRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.multipart.MultipartException;
 
 @RestControllerAdvice
 public class GlobalExceptionHandler {
@@ -16,9 +18,15 @@ public class GlobalExceptionHandler {
         return Result.error(400, e.getMessage());
     }
 
+    @ExceptionHandler(MultipartException.class)
+    public Result<Void> handleMultipartException(MultipartException e, HttpServletRequest request) {
+        log.warn("非multipart请求访问文件接口: uri={}, error={}", request.getRequestURI(), e.getMessage());
+        return Result.error(400, "请求格式错误,请使用文件表单上传");
+    }
+
     @ExceptionHandler(Exception.class)
-    public Result<Void> handleException(Exception e) {
-        log.error("未捕获异常: {} - {}", e.getClass().getName(), e.getMessage(), e);
+    public Result<Void> handleException(Exception e, HttpServletRequest request) {
+        log.error("未捕获异常: {} - {} | uri={}", e.getClass().getName(), e.getMessage(), request.getRequestURI(), e);
         return Result.error("服务器内部错误");
     }
 }

+ 5 - 2
cfc-backend/src/main/java/com/etotem/cfc/controller/HealthReportController.java

@@ -1328,10 +1328,13 @@ public class HealthReportController {
 
     @Operation(summary = "获取食材推荐列表")
     @PostMapping("/foods")
-    public Result<List<Food>> listFoods(@RequestBody Map<String, Object> params) {
+    public Result<List<Food>> listFoods(@RequestBody(required = false) Map<String, Object> params) {
+        if (params == null) {
+            return Result.success(java.util.Collections.emptyList());
+        }
         Long reportId = ParamUtils.getLong(params.get("reportId"));
         if (reportId == null) {
-            return Result.error("reportId不能为空");
+            return Result.success(java.util.Collections.emptyList());
         }
         List<Food> foods = foodService.listByReportId(reportId);
         return Result.success(foods);

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/controller/MediaController.java

@@ -29,8 +29,8 @@ public class MediaController {
     @PostMapping("/upload")
     public Result<MediaRecord> uploadMedia(
             @RequestParam("file") MultipartFile file,
-            @RequestParam Long taskId,
-            @RequestParam Long creatorId,
+            @RequestParam(required = false) Long taskId,
+            @RequestParam(required = false) Long creatorId,
             @RequestParam(required = false) String description) {
 
         // 验证文件大小

+ 5 - 1
cfc-backend/src/main/java/com/etotem/cfc/controller/diet/DietRecommendationController.java

@@ -17,7 +17,11 @@ public class DietRecommendationController {
     @PostMapping("/today")
     public Result<Map> getTodayRecommendation(
             @RequestAttribute("familyId") Long familyId,
-            @RequestParam String date) {
+            @RequestBody(required = false) Map<String, String> request) {
+        String date = (request != null) ? request.get("date") : null;
+        if (date == null || date.isEmpty()) {
+            return Result.error("date不能为空");
+        }
         return Result.success(dietRecommendationService.getTodayRecommendation(familyId, date));
     }
 

+ 1 - 4
cfc-backend/src/main/java/com/etotem/cfc/controller/family/FamilyInviteController.java

@@ -272,10 +272,7 @@ public class FamilyInviteController {
             return Result.error(e.getMessage());
         }
 
-        String qrBase64;
-        // scene 必须是合法 JSON 字符串(getwxacodeunlimit 限制 64 字节,token 32 字符 → ~46 字节安全)
-        String scene = "{\"t\":\"" + token + "\"}";
-        qrBase64 = wechatService.generateWxacode(scene, "pages/invite/join");
+        String qrBase64 = wechatService.generateWxacode(token, "pages/invite/join");
 
         Family family = familyMapper.selectById(user.getFamilyId());
 

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/controller/notice/NoticeController.java

@@ -21,7 +21,7 @@ public class NoticeController {
     private NoticeMapper noticeMapper;
 
     @Operation(summary = "获取已发布公告列表")
-    @GetMapping("/list")
+    @RequestMapping(value = "/list", method = {RequestMethod.GET, RequestMethod.POST})
     public Result<List<Notice>> list() {
         LambdaQueryWrapper<Notice> q = new LambdaQueryWrapper<>();
         q.eq(Notice::getStatus, "active");

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/MembershipService.java

@@ -76,7 +76,7 @@ public class MembershipService implements MembershipServiceInterface {
     public Long getUserFamilyId(Long userId) {
         User user = userMapper.selectById(userId);
         if (user == null) {
-            throw new RuntimeException("用户不存在");
+            throw new IllegalArgumentException("用户不存在");
         }
         return user.getFamilyId();
     }
@@ -85,7 +85,7 @@ public class MembershipService implements MembershipServiceInterface {
     public Long getOrCreateUserFamilyId(Long userId) {
         User user = userMapper.selectById(userId);
         if (user == null) {
-            throw new RuntimeException("用户不存在");
+            throw new IllegalArgumentException("用户不存在");
         }
         if (user.getFamilyId() != null && user.getFamilyId() != 0L) {
             return user.getFamilyId();
@@ -645,7 +645,7 @@ public class MembershipService implements MembershipServiceInterface {
     public void upgradeToFamily(Long userId, String upgradeType, Long orderId) {
         User user = userMapper.selectById(userId);
         if (user == null) {
-            throw new RuntimeException("用户不存在");
+            throw new IllegalArgumentException("用户不存在");
         }
 
         String fromLevel = user.getMemberLevel() != null ? user.getMemberLevel() : "FREE";

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/service/UserService.java

@@ -1069,7 +1069,7 @@ FamilyMember child = familyMemberMapper.selectById(memberId);
             user.setRole(dto.getRole());
         }
         // 更新性别
-        if (dto.getGender() != null) {
+        if (dto.getGender() != null && !dto.getGender().trim().isEmpty()) {
             String gender = dto.getGender();
             if ("男".equals(gender) || "0".equals(gender)) {
                 gender = "male";

+ 5 - 2
cfc-backend/src/main/java/com/etotem/cfc/service/impl/SurveyServiceImpl.java

@@ -151,13 +151,16 @@ public class SurveyServiceImpl implements SurveyService {
 
     @Override
     public SurveyRecord submitSurvey(Long userId, Long memberId, Long templateId, String answersJson, Date periodStart, Date periodEnd) {
+        if (templateId == null) {
+            throw new IllegalArgumentException("缺少调研模板ID,请从调研列表进入");
+        }
         memberId = resolveMemberId(userId, memberId);
         SurveyTemplate template = surveyTemplateMapper.selectById(templateId);
         if (template == null) {
-            throw new RuntimeException("调研模板不存在");
+            throw new IllegalArgumentException("调研模板不存在");
         }
         if (memberId == null) {
-            throw new RuntimeException("无法确定成员ID,请先完善家庭成员信息");
+            throw new IllegalArgumentException("无法确定成员ID,请先完善家庭成员信息");
         }
         FamilyMember member = familyMemberMapper.selectById(memberId);
         SurveyRecord record = new SurveyRecord();