浏览代码

配置调整

hr~ 15 小时之前
父节点
当前提交
5fdf57f5f5

+ 4 - 0
product-common/pom.xml

@@ -15,6 +15,10 @@
     <description>商品服务公共模块</description>
 
     <dependencies>
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.qcloud</groupId>
             <artifactId>cos_api</artifactId>

+ 6 - 2
product-common/src/main/java/com/poyee/aspect/weblog/WebLogAspect.java

@@ -38,7 +38,10 @@ public class WebLogAspect {
     @Before("webLog()")
     public void doBefore(JoinPoint joinPoint) {
         HttpServletRequest request = ServletUtils.getRequest();
-        String traceId = Objects.requireNonNull(request).getHeader("X-Trace-Id");
+        if (request == null) {
+            return;
+        }
+        String traceId = request.getHeader("X-Trace-Id");
         if (!StringUtils.hasText(traceId)) {
             traceId = UUID.randomUUID().toString().replace("-", "");
         }
@@ -75,7 +78,8 @@ public class WebLogAspect {
     public void throwing(Throwable e) {
         HttpServletRequest request = ServletUtils.getRequest();
         long costTime = System.currentTimeMillis() - RequestNoContext.callTime.get();
-        logger.error("\n--------------[{}]返回内容开始----------------\n    接口地址:{}\n    请求令牌:{}\n    接口参数:{}\n    请求失败:{}\n    请求耗时:{}ms\n--------------[{}]返回内容结束----------------", RequestNoContext.currentThreadId.get(), RequestNoContext.apiUrl.get(), Objects.requireNonNull(request).getHeader("Authorization"), RequestNoContext.requestParam.get(), e.getMessage(), costTime, RequestNoContext.currentThreadId.get());
+        String authorization = request != null ? request.getHeader("Authorization") : "";
+        logger.error("\n--------------[{}]返回内容开始----------------\n    接口地址:{}\n    请求令牌:{}\n    接口参数:{}\n    请求失败:{}\n    请求耗时:{}ms\n--------------[{}]返回内容结束----------------", RequestNoContext.currentThreadId.get(), RequestNoContext.apiUrl.get(), authorization, RequestNoContext.requestParam.get(), e.getMessage(), costTime, RequestNoContext.currentThreadId.get());
         RequestNoContext.remove();
         MDC.remove("traceId");
     }

+ 60 - 17
product-common/src/main/java/com/poyee/exception/GlobalExceptionHandler.java

@@ -33,17 +33,27 @@ public class GlobalExceptionHandler {
      */
     @ExceptionHandler(BusinessException.class)
     public Result<Void> handleBusinessException(BusinessException e) {
-        log.warn("业务异常:{}", I18nUtil.getMessage(e.getMessage()));
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-        return Result.error(e.getCode(), I18nUtil.getMessage(e.getMessage()));
+        String message = e.getMessage();
+        String i18nMessage = I18nUtil.getMessage(message);
+        log.warn("业务异常:{}", i18nMessage != null ? i18nMessage : message);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+        }
+        return Result.error(e.getCode(), i18nMessage != null ? i18nMessage : message);
     }
 
 
     @ExceptionHandler(RuntimeException.class)
     public Result<Void> handleRuntimeException(RuntimeException e) {
-        log.warn("运行异常:{}", I18nUtil.getMessage(e.getMessage()));
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-        return Result.error(I18nUtil.getMessage(e.getMessage()));
+        String message = e.getMessage();
+        String i18nMessage = message != null ? I18nUtil.getMessage(message) : null;
+        log.warn("运行异常:{}", i18nMessage != null ? i18nMessage : message);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+        }
+        return Result.error(i18nMessage != null ? i18nMessage : (message != null ? message : "系统运行异常"));
     }
 
     /**
@@ -52,7 +62,10 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(Exception.class)
     public Result<Void> handleException(Exception e) {
         log.error("系统异常", e);
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+        }
         return Result.error(500, "系统繁忙,请稍后重试");
     }
 
@@ -63,7 +76,10 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(IllegalArgumentException.class)
     public Result<Void> handleIllegalArgumentException(IllegalArgumentException e) {
         log.error("参数异常", e);
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        }
         return Result.error(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
     }
 
@@ -81,7 +97,10 @@ public class GlobalExceptionHandler {
                     return i18nMessage != null ? i18nMessage : defaultMessage;
                 })
                 .collect(Collectors.toList());
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        }
         return Result.error(HttpServletResponse.SC_BAD_REQUEST, collect.toString());
     }
 
@@ -91,7 +110,10 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(MissingServletRequestParameterException.class)
     public Result<Void> handleMissingServletRequestParameter(MissingServletRequestParameterException e) {
         log.warn("缺少请求参数:{}", e.getParameterName());
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        }
         return Result.error(HttpServletResponse.SC_BAD_REQUEST, "缺少请求参数:" + e.getParameterName());
     }
 
@@ -101,7 +123,10 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(MethodArgumentTypeMismatchException.class)
     public Result<Void> handleMethodArgumentTypeMismatch(MethodArgumentTypeMismatchException e) {
         log.warn("参数类型不匹配:{}", e.getName());
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        }
         return Result.error(HttpServletResponse.SC_BAD_REQUEST, "参数类型不匹配:" + e.getName());
     }
 
@@ -111,7 +136,10 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(HttpMessageNotReadableException.class)
     public Result<Void> handleHttpMessageNotReadable(HttpMessageNotReadableException e) {
         log.warn("请求体解析失败:{}", e.getMessage());
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        }
         return Result.error(HttpServletResponse.SC_BAD_REQUEST, "请求体格式错误");
     }
 
@@ -121,7 +149,10 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
     public Result<Void> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e) {
         log.warn("请求方法不支持:{}", e.getMethod());
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+        }
         return Result.error(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "不支持的请求方法:" + e.getMethod());
     }
 
@@ -131,7 +162,10 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
     public Result<Void> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException e) {
         log.warn("媒体类型不支持:{}", e.getContentType());
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
+        }
         return Result.error(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, "不支持的媒体类型:" + e.getContentType());
     }
 
@@ -141,7 +175,10 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(TokenExpiredException.class)
     public Result<Void> handleTokenExpired(TokenExpiredException e) {
         log.warn("Token已过期:{}", e.getMessage());
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        }
         return Result.error(HttpServletResponse.SC_UNAUTHORIZED, "Token已过期,请重新登录");
     }
 
@@ -151,7 +188,10 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(JWTVerificationException.class)
     public Result<Void> handleJWTVerification(JWTVerificationException e) {
         log.warn("Token验证失败:{}", e.getMessage());
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        }
         return Result.error(HttpServletResponse.SC_UNAUTHORIZED, "Token无效,请重新登录");
     }
 
@@ -161,7 +201,10 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(NullPointerException.class)
     public Result<Void> handleNullPointerException(NullPointerException e) {
         log.error("空指针异常", e);
-        ServletUtils.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+        HttpServletResponse response = ServletUtils.getHttpResponse();
+        if (response != null) {
+            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+        }
         return Result.error(500, "系统繁忙,请稍后重试");
     }
 }

+ 8 - 3
product-common/src/main/java/com/poyee/utils/JwtUtils.java

@@ -18,8 +18,13 @@ public class JwtUtils {
      * 2. Base64编码的用户信息
      */
     public static JSONObject getTokenUserInfo(String token) {
-        JWT jwt = JWTUtil.parseToken(token);
-        String payloads = jwt.getPayloads().toString();
-        return JSONObject.parseObject(payloads);
+        try {
+            JWT jwt = JWTUtil.parseToken(token);
+            String payloads = jwt.getPayloads().toString();
+            return JSONObject.parseObject(payloads);
+        } catch (Exception e) {
+            log.error("解析JWT Token失败", e);
+            return null;
+        }
     }
 }

+ 19 - 0
product-common/src/main/java/com/poyee/utils/PageUtil.java

@@ -0,0 +1,19 @@
+package com.poyee.utils;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.github.pagehelper.PageInfo;
+
+import java.util.List;
+
+/**
+ * @author huang_run
+ * @date 2026/3/23 10:08
+ */
+public class PageUtil {
+    public static <T, R> PageInfo<R> convertPage(PageInfo<T> source, List<R> list) {
+        PageInfo<R> target = new PageInfo<>();
+        BeanUtil.copyProperties(source, target, "list");
+        target.setList(list);
+        return target;
+    }
+}

+ 5 - 1
product-common/src/main/java/com/poyee/utils/ServletUtils.java

@@ -26,7 +26,11 @@ public class ServletUtils {
     }
 
     public static HttpServletResponse getHttpResponse() {
-        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
+        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        if (attributes == null) {
+            return null;
+        }
+        return attributes.getResponse();
     }
 
     /**

+ 3 - 3
product-web/src/main/java/com/poyee/controller/ProductInfoController.java

@@ -48,13 +48,13 @@ public class ProductInfoController {
         return Result.success(productInfoFacade.review(productReviewReq));
     }
 
-    @GetMapping("/idea/attribute/{sku}")
+    @GetMapping("/idle/attribute/{sku}")
     @ApiOperation("查看闲置信息")
     public Result<IdleAttributeRes> idleAttribute(@ApiParam("sku") @PathVariable("sku") String sku) {
         return Result.success(productInfoFacade.idleAttribute(sku));
     }
 
-    @PostMapping("/idea/attribute")
+    @PostMapping("/idle/attribute")
     @ApiOperation("编辑闲置信息")
     public Result<Boolean> idleAttribute(@RequestBody @Validated IdleAttributeReq idleAttributeReq) {
         return Result.success(productInfoFacade.idleAttribute(idleAttributeReq));
@@ -66,7 +66,7 @@ public class ProductInfoController {
         return Result.success(productInfoFacade.fastSale(sku));
     }
 
-    @GetMapping("/fast/sale")
+    @PostMapping("/fast/sale")
     @ApiOperation("编辑商品闪购")
     public Result<Boolean> fastSale(@RequestBody @Validated FastSaleReq fastSaleReq) {
         FastSaleReq.checkParam(fastSaleReq);

+ 6 - 9
product-web/src/main/java/com/poyee/facade/impl/ProductInfoFacade.java

@@ -1,6 +1,5 @@
 package com.poyee.facade.impl;
 
-import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.BooleanUtil;
@@ -26,6 +25,7 @@ import com.poyee.res.ProductListRes;
 import com.poyee.service.*;
 import com.poyee.utils.I18nUtil;
 import com.poyee.utils.LocaleTimeZoneUtil;
+import com.poyee.utils.PageUtil;
 import com.poyee.utils.ServletUtils;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Component;
@@ -66,11 +66,11 @@ public class ProductInfoFacade implements IProductInfoFacade {
         if (Objects.nonNull(productSearchReq.getStatus())) {
             lambdaQueryWrapper.eq(ProductInfo::getStatus, productSearchReq.getStatus());
         }
-        List<ProductInfo> productInfos = this.productInfoService.list(lambdaQueryWrapper);
-        if (CollUtil.isEmpty(productInfos)) {
+        PageInfo<ProductInfo> productInfos = new PageInfo<>(this.productInfoService.list(lambdaQueryWrapper));
+        if (CollUtil.isEmpty(productInfos.getList())) {
             return PageInfo.emptyPageInfo();
         }
-        List<String> fastSaleSkus = productInfos.stream()
+        List<String> fastSaleSkus = productInfos.getList().stream()
                 .filter(product -> Objects.nonNull(product.getFastSaleFlag()) && product.getFastSaleFlag() == StatusEnum.TRUE.getCode())
                 .map(ProductInfo::getSku)
                 .collect(Collectors.toList());
@@ -81,7 +81,7 @@ public class ProductInfoFacade implements IProductInfoFacade {
                 .list()
                 .stream()
                 .collect(Collectors.toMap(ProductFastSale::getSku, Function.identity()));
-        List<ProductListRes> productListResList = productInfos.stream()
+        List<ProductListRes> productListResList = productInfos.getList().stream()
                 .map(productInfo -> {
                     ProductListBO productBO = productInfoMapstruct.productDo2Bo(productInfo);
                     ProductListRes productListRes = productInfoMapstruct.productBO2Res(productBO);
@@ -92,10 +92,7 @@ public class ProductInfoFacade implements IProductInfoFacade {
                     return productListRes;
                 })
                 .collect(Collectors.toList());
-        PageInfo<ProductListRes> returnPageInfo = new PageInfo<>();
-        BeanUtil.copyProperties(productInfos, returnPageInfo);
-        returnPageInfo.setList(productListResList);
-        return returnPageInfo;
+        return PageUtil.convertPage(productInfos, productListResList);
     }
 
     @Override

+ 8 - 13
product-web/src/main/java/com/poyee/facade/impl/ProductItemFacade.java

@@ -1,6 +1,5 @@
 package com.poyee.facade.impl;
 
-import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.StrUtil;
@@ -26,10 +25,10 @@ import com.poyee.service.ProductInfoService;
 import com.poyee.service.ProductItemService;
 import com.poyee.service.SysDictDataService;
 import com.poyee.utils.LocaleTimeZoneUtil;
+import com.poyee.utils.PageUtil;
 import com.poyee.utils.ServletUtils;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.annotation.Bean;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
@@ -65,16 +64,14 @@ public class ProductItemFacade implements IProductItemFacade {
         List<ProductItemListRes> productListResList = productItemPageInfo.getList()
                 .stream()
                 .map(productItem -> {
-                    //在售库存=库存-冻结库存
+                    //在售库存=库存-冻结库存,确保不小于0
                     ProductItemListRes res = productItemMapstruct.productItem2ProductItemListRes(productItem);
-                    res.setInventory(productItem.getInventory() - productItem.getFrozenInventory());
+                    int availableInventory = Math.max(0, productItem.getInventory() - productItem.getFrozenInventory());
+                    res.setInventory(availableInventory);
                     return res;
                 })
                 .collect(Collectors.toList());
-        PageInfo<ProductItemListRes> returnPageInfo = new PageInfo<>();
-        BeanUtil.copyProperties(productItemPageInfo, returnPageInfo);
-        returnPageInfo.setList(productListResList);
-        return returnPageInfo;
+        return PageUtil.convertPage(productItemPageInfo, productListResList);
     }
 
 
@@ -104,8 +101,9 @@ public class ProductItemFacade implements IProductItemFacade {
     public ProductItemDetail detail(Long id) {
         ProductItem productItem = this.productItemService.getById(id);
         Assert.notNull(productItem, "the_product_does_not_exist");
+        int availableInventory = Math.max(0, productItem.getInventory() - productItem.getFrozenInventory());
         return ProductItemDetail.builder().price(productItem.getItemPrice()).spec(productItem.getItemSpec())
-                .inventory((productItem.getInventory() - productItem.getFrozenInventory())).id(productItem.getId()).build();
+                .inventory(availableInventory).id(productItem.getId()).build();
     }
 
     @Override
@@ -138,10 +136,7 @@ public class ProductItemFacade implements IProductItemFacade {
             lambdaQueryWrapper.in(ProductItem::getId, orderServiceProductItemSearchReq.getItemList());
         }
         PageInfo<ProductItem> productItemPageInfo = new PageInfo<>(this.productItemService.list(lambdaQueryWrapper));
-        PageInfo<OrderServiceProductItemSearchRes> returnPageInfo = new PageInfo<>();
-        BeanUtil.copyProperties(productItemPageInfo, returnPageInfo);
-        returnPageInfo.setList(productItemMapstruct.convertRes(productItemPageInfo.getList()));
-        return returnPageInfo;
+        return PageUtil.convertPage(productItemPageInfo, productItemMapstruct.convertRes(productItemPageInfo.getList()));
     }
 }