From a3e7faed944bd06c19a21c98ae3b9fb787662a21 Mon Sep 17 00:00:00 2001 From: zhangsan <646228430@qq.com> Date: Tue, 20 May 2025 19:21:02 +0800 Subject: [PATCH] first commit --- .gitignore | 72 ++++++++ cart-service/pom.xml | 58 ++++++ .../java/com/hmall/cart/CartApplication.java | 14 ++ .../hmall/cart/controller/CartController.java | 53 ++++++ .../hmall/cart/domain/dto/CartFormDTO.java | 20 ++ .../java/com/hmall/cart/domain/po/Cart.java | 81 +++++++++ .../java/com/hmall/cart/domain/vo/CartVO.java | 43 +++++ .../com/hmall/cart/mapper/CartMapper.java | 21 +++ .../com/hmall/cart/service/ICartService.java | 27 +++ .../cart/service/impl/CartServiceImpl.java | 134 ++++++++++++++ .../src/main/resources/application-dev.yaml | 4 + .../src/main/resources/application-local.yaml | 4 + .../src/main/resources/application.yaml | 43 +++++ .../src/main/resources/mapper/CartMapper.xml | 5 + hm-common/pom.xml | 95 ++++++++++ .../common/advice/CommonExceptionAdvice.java | 68 +++++++ .../com/hmall/common/config/JsonConfig.java | 23 +++ .../hmall/common/config/MyBatisConfig.java | 25 +++ .../java/com/hmall/common/domain/PageDTO.java | 61 +++++++ .../com/hmall/common/domain/PageQuery.java | 69 +++++++ .../main/java/com/hmall/common/domain/R.java | 45 +++++ .../common/exception/BadRequestException.java | 16 ++ .../common/exception/BizIllegalException.java | 16 ++ .../common/exception/CommonException.java | 23 +++ .../hmall/common/exception/DbException.java | 16 ++ .../common/exception/ForbiddenException.java | 16 ++ .../exception/UnauthorizedException.java | 16 ++ .../com/hmall/common/utils/BeanUtils.java | 59 ++++++ .../com/hmall/common/utils/CollUtils.java | 72 ++++++++ .../java/com/hmall/common/utils/Convert.java | 8 + .../com/hmall/common/utils/CookieBuilder.java | 67 +++++++ .../com/hmall/common/utils/UserContext.java | 28 +++ .../java/com/hmall/common/utils/WebUtils.java | 151 ++++++++++++++++ .../spring-configuration-metadata.json | 171 ++++++++++++++++++ .../main/resources/META-INF/spring.factories | 3 + hm-service/Dockerfile | 9 + hm-service/pom.xml | 71 ++++++++ .../main/java/com/hmall/HMallApplication.java | 13 ++ .../java/com/hmall/config/AuthProperties.java | 13 ++ .../java/com/hmall/config/JwtProperties.java | 16 ++ .../main/java/com/hmall/config/MvcConfig.java | 54 ++++++ .../java/com/hmall/config/SecurityConfig.java | 33 ++++ .../hmall/controller/AddressController.java | 61 +++++++ .../com/hmall/controller/CartController.java | 54 ++++++ .../com/hmall/controller/HelloController.java | 29 +++ .../com/hmall/controller/ItemController.java | 83 +++++++++ .../com/hmall/controller/OrderController.java | 39 ++++ .../com/hmall/controller/PayController.java | 39 ++++ .../hmall/controller/SearchController.java | 39 ++++ .../com/hmall/controller/UserController.java | 38 ++++ .../java/com/hmall/domain/dto/AddressDTO.java | 28 +++ .../com/hmall/domain/dto/CartFormDTO.java | 20 ++ .../java/com/hmall/domain/dto/ItemDTO.java | 34 ++++ .../com/hmall/domain/dto/LoginFormDTO.java | 20 ++ .../com/hmall/domain/dto/OrderDetailDTO.java | 16 ++ .../com/hmall/domain/dto/OrderFormDTO.java | 18 ++ .../com/hmall/domain/dto/PayApplyDTO.java | 30 +++ .../com/hmall/domain/dto/PayOrderFormDTO.java | 20 ++ .../java/com/hmall/domain/po/Address.java | 77 ++++++++ .../main/java/com/hmall/domain/po/Cart.java | 80 ++++++++ .../main/java/com/hmall/domain/po/Item.java | 113 ++++++++++++ .../main/java/com/hmall/domain/po/Order.java | 91 ++++++++++ .../java/com/hmall/domain/po/OrderDetail.java | 80 ++++++++ .../com/hmall/domain/po/OrderLogistics.java | 86 +++++++++ .../java/com/hmall/domain/po/PayOrder.java | 123 +++++++++++++ .../main/java/com/hmall/domain/po/User.java | 66 +++++++ .../com/hmall/domain/query/ItemPageQuery.java | 23 +++ .../main/java/com/hmall/domain/vo/CartVO.java | 43 +++++ .../java/com/hmall/domain/vo/OrderVO.java | 34 ++++ .../java/com/hmall/domain/vo/PayOrderVO.java | 49 +++++ .../java/com/hmall/domain/vo/UserLoginVO.java | 11 ++ .../main/java/com/hmall/enums/PayChannel.java | 25 +++ .../main/java/com/hmall/enums/PayStatus.java | 27 +++ .../main/java/com/hmall/enums/PayType.java | 27 +++ .../main/java/com/hmall/enums/UserStatus.java | 30 +++ .../hmall/interceptor/LoginInterceptor.java | 33 ++++ .../java/com/hmall/mapper/AddressMapper.java | 16 ++ .../java/com/hmall/mapper/CartMapper.java | 20 ++ .../java/com/hmall/mapper/ItemMapper.java | 21 +++ .../com/hmall/mapper/OrderDetailMapper.java | 16 ++ .../hmall/mapper/OrderLogisticsMapper.java | 16 ++ .../java/com/hmall/mapper/OrderMapper.java | 16 ++ .../java/com/hmall/mapper/PayOrderMapper.java | 16 ++ .../java/com/hmall/mapper/UserMapper.java | 19 ++ .../com/hmall/service/IAddressService.java | 16 ++ .../java/com/hmall/service/ICartService.java | 26 +++ .../java/com/hmall/service/IItemService.java | 24 +++ .../hmall/service/IOrderDetailService.java | 16 ++ .../hmall/service/IOrderLogisticsService.java | 16 ++ .../java/com/hmall/service/IOrderService.java | 20 ++ .../com/hmall/service/IPayOrderService.java | 21 +++ .../java/com/hmall/service/IUserService.java | 21 +++ .../service/impl/AddressServiceImpl.java | 20 ++ .../hmall/service/impl/CartServiceImpl.java | 133 ++++++++++++++ .../hmall/service/impl/ItemServiceImpl.java | 46 +++++ .../service/impl/OrderDetailServiceImpl.java | 20 ++ .../impl/OrderLogisticsServiceImpl.java | 20 ++ .../hmall/service/impl/OrderServiceImpl.java | 112 ++++++++++++ .../service/impl/PayOrderServiceImpl.java | 133 ++++++++++++++ .../hmall/service/impl/UserServiceImpl.java | 85 +++++++++ .../main/java/com/hmall/utils/JwtTool.java | 82 +++++++++ .../src/main/resources/application-dev.yaml | 4 + .../src/main/resources/application-local.yaml | 4 + .../src/main/resources/application.yaml | 54 ++++++ hm-service/src/main/resources/hmall.jks | Bin 0 -> 2711 bytes .../src/main/resources/mapper/CartMapper.xml | 5 + .../src/main/resources/mapper/ItemMapper.xml | 5 + .../resources/mapper/OrderDetailMapper.xml | 5 + .../resources/mapper/OrderLogisticsMapper.xml | 5 + .../src/main/resources/mapper/OrderMapper.xml | 5 + .../main/resources/mapper/PayOrderMapper.xml | 5 + .../src/main/resources/mapper/TradeClient.xml | 5 + .../src/main/resources/mapper/UserMapper.xml | 5 + item-service/pom.xml | 58 ++++++ .../java/com/hmall/item/ItemApplication.java | 13 ++ .../hmall/item/controller/ItemController.java | 82 +++++++++ .../com/hmall/item/domain/dto/ItemDTO.java | 34 ++++ .../hmall/item/domain/dto/OrderDetailDTO.java | 16 ++ .../java/com/hmall/item/domain/po/Item.java | 113 ++++++++++++ .../item/domain/query/ItemPageQuery.java | 23 +++ .../com/hmall/item/mapper/ItemMapper.java | 21 +++ .../com/hmall/item/service/IItemService.java | 24 +++ .../item/service/impl/ItemServiceImpl.java | 46 +++++ .../src/main/resources/application-dev.yaml | 4 + .../src/main/resources/application-local.yaml | 4 + .../src/main/resources/application.yaml | 43 +++++ .../src/main/resources/mapper/ItemMapper.xml | 5 + logs/hm-service/spring.log.2024-06-01.0.gz | Bin 0 -> 4098 bytes logs/hm-service/spring.log.2025-05-19.0.gz | Bin 0 -> 8775 bytes pom.xml | 108 +++++++++++ user-service/pom.xml | 19 ++ 131 files changed, 5088 insertions(+) create mode 100644 .gitignore create mode 100644 cart-service/pom.xml create mode 100644 cart-service/src/main/java/com/hmall/cart/CartApplication.java create mode 100644 cart-service/src/main/java/com/hmall/cart/controller/CartController.java create mode 100644 cart-service/src/main/java/com/hmall/cart/domain/dto/CartFormDTO.java create mode 100644 cart-service/src/main/java/com/hmall/cart/domain/po/Cart.java create mode 100644 cart-service/src/main/java/com/hmall/cart/domain/vo/CartVO.java create mode 100644 cart-service/src/main/java/com/hmall/cart/mapper/CartMapper.java create mode 100644 cart-service/src/main/java/com/hmall/cart/service/ICartService.java create mode 100644 cart-service/src/main/java/com/hmall/cart/service/impl/CartServiceImpl.java create mode 100644 cart-service/src/main/resources/application-dev.yaml create mode 100644 cart-service/src/main/resources/application-local.yaml create mode 100644 cart-service/src/main/resources/application.yaml create mode 100644 cart-service/src/main/resources/mapper/CartMapper.xml create mode 100644 hm-common/pom.xml create mode 100644 hm-common/src/main/java/com/hmall/common/advice/CommonExceptionAdvice.java create mode 100644 hm-common/src/main/java/com/hmall/common/config/JsonConfig.java create mode 100644 hm-common/src/main/java/com/hmall/common/config/MyBatisConfig.java create mode 100644 hm-common/src/main/java/com/hmall/common/domain/PageDTO.java create mode 100644 hm-common/src/main/java/com/hmall/common/domain/PageQuery.java create mode 100644 hm-common/src/main/java/com/hmall/common/domain/R.java create mode 100644 hm-common/src/main/java/com/hmall/common/exception/BadRequestException.java create mode 100644 hm-common/src/main/java/com/hmall/common/exception/BizIllegalException.java create mode 100644 hm-common/src/main/java/com/hmall/common/exception/CommonException.java create mode 100644 hm-common/src/main/java/com/hmall/common/exception/DbException.java create mode 100644 hm-common/src/main/java/com/hmall/common/exception/ForbiddenException.java create mode 100644 hm-common/src/main/java/com/hmall/common/exception/UnauthorizedException.java create mode 100644 hm-common/src/main/java/com/hmall/common/utils/BeanUtils.java create mode 100644 hm-common/src/main/java/com/hmall/common/utils/CollUtils.java create mode 100644 hm-common/src/main/java/com/hmall/common/utils/Convert.java create mode 100644 hm-common/src/main/java/com/hmall/common/utils/CookieBuilder.java create mode 100644 hm-common/src/main/java/com/hmall/common/utils/UserContext.java create mode 100644 hm-common/src/main/java/com/hmall/common/utils/WebUtils.java create mode 100644 hm-common/src/main/resources/META-INF/spring-configuration-metadata.json create mode 100644 hm-common/src/main/resources/META-INF/spring.factories create mode 100644 hm-service/Dockerfile create mode 100644 hm-service/pom.xml create mode 100644 hm-service/src/main/java/com/hmall/HMallApplication.java create mode 100644 hm-service/src/main/java/com/hmall/config/AuthProperties.java create mode 100644 hm-service/src/main/java/com/hmall/config/JwtProperties.java create mode 100644 hm-service/src/main/java/com/hmall/config/MvcConfig.java create mode 100644 hm-service/src/main/java/com/hmall/config/SecurityConfig.java create mode 100644 hm-service/src/main/java/com/hmall/controller/AddressController.java create mode 100644 hm-service/src/main/java/com/hmall/controller/CartController.java create mode 100644 hm-service/src/main/java/com/hmall/controller/HelloController.java create mode 100644 hm-service/src/main/java/com/hmall/controller/ItemController.java create mode 100644 hm-service/src/main/java/com/hmall/controller/OrderController.java create mode 100644 hm-service/src/main/java/com/hmall/controller/PayController.java create mode 100644 hm-service/src/main/java/com/hmall/controller/SearchController.java create mode 100644 hm-service/src/main/java/com/hmall/controller/UserController.java create mode 100644 hm-service/src/main/java/com/hmall/domain/dto/AddressDTO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/dto/CartFormDTO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/dto/ItemDTO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/dto/LoginFormDTO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/dto/OrderDetailDTO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/dto/OrderFormDTO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/dto/PayApplyDTO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/dto/PayOrderFormDTO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/po/Address.java create mode 100644 hm-service/src/main/java/com/hmall/domain/po/Cart.java create mode 100644 hm-service/src/main/java/com/hmall/domain/po/Item.java create mode 100644 hm-service/src/main/java/com/hmall/domain/po/Order.java create mode 100644 hm-service/src/main/java/com/hmall/domain/po/OrderDetail.java create mode 100644 hm-service/src/main/java/com/hmall/domain/po/OrderLogistics.java create mode 100644 hm-service/src/main/java/com/hmall/domain/po/PayOrder.java create mode 100644 hm-service/src/main/java/com/hmall/domain/po/User.java create mode 100644 hm-service/src/main/java/com/hmall/domain/query/ItemPageQuery.java create mode 100644 hm-service/src/main/java/com/hmall/domain/vo/CartVO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/vo/OrderVO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/vo/PayOrderVO.java create mode 100644 hm-service/src/main/java/com/hmall/domain/vo/UserLoginVO.java create mode 100644 hm-service/src/main/java/com/hmall/enums/PayChannel.java create mode 100644 hm-service/src/main/java/com/hmall/enums/PayStatus.java create mode 100644 hm-service/src/main/java/com/hmall/enums/PayType.java create mode 100644 hm-service/src/main/java/com/hmall/enums/UserStatus.java create mode 100644 hm-service/src/main/java/com/hmall/interceptor/LoginInterceptor.java create mode 100644 hm-service/src/main/java/com/hmall/mapper/AddressMapper.java create mode 100644 hm-service/src/main/java/com/hmall/mapper/CartMapper.java create mode 100644 hm-service/src/main/java/com/hmall/mapper/ItemMapper.java create mode 100644 hm-service/src/main/java/com/hmall/mapper/OrderDetailMapper.java create mode 100644 hm-service/src/main/java/com/hmall/mapper/OrderLogisticsMapper.java create mode 100644 hm-service/src/main/java/com/hmall/mapper/OrderMapper.java create mode 100644 hm-service/src/main/java/com/hmall/mapper/PayOrderMapper.java create mode 100644 hm-service/src/main/java/com/hmall/mapper/UserMapper.java create mode 100644 hm-service/src/main/java/com/hmall/service/IAddressService.java create mode 100644 hm-service/src/main/java/com/hmall/service/ICartService.java create mode 100644 hm-service/src/main/java/com/hmall/service/IItemService.java create mode 100644 hm-service/src/main/java/com/hmall/service/IOrderDetailService.java create mode 100644 hm-service/src/main/java/com/hmall/service/IOrderLogisticsService.java create mode 100644 hm-service/src/main/java/com/hmall/service/IOrderService.java create mode 100644 hm-service/src/main/java/com/hmall/service/IPayOrderService.java create mode 100644 hm-service/src/main/java/com/hmall/service/IUserService.java create mode 100644 hm-service/src/main/java/com/hmall/service/impl/AddressServiceImpl.java create mode 100644 hm-service/src/main/java/com/hmall/service/impl/CartServiceImpl.java create mode 100644 hm-service/src/main/java/com/hmall/service/impl/ItemServiceImpl.java create mode 100644 hm-service/src/main/java/com/hmall/service/impl/OrderDetailServiceImpl.java create mode 100644 hm-service/src/main/java/com/hmall/service/impl/OrderLogisticsServiceImpl.java create mode 100644 hm-service/src/main/java/com/hmall/service/impl/OrderServiceImpl.java create mode 100644 hm-service/src/main/java/com/hmall/service/impl/PayOrderServiceImpl.java create mode 100644 hm-service/src/main/java/com/hmall/service/impl/UserServiceImpl.java create mode 100644 hm-service/src/main/java/com/hmall/utils/JwtTool.java create mode 100644 hm-service/src/main/resources/application-dev.yaml create mode 100644 hm-service/src/main/resources/application-local.yaml create mode 100644 hm-service/src/main/resources/application.yaml create mode 100644 hm-service/src/main/resources/hmall.jks create mode 100644 hm-service/src/main/resources/mapper/CartMapper.xml create mode 100644 hm-service/src/main/resources/mapper/ItemMapper.xml create mode 100644 hm-service/src/main/resources/mapper/OrderDetailMapper.xml create mode 100644 hm-service/src/main/resources/mapper/OrderLogisticsMapper.xml create mode 100644 hm-service/src/main/resources/mapper/OrderMapper.xml create mode 100644 hm-service/src/main/resources/mapper/PayOrderMapper.xml create mode 100644 hm-service/src/main/resources/mapper/TradeClient.xml create mode 100644 hm-service/src/main/resources/mapper/UserMapper.xml create mode 100644 item-service/pom.xml create mode 100644 item-service/src/main/java/com/hmall/item/ItemApplication.java create mode 100644 item-service/src/main/java/com/hmall/item/controller/ItemController.java create mode 100644 item-service/src/main/java/com/hmall/item/domain/dto/ItemDTO.java create mode 100644 item-service/src/main/java/com/hmall/item/domain/dto/OrderDetailDTO.java create mode 100644 item-service/src/main/java/com/hmall/item/domain/po/Item.java create mode 100644 item-service/src/main/java/com/hmall/item/domain/query/ItemPageQuery.java create mode 100644 item-service/src/main/java/com/hmall/item/mapper/ItemMapper.java create mode 100644 item-service/src/main/java/com/hmall/item/service/IItemService.java create mode 100644 item-service/src/main/java/com/hmall/item/service/impl/ItemServiceImpl.java create mode 100644 item-service/src/main/resources/application-dev.yaml create mode 100644 item-service/src/main/resources/application-local.yaml create mode 100644 item-service/src/main/resources/application.yaml create mode 100644 item-service/src/main/resources/mapper/ItemMapper.xml create mode 100644 logs/hm-service/spring.log.2024-06-01.0.gz create mode 100644 logs/hm-service/spring.log.2025-05-19.0.gz create mode 100644 pom.xml create mode 100644 user-service/pom.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..141f938 --- /dev/null +++ b/.gitignore @@ -0,0 +1,72 @@ +# ========== IDEA ========== +# IntelliJ IDEA 项目文件 +.idea/ +# IDEA 模块文件 +*.iml +*.iws +# IDEA 生成的工作区文件 +workspace.xml +# 代码样式、运行配置等 +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries +.idea/vcs.xml +# 防止提交本地历史 +.idea/**/localHistory/ + +# ========== 编译输出 ========== +# Maven 默认输出目录 +target/ +# Gradle 默认输出目录 +build/ + +# ========== 操作系统 ========== +# Windows 缓存文件 +Thumbs.db +ehthumbs.db +# macOS 缓存文件 +.DS_Store +.AppleDouble +.LSOverride +# Linux 缓存文件 +*~ + +# ========== 日志和临时文件 ========== +*.log +*.tmp +*.temp +*.swp + +# ========== Test 输出 ========== +test-output/ +surefire-reports/ +failsafe-reports/ + +# ========== 依赖管理 ========== +# Maven 本地仓库 +.mvn/repository/ +# Gradle 缓存(可选) +.gradle/ + +# ========== 打包文件 ========== +# Spring Boot 可执行包 +*.jar +*.war +# Spring Boot 可执行包目录 +BOOT-INF/ + +# ========== IDE 外插件 ========== +# Lombok 插件生成文件 +*.class +# JRebel 缓存 +rebel.xml + +# ========== 其它 ========== +# 环境变量文件(如包含敏感配置) +*.env +# Docker 相关 +docker-compose.override.yml + +# 如果你用到 IDEA 自带的 File-Based Storage(8+版本默认),可以添加: +# .idea/.name +# .idea/gradle.xml diff --git a/cart-service/pom.xml b/cart-service/pom.xml new file mode 100644 index 0000000..99e8c61 --- /dev/null +++ b/cart-service/pom.xml @@ -0,0 +1,58 @@ + + + + hmall + com.heima + 1.0.0 + + 4.0.0 + + cart-service + + + 17 + 17 + + + + + com.heima + hm-common + 1.0.0 + + + + org.springframework.boot + spring-boot-starter-web + + + + + mysql + mysql-connector-java + + + + com.baomidou + mybatis-plus-boot-starter + + + com.heima + hm-service + 1.0.0 + compile + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/cart-service/src/main/java/com/hmall/cart/CartApplication.java b/cart-service/src/main/java/com/hmall/cart/CartApplication.java new file mode 100644 index 0000000..502a1e7 --- /dev/null +++ b/cart-service/src/main/java/com/hmall/cart/CartApplication.java @@ -0,0 +1,14 @@ +package com.hmall.cart; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@MapperScan("com.hmall.cart.mapper") +@SpringBootApplication +public class CartApplication { + public static void main(String[] args) { + + SpringApplication.run(CartApplication.class, args); + } +} \ No newline at end of file diff --git a/cart-service/src/main/java/com/hmall/cart/controller/CartController.java b/cart-service/src/main/java/com/hmall/cart/controller/CartController.java new file mode 100644 index 0000000..bf8be0d --- /dev/null +++ b/cart-service/src/main/java/com/hmall/cart/controller/CartController.java @@ -0,0 +1,53 @@ +package com.hmall.cart.controller; + +import com.hmall.cart.domain.dto.CartFormDTO; +import com.hmall.cart.domain.po.Cart; +import com.hmall.cart.domain.vo.CartVO; +import com.hmall.cart.service.ICartService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.apache.ibatis.annotations.Param; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +@Api(tags = "购物车相关接口") +@RestController +@RequestMapping("/carts") +@RequiredArgsConstructor +public class CartController { + private final ICartService cartService; + + @ApiOperation("添加商品到购物车") + @PostMapping + public void addItem2Cart(@Valid @RequestBody CartFormDTO cartFormDTO){ + cartService.addItem2Cart(cartFormDTO); + } + + @ApiOperation("更新购物车数据") + @PutMapping + public void updateCart(@RequestBody Cart cart){ + cartService.updateById(cart); + } + + @ApiOperation("删除购物车中商品") + @DeleteMapping("{id}") + public void deleteCartItem(@Param ("购物车条目id")@PathVariable("id") Long id){ + cartService.removeById(id); + } + + @ApiOperation("查询购物车列表") + @GetMapping + public List queryMyCarts(){ + return cartService.queryMyCarts(); + } + @ApiOperation("批量删除购物车中商品") + @ApiImplicitParam(name = "ids", value = "购物车条目id集合") + @DeleteMapping + public void deleteCartItemByIds(@RequestParam("ids") List ids){ + cartService.removeByItemIds(ids); + } +} diff --git a/cart-service/src/main/java/com/hmall/cart/domain/dto/CartFormDTO.java b/cart-service/src/main/java/com/hmall/cart/domain/dto/CartFormDTO.java new file mode 100644 index 0000000..eb9cb9f --- /dev/null +++ b/cart-service/src/main/java/com/hmall/cart/domain/dto/CartFormDTO.java @@ -0,0 +1,20 @@ +package com.hmall.cart.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(description = "新增购物车商品表单实体") +public class CartFormDTO { + @ApiModelProperty("商品id") + private Long itemId; + @ApiModelProperty("商品标题") + private String name; + @ApiModelProperty("商品动态属性键值集") + private String spec; + @ApiModelProperty("价格,单位:分") + private Integer price; + @ApiModelProperty("商品图片") + private String image; +} diff --git a/cart-service/src/main/java/com/hmall/cart/domain/po/Cart.java b/cart-service/src/main/java/com/hmall/cart/domain/po/Cart.java new file mode 100644 index 0000000..5ab31e6 --- /dev/null +++ b/cart-service/src/main/java/com/hmall/cart/domain/po/Cart.java @@ -0,0 +1,81 @@ +package com.hmall.cart.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 订单详情表 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("cart") +public class Cart implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 购物车条目id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 用户id + */ + private Long userId; + + /** + * sku商品id + */ + private Long itemId; + + /** + * 购买数量 + */ + private Integer num; + + /** + * 商品标题 + */ + private String name; + + /** + * 商品动态属性键值集 + */ + private String spec; + + /** + * 价格,单位:分 + */ + private Integer price; + + /** + * 商品图片 + */ + private String image; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/cart-service/src/main/java/com/hmall/cart/domain/vo/CartVO.java b/cart-service/src/main/java/com/hmall/cart/domain/vo/CartVO.java new file mode 100644 index 0000000..27ce1e3 --- /dev/null +++ b/cart-service/src/main/java/com/hmall/cart/domain/vo/CartVO.java @@ -0,0 +1,43 @@ +package com.hmall.cart.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 订单详情表 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@ApiModel(description = "购物车VO实体") +public class CartVO { + @ApiModelProperty("购物车条目id ") + private Long id; + @ApiModelProperty("sku商品id") + private Long itemId; + @ApiModelProperty("购买数量") + private Integer num; + @ApiModelProperty("商品标题") + private String name; + @ApiModelProperty("商品动态属性键值集") + private String spec; + @ApiModelProperty("价格,单位:分") + private Integer price; + @ApiModelProperty("商品最新价格") + private Integer newPrice; + @ApiModelProperty("商品最新状态") + private Integer status = 1; + @ApiModelProperty("商品最新库存") + private Integer stock = 10; + @ApiModelProperty("商品图片") + private String image; + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/cart-service/src/main/java/com/hmall/cart/mapper/CartMapper.java b/cart-service/src/main/java/com/hmall/cart/mapper/CartMapper.java new file mode 100644 index 0000000..90cb68d --- /dev/null +++ b/cart-service/src/main/java/com/hmall/cart/mapper/CartMapper.java @@ -0,0 +1,21 @@ +package com.hmall.cart.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.hmall.cart.domain.po.Cart; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + *

+ * 订单详情表 Mapper 接口 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface CartMapper extends BaseMapper { + + @Update("UPDATE cart SET num = num + 1 WHERE user_id = #{userId} AND item_id = #{itemId}") + void updateNum(@Param("itemId") Long itemId, @Param("userId") Long userId); +} diff --git a/cart-service/src/main/java/com/hmall/cart/service/ICartService.java b/cart-service/src/main/java/com/hmall/cart/service/ICartService.java new file mode 100644 index 0000000..198e68f --- /dev/null +++ b/cart-service/src/main/java/com/hmall/cart/service/ICartService.java @@ -0,0 +1,27 @@ +package com.hmall.cart.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.hmall.cart.domain.dto.CartFormDTO; +import com.hmall.cart.domain.po.Cart; +import com.hmall.cart.domain.vo.CartVO; + + +import java.util.Collection; +import java.util.List; + +/** + *

+ * 订单详情表 服务类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface ICartService extends IService { + + void addItem2Cart(CartFormDTO cartFormDTO); + + List queryMyCarts(); + + void removeByItemIds(Collection itemIds); +} diff --git a/cart-service/src/main/java/com/hmall/cart/service/impl/CartServiceImpl.java b/cart-service/src/main/java/com/hmall/cart/service/impl/CartServiceImpl.java new file mode 100644 index 0000000..ccdec09 --- /dev/null +++ b/cart-service/src/main/java/com/hmall/cart/service/impl/CartServiceImpl.java @@ -0,0 +1,134 @@ +package com.hmall.cart.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.hmall.cart.domain.dto.CartFormDTO; +import com.hmall.cart.domain.po.Cart; +import com.hmall.cart.domain.vo.CartVO; +import com.hmall.cart.mapper.CartMapper; +import com.hmall.cart.service.ICartService; +import com.hmall.common.exception.BizIllegalException; +import com.hmall.common.utils.BeanUtils; +import com.hmall.common.utils.CollUtils; +import com.hmall.common.utils.UserContext; + +import com.hmall.domain.dto.ItemDTO; +import com.hmall.service.IItemService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + *

+ * 订单详情表 服务实现类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Service +@RequiredArgsConstructor +public class CartServiceImpl extends ServiceImpl implements ICartService { + +// private final IItemService itemService; + + @Override + public void addItem2Cart(CartFormDTO cartFormDTO) { + // 1.获取登录用户 + Long userId = UserContext.getUser(); + + // 2.判断是否已经存在 + if(checkItemExists(cartFormDTO.getItemId(), userId)){ + // 2.1.存在,则更新数量 + baseMapper.updateNum(cartFormDTO.getItemId(), userId); + return; + } + // 2.2.不存在,判断是否超过购物车数量 + checkCartsFull(userId); + + // 3.新增购物车条目 + // 3.1.转换PO + Cart cart = BeanUtils.copyBean(cartFormDTO, Cart.class); + // 3.2.保存当前用户 + cart.setUserId(userId); + // 3.3.保存到数据库 + save(cart); + } + + @Override + public List queryMyCarts() { + // 1.查询我的购物车列表 + List carts = lambdaQuery().eq(Cart::getUserId,1L /*UserContext.getUser()*/).list(); + if (CollUtils.isEmpty(carts)) { + return CollUtils.emptyList(); + } + + // 2.转换VO + List vos = BeanUtils.copyList(carts, CartVO.class); + + // 3.处理VO中的商品信息 + handleCartItems(vos); + + // 4.返回 + return vos; + } + + private void handleCartItems(List vos) { +// // 1.获取商品id +// Set itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet()); +// // 2.查询商品 +// List items = itemService.queryItemByIds(itemIds); +// if (CollUtils.isEmpty(items)) { +// return; +// } +// // 3.转为 id 到 item的map +// Map itemMap = items.stream().collect(Collectors.toMap(ItemDTO::getId, Function.identity())); +// // 4.写入vo +// for (CartVO v : vos) { +// ItemDTO item = itemMap.get(v.getItemId()); +// if (item == null) { +// continue; +// } +// v.setNewPrice(item.getPrice()); +// v.setStatus(item.getStatus()); +// v.setStock(item.getStock()); +// } + } + + @Override + public void removeByItemIds(Collection itemIds) { + // 1.构建删除条件,userId和itemId + QueryWrapper queryWrapper = new QueryWrapper(); + queryWrapper.lambda() + .eq(Cart::getUserId, UserContext.getUser()) + .in(Cart::getItemId, itemIds); + // 2.删除 + remove(queryWrapper); + } + + private void checkCartsFull(Long userId) { + long count = lambdaQuery() + .eq(Cart::getUserId, userId) + .count(); // ← 这里返回 long + if (count >= 10) { + throw new BizIllegalException( + StrUtil.format("用户购物车课程不能超过{}", 10) + ); + } + } + + private boolean checkItemExists(Long itemId, Long userId) { + long count = lambdaQuery() + .eq(Cart::getUserId, userId) + .eq(Cart::getItemId, itemId) + .count(); + return count > 0; + } +} diff --git a/cart-service/src/main/resources/application-dev.yaml b/cart-service/src/main/resources/application-dev.yaml new file mode 100644 index 0000000..a6fa71e --- /dev/null +++ b/cart-service/src/main/resources/application-dev.yaml @@ -0,0 +1,4 @@ +hm: + db: + host: mysql + pw: 123 \ No newline at end of file diff --git a/cart-service/src/main/resources/application-local.yaml b/cart-service/src/main/resources/application-local.yaml new file mode 100644 index 0000000..707fb24 --- /dev/null +++ b/cart-service/src/main/resources/application-local.yaml @@ -0,0 +1,4 @@ +hm: + db: + host: localhost # 修改为你自己的虚拟机IP地址 + pw: 123456 # 修改为docker中的MySQL密码 \ No newline at end of file diff --git a/cart-service/src/main/resources/application.yaml b/cart-service/src/main/resources/application.yaml new file mode 100644 index 0000000..78d6525 --- /dev/null +++ b/cart-service/src/main/resources/application.yaml @@ -0,0 +1,43 @@ +server: + port: 8082 +spring: + application: + name: cart-service + profiles: + active: local + datasource: + url: jdbc:mysql://${hm.db.host}:3306/hm-cart?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai + driver-class-name: com.mysql.cj.jdbc.Driver + username: root + password: ${hm.db.pw} +mybatis-plus: + configuration: + default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler + global-config: + db-config: + update-strategy: not_null + id-type: auto +logging: + level: + com.hmall: debug + pattern: + dateformat: HH:mm:ss:SSS + file: + path: "logs/${spring.application.name}" +knife4j: + enable: true + openapi: + title: 黑马商城购物车接口文档 + description: "黑马商城购物车接口文档" + email: zhangsan@itcast.cn + concat: 宇哥 + url: https://www.itcast.cn + version: v1.0.0 + group: + default: + group-name: default + api-rule: package + api-rule-resources: + - com.hmall.cart.controller + +# keytool -genkeypair -alias hmall -keyalg RSA -keypass hmall123 -keystore hmall.jks -storepass hmall123 \ No newline at end of file diff --git a/cart-service/src/main/resources/mapper/CartMapper.xml b/cart-service/src/main/resources/mapper/CartMapper.xml new file mode 100644 index 0000000..f22854a --- /dev/null +++ b/cart-service/src/main/resources/mapper/CartMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/hm-common/pom.xml b/hm-common/pom.xml new file mode 100644 index 0000000..07cc9b5 --- /dev/null +++ b/hm-common/pom.xml @@ -0,0 +1,95 @@ + + + + hmall + com.heima + 1.0.0 + + 4.0.0 + + hm-common + + + 11 + 11 + + + + + org.apache.commons + commons-pool2 + + + + cn.hutool + hutool-all + + + + org.springframework + spring-webmvc + provided + + + + org.springframework.boot + spring-boot-starter-logging + + + org.apache.tomcat.embed + tomcat-embed-core + 9.0.73 + provided + + + com.baomidou + mybatis-plus-core + ${mybatis-plus.version} + provided + + + com.baomidou + mybatis-plus-extension + ${mybatis-plus.version} + provided + + + org.hibernate.validator + hibernate-validator + + + org.springframework.boot + spring-boot-autoconfigure + + + com.github.xiaoymin + knife4j-openapi2-spring-boot-starter + 4.1.0 + + + + com.github.ben-manes.caffeine + caffeine + + + + org.springframework.amqp + spring-amqp + provided + + + + org.springframework.amqp + spring-rabbit + provided + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + provided + + + \ No newline at end of file diff --git a/hm-common/src/main/java/com/hmall/common/advice/CommonExceptionAdvice.java b/hm-common/src/main/java/com/hmall/common/advice/CommonExceptionAdvice.java new file mode 100644 index 0000000..75ae4ad --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/advice/CommonExceptionAdvice.java @@ -0,0 +1,68 @@ +package com.hmall.common.advice; + +import com.hmall.common.domain.R; +import com.hmall.common.exception.BadRequestException; +import com.hmall.common.exception.CommonException; +import com.hmall.common.exception.DbException; +import com.hmall.common.utils.WebUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.util.NestedServletException; + +import java.net.BindException; +import java.util.stream.Collectors; + +@RestControllerAdvice +@Slf4j +public class CommonExceptionAdvice { + + @ExceptionHandler(DbException.class) + public Object handleDbException(DbException e) { + log.error("mysql数据库操作异常 -> ", e); + return processResponse(e); + } + + @ExceptionHandler(CommonException.class) + public Object handleBadRequestException(CommonException e) { + log.error("自定义异常 -> {} , 异常原因:{} ",e.getClass().getName(), e.getMessage()); + log.debug("", e); + return processResponse(e); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + String msg = e.getBindingResult().getAllErrors() + .stream().map(ObjectError::getDefaultMessage) + .collect(Collectors.joining("|")); + log.error("请求参数校验异常 -> {}", msg); + log.debug("", e); + return processResponse(new BadRequestException(msg)); + } + @ExceptionHandler(BindException.class) + public Object handleBindException(BindException e) { + log.error("请求参数绑定异常 ->BindException, {}", e.getMessage()); + log.debug("", e); + return processResponse(new BadRequestException("请求参数格式错误")); + } + + @ExceptionHandler(NestedServletException.class) + public Object handleNestedServletException(NestedServletException e) { + log.error("参数异常 -> NestedServletException,{}", e.getMessage()); + log.debug("", e); + return processResponse(new BadRequestException("请求参数处理异常")); + } + + @ExceptionHandler(Exception.class) + public Object handleRuntimeException(Exception e) { + log.error("其他异常 uri : {} -> ", WebUtils.getRequest().getRequestURI(), e); + return processResponse(new CommonException("服务器内部异常", 500)); + } + + private ResponseEntity> processResponse(CommonException e){ + return ResponseEntity.status(e.getCode()).body(R.error(e)); + } +} diff --git a/hm-common/src/main/java/com/hmall/common/config/JsonConfig.java b/hm-common/src/main/java/com/hmall/common/config/JsonConfig.java new file mode 100644 index 0000000..d8fa781 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/config/JsonConfig.java @@ -0,0 +1,23 @@ +package com.hmall.common.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.math.BigInteger; + +@Configuration +@ConditionalOnClass(ObjectMapper.class) +public class JsonConfig { + @Bean + public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { + return jacksonObjectMapperBuilder -> { + // long -> string + jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance); + jacksonObjectMapperBuilder.serializerByType(BigInteger.class, ToStringSerializer.instance); + }; + } +} \ No newline at end of file diff --git a/hm-common/src/main/java/com/hmall/common/config/MyBatisConfig.java b/hm-common/src/main/java/com/hmall/common/config/MyBatisConfig.java new file mode 100644 index 0000000..8a2d463 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/config/MyBatisConfig.java @@ -0,0 +1,25 @@ +package com.hmall.common.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnClass({MybatisPlusInterceptor.class, BaseMapper.class}) +public class MyBatisConfig { + @Bean + @ConditionalOnMissingBean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 1.分页拦截器 + PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); + paginationInnerInterceptor.setMaxLimit(1000L); + interceptor.addInnerInterceptor(paginationInnerInterceptor); + return interceptor; + } +} \ No newline at end of file diff --git a/hm-common/src/main/java/com/hmall/common/domain/PageDTO.java b/hm-common/src/main/java/com/hmall/common/domain/PageDTO.java new file mode 100644 index 0000000..98eaf2b --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/domain/PageDTO.java @@ -0,0 +1,61 @@ +package com.hmall.common.domain; + + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.hmall.common.utils.BeanUtils; +import com.hmall.common.utils.CollUtils; +import com.hmall.common.utils.Convert; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PageDTO { + protected Long total; + protected Long pages; + protected List list; + + public static PageDTO empty(Long total, Long pages) { + return new PageDTO<>(total, pages, CollUtils.emptyList()); + } + public static PageDTO empty(Page page) { + return new PageDTO<>(page.getTotal(), page.getPages(), CollUtils.emptyList()); + } + + public static PageDTO of(Page page) { + if(page == null){ + return new PageDTO<>(); + } + if (CollUtils.isEmpty(page.getRecords())) { + return empty(page); + } + return new PageDTO<>(page.getTotal(), page.getPages(), page.getRecords()); + } + public static PageDTO of(Page page, Function mapper) { + if(page == null){ + return new PageDTO<>(); + } + if (CollUtils.isEmpty(page.getRecords())) { + return empty(page); + } + return new PageDTO<>(page.getTotal(), page.getPages(), + page.getRecords().stream().map(mapper).collect(Collectors.toList())); + } + public static PageDTO of(Page page, List list) { + return new PageDTO<>(page.getTotal(), page.getPages(), list); + } + + public static PageDTO of(Page page, Class clazz) { + return new PageDTO<>(page.getTotal(), page.getPages(), BeanUtils.copyList(page.getRecords(), clazz)); + } + + public static PageDTO of(Page page, Class clazz, Convert convert) { + return new PageDTO<>(page.getTotal(), page.getPages(), BeanUtils.copyList(page.getRecords(), clazz, convert)); + } +} diff --git a/hm-common/src/main/java/com/hmall/common/domain/PageQuery.java b/hm-common/src/main/java/com/hmall/common/domain/PageQuery.java new file mode 100644 index 0000000..7abcd75 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/domain/PageQuery.java @@ -0,0 +1,69 @@ +package com.hmall.common.domain; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.Min; + +@Data +@ApiModel(description = "分页查询条件") +@Accessors(chain = true) +public class PageQuery { + public static final Integer DEFAULT_PAGE_SIZE = 20; + public static final Integer DEFAULT_PAGE_NUM = 1; + @ApiModelProperty("页码") + @Min(value = 1, message = "页码不能小于1") + private Integer pageNo = DEFAULT_PAGE_NUM; + @ApiModelProperty("页码") + @Min(value = 1, message = "每页查询数量不能小于1") + private Integer pageSize = DEFAULT_PAGE_SIZE; + @ApiModelProperty("是否升序") + private Boolean isAsc = true; + @ApiModelProperty("排序方式") + private String sortBy; + + public int from(){ + return (pageNo - 1) * pageSize; + } + + public Page toMpPage(OrderItem... orderItems) { + Page page = new Page<>(pageNo, pageSize); + // 是否手动指定排序方式 + if (orderItems != null && orderItems.length > 0) { + for (OrderItem orderItem : orderItems) { + page.addOrder(orderItem); + } + return page; + } + // 前端是否有排序字段 + if (StrUtil.isNotEmpty(sortBy)){ + OrderItem orderItem = new OrderItem(); + orderItem.setAsc(isAsc); + orderItem.setColumn(sortBy); + page.addOrder(orderItem); + } + return page; + } + + public Page toMpPage(String defaultSortBy, boolean isAsc) { + if (StringUtils.isBlank(sortBy)){ + sortBy = defaultSortBy; + this.isAsc = isAsc; + } + Page page = new Page<>(pageNo, pageSize); + OrderItem orderItem = new OrderItem(); + orderItem.setAsc(this.isAsc); + orderItem.setColumn(sortBy); + page.addOrder(orderItem); + return page; + } + public Page toMpPageDefaultSortByCreateTimeDesc() { + return toMpPage("create_time", false); + } +} diff --git a/hm-common/src/main/java/com/hmall/common/domain/R.java b/hm-common/src/main/java/com/hmall/common/domain/R.java new file mode 100644 index 0000000..33bda25 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/domain/R.java @@ -0,0 +1,45 @@ +package com.hmall.common.domain; + +import com.hmall.common.exception.CommonException; +import lombok.Data; + + +@Data +public class R { + private int code; + private String msg; + private T data; + + public static R ok() { + return ok(null); + } + + public static R ok(T data) { + return new R<>(200, "OK", data); + } + + public static R error(String msg) { + return new R<>(500, msg, null); + } + + public static R error(int code, String msg) { + return new R<>(code, msg, null); + } + + public static R error(CommonException e) { + return new R<>(e.getCode(), e.getMessage(), null); + } + + public R() { + } + + public R(int code, String msg, T data) { + this.code = code; + this.msg = msg; + this.data = data; + } + + public boolean success(){ + return code == 200; + } +} diff --git a/hm-common/src/main/java/com/hmall/common/exception/BadRequestException.java b/hm-common/src/main/java/com/hmall/common/exception/BadRequestException.java new file mode 100644 index 0000000..e0618e2 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/exception/BadRequestException.java @@ -0,0 +1,16 @@ +package com.hmall.common.exception; + +public class BadRequestException extends CommonException{ + + public BadRequestException(String message) { + super(message, 400); + } + + public BadRequestException(String message, Throwable cause) { + super(message, cause, 400); + } + + public BadRequestException(Throwable cause) { + super(cause, 400); + } +} diff --git a/hm-common/src/main/java/com/hmall/common/exception/BizIllegalException.java b/hm-common/src/main/java/com/hmall/common/exception/BizIllegalException.java new file mode 100644 index 0000000..584588e --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/exception/BizIllegalException.java @@ -0,0 +1,16 @@ +package com.hmall.common.exception; + +public class BizIllegalException extends CommonException{ + + public BizIllegalException(String message) { + super(message, 500); + } + + public BizIllegalException(String message, Throwable cause) { + super(message, cause, 500); + } + + public BizIllegalException(Throwable cause) { + super(cause, 500); + } +} diff --git a/hm-common/src/main/java/com/hmall/common/exception/CommonException.java b/hm-common/src/main/java/com/hmall/common/exception/CommonException.java new file mode 100644 index 0000000..871dcf3 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/exception/CommonException.java @@ -0,0 +1,23 @@ +package com.hmall.common.exception; + +import lombok.Getter; + +@Getter +public class CommonException extends RuntimeException{ + private int code; + + public CommonException(String message, int code) { + super(message); + this.code = code; + } + + public CommonException(String message, Throwable cause, int code) { + super(message, cause); + this.code = code; + } + + public CommonException(Throwable cause, int code) { + super(cause); + this.code = code; + } +} diff --git a/hm-common/src/main/java/com/hmall/common/exception/DbException.java b/hm-common/src/main/java/com/hmall/common/exception/DbException.java new file mode 100644 index 0000000..635044a --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/exception/DbException.java @@ -0,0 +1,16 @@ +package com.hmall.common.exception; + +public class DbException extends CommonException{ + + public DbException(String message) { + super(message, 500); + } + + public DbException(String message, Throwable cause) { + super(message, cause, 500); + } + + public DbException(Throwable cause) { + super(cause, 500); + } +} diff --git a/hm-common/src/main/java/com/hmall/common/exception/ForbiddenException.java b/hm-common/src/main/java/com/hmall/common/exception/ForbiddenException.java new file mode 100644 index 0000000..05f9230 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/exception/ForbiddenException.java @@ -0,0 +1,16 @@ +package com.hmall.common.exception; + +public class ForbiddenException extends CommonException{ + + public ForbiddenException(String message) { + super(message, 403); + } + + public ForbiddenException(String message, Throwable cause) { + super(message, cause, 403); + } + + public ForbiddenException(Throwable cause) { + super(cause, 403); + } +} diff --git a/hm-common/src/main/java/com/hmall/common/exception/UnauthorizedException.java b/hm-common/src/main/java/com/hmall/common/exception/UnauthorizedException.java new file mode 100644 index 0000000..704f3d1 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/exception/UnauthorizedException.java @@ -0,0 +1,16 @@ +package com.hmall.common.exception; + +public class UnauthorizedException extends CommonException{ + + public UnauthorizedException(String message) { + super(message, 401); + } + + public UnauthorizedException(String message, Throwable cause) { + super(message, cause, 401); + } + + public UnauthorizedException(Throwable cause) { + super(cause, 401); + } +} diff --git a/hm-common/src/main/java/com/hmall/common/utils/BeanUtils.java b/hm-common/src/main/java/com/hmall/common/utils/BeanUtils.java new file mode 100644 index 0000000..eb33c2e --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/utils/BeanUtils.java @@ -0,0 +1,59 @@ +package com.hmall.common.utils; + +import cn.hutool.core.bean.BeanUtil; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 继承自 hutool 的BeanUtil,增加了bean转换时自定义转换器的功能 + */ +public class BeanUtils extends BeanUtil { + + /** + * 将原对象转换成目标对象,对于字段不匹配的字段可以使用转换器处理 + * + * @param source 原对象 + * @param clazz 目标对象的class + * @param convert 转换器 + * @param 原对象类型 + * @param 目标对象类型 + * @return 目标对象 + */ + public static T copyBean(R source, Class clazz, Convert convert) { + T target = copyBean(source, clazz); + if (convert != null) { + convert.convert(source, target); + } + return target; + } + /** + * 将原对象转换成目标对象,对于字段不匹配的字段可以使用转换器处理 + * + * @param source 原对象 + * @param clazz 目标对象的class + * @param 原对象类型 + * @param 目标对象类型 + * @return 目标对象 + */ + public static T copyBean(R source, Class clazz){ + if (source == null) { + return null; + } + return toBean(source, clazz); + } + + public static List copyList(List list, Class clazz) { + if (list == null || list.size() == 0) { + return CollUtils.emptyList(); + } + return copyToList(list, clazz); + } + + public static List copyList(List list, Class clazz, Convert convert) { + if (list == null || list.size() == 0) { + return CollUtils.emptyList(); + } + return list.stream().map(r -> copyBean(r, clazz, convert)).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/hm-common/src/main/java/com/hmall/common/utils/CollUtils.java b/hm-common/src/main/java/com/hmall/common/utils/CollUtils.java new file mode 100644 index 0000000..70121d4 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/utils/CollUtils.java @@ -0,0 +1,72 @@ +package com.hmall.common.utils; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.IterUtil; +import cn.hutool.core.util.NumberUtil; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 继承自 hutool 的集合工具类 + */ +public class CollUtils extends CollectionUtil { + + public static List emptyList() { + return Collections.emptyList(); + } + + public static Set emptySet() { + return Collections.emptySet(); + } + + public static Map emptyMap() { + return Collections.emptyMap(); + } + + public static Set singletonSet(T t) { + return Collections.singleton(t); + } + + public static List singletonList(T t) { + return Collections.singletonList(t); + } + + public static List convertToInteger(List originList){ + return CollUtils.isNotEmpty(originList) ? originList.stream().map(NumberUtil::parseInt).collect(Collectors.toList()) : null; + } + + public static List convertToLong(List originLIst){ + return CollUtils.isNotEmpty(originLIst) ? originLIst.stream().map(NumberUtil::parseLong).collect(Collectors.toList()) : null; + } + + /** + * 以 conjunction 为分隔符将集合转换为字符串 如果集合元素为数组、Iterable或Iterator,则递归组合其为字符串 + * @param collection 集合 + * @param conjunction 分隔符 + * @param 集合元素类型 + * @return 连接后的字符串 + * See Also: IterUtil.join(Iterator, CharSequence) + */ + public static String join(Collection collection, CharSequence conjunction) { + if (null == collection || collection.isEmpty()) { + return null; + } + return IterUtil.join(collection.iterator(), conjunction); + } + + public static String joinIgnoreNull(Collection collection, CharSequence conjunction) { + if (null == collection || collection.isEmpty()) { + return null; + } + StringBuilder sb = new StringBuilder(); + for (T t : collection) { + if(t == null) continue; + sb.append(t).append(","); + } + if(sb.length() <= 0){ + return null; + } + return sb.deleteCharAt(sb.length() - 1).toString(); + } +} \ No newline at end of file diff --git a/hm-common/src/main/java/com/hmall/common/utils/Convert.java b/hm-common/src/main/java/com/hmall/common/utils/Convert.java new file mode 100644 index 0000000..0f56885 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/utils/Convert.java @@ -0,0 +1,8 @@ +package com.hmall.common.utils; + +/** + * 对原对象进行计算,设置到目标对象中 + **/ +public interface Convert{ + void convert(R origin, T target); +} \ No newline at end of file diff --git a/hm-common/src/main/java/com/hmall/common/utils/CookieBuilder.java b/hm-common/src/main/java/com/hmall/common/utils/CookieBuilder.java new file mode 100644 index 0000000..8ac5dd5 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/utils/CookieBuilder.java @@ -0,0 +1,67 @@ +package com.hmall.common.utils; + +import cn.hutool.core.util.StrUtil; +import lombok.Data; +import lombok.experimental.Accessors; +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +@Slf4j +@Data +@Accessors(chain = true, fluent = true) +public class CookieBuilder { + private Charset charset = StandardCharsets.UTF_8; + private int maxAge = -1; + private String path = "/"; + private boolean httpOnly; + private String name; + private String value; + private String domain; + private final HttpServletRequest request; + private final HttpServletResponse response; + + public CookieBuilder(HttpServletRequest request, HttpServletResponse response) { + this.request = request; + this.response = response; + } + + /** + * 构建cookie,会对cookie值用UTF-8做URL编码,避免中文乱码 + */ + public void build(){ + if (response == null) { + log.error("response为null,无法写入cookie"); + return; + } + Cookie cookie = new Cookie(name, URLEncoder.encode(value, charset)); + if(StrUtil.isNotBlank(domain)) { + cookie.setDomain(domain); + }else if (request != null) { + String serverName = request.getServerName(); + serverName = StrUtil.subAfter(serverName, ".", false); + cookie.setDomain("." + serverName); + } + cookie.setHttpOnly(httpOnly); + cookie.setMaxAge(maxAge); + cookie.setPath(path); + log.debug("生成cookie,编码方式:{},【{}={},domain:{};maxAge={};path={};httpOnly={}】", + charset.name(), name, value, domain, maxAge, path, httpOnly); + response.addCookie(cookie); + } + + /** + * 利用UTF-8对cookie值解码,避免中文乱码问题 + * @param cookieValue cookie原始值 + * @return 解码后的值 + */ + public String decode(String cookieValue){ + return URLDecoder.decode(cookieValue, charset); + } +} diff --git a/hm-common/src/main/java/com/hmall/common/utils/UserContext.java b/hm-common/src/main/java/com/hmall/common/utils/UserContext.java new file mode 100644 index 0000000..d87af95 --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/utils/UserContext.java @@ -0,0 +1,28 @@ +package com.hmall.common.utils; + +public class UserContext { + private static final ThreadLocal tl = new ThreadLocal<>(); + + /** + * 保存当前登录用户信息到ThreadLocal + * @param userId 用户id + */ + public static void setUser(Long userId) { + tl.set(userId); + } + + /** + * 获取当前登录用户信息 + * @return 用户id + */ + public static Long getUser() { + return tl.get(); + } + + /** + * 移除当前登录用户信息 + */ + public static void removeUser(){ + tl.remove(); + } +} diff --git a/hm-common/src/main/java/com/hmall/common/utils/WebUtils.java b/hm-common/src/main/java/com/hmall/common/utils/WebUtils.java new file mode 100644 index 0000000..eaff08a --- /dev/null +++ b/hm-common/src/main/java/com/hmall/common/utils/WebUtils.java @@ -0,0 +1,151 @@ +package com.hmall.common.utils; + + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StringUtils; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Collection; +import java.util.Map; + +@Slf4j +public class WebUtils { + + /** + * 获取ServletRequestAttributes + * + * @return ServletRequestAttributes + */ + public static ServletRequestAttributes getServletRequestAttributes() { + RequestAttributes ra = RequestContextHolder.getRequestAttributes(); + if (ra == null) { + return null; + } + return (ServletRequestAttributes) ra; + } + + /** + * 获取request + * + * @return HttpServletRequest + */ + public static HttpServletRequest getRequest() { + ServletRequestAttributes servletRequestAttributes = getServletRequestAttributes(); + return servletRequestAttributes == null ? null : servletRequestAttributes.getRequest(); + } + + /** + * 获取response + * + * @return HttpServletResponse + */ + public static HttpServletResponse getResponse() { + ServletRequestAttributes servletRequestAttributes = getServletRequestAttributes(); + return servletRequestAttributes == null ? null : servletRequestAttributes.getResponse(); + } + + /** + * 获取request header中的内容 + * + * @param headerName 请求头名称 + * @return 请求头的值 + */ + public static String getHeader(String headerName) { + HttpServletRequest request = getRequest(); + if (request == null) { + return null; + } + return getRequest().getHeader(headerName); + } + + public static void setResponseHeader(String key, String value){ + HttpServletResponse response = getResponse(); + if (response == null) { + return; + } + response.setHeader(key, value); + } + + public static boolean isSuccess() { + HttpServletResponse response = getResponse(); + return response != null && response.getStatus() < 300; + } + + /** + * 获取请求地址中的请求参数组装成 key1=value1&key2=value2 + * 如果key对应多个值,中间使用逗号隔开例如 key1对应value1,key2对应value2,value3, key1=value1&key2=value2,value3 + * + * @param request + * @return 返回拼接字符串 + */ + public static String getParameters(HttpServletRequest request) { + Map parameterMap = request.getParameterMap(); + return getParameters(parameterMap); + } + + /** + * 获取请求地址中的请求参数组装成 key1=value1&key2=value2 + * 如果key对应多个值,中间使用逗号隔开例如 key1对应value1,key2对应value2,value3, key1=value1&key2=value2,value3 + * + * @param queries + * @return + */ + public static String getParameters(final Map queries) { + StringBuilder buffer = new StringBuilder(); + for (Map.Entry entry : queries.entrySet()) { + if(entry.getValue() instanceof String[]){ + buffer.append(entry.getKey()).append(String.join(",", ((String[])entry.getValue()))) + .append("&"); + }else if(entry.getValue() instanceof Collection){ + buffer.append(entry.getKey()).append( + CollUtil.join(((Collection)entry.getValue()),",") + ).append("&"); + } + } + return buffer.length() > 0 ? buffer.substring(0, buffer.length() - 1) : StrUtil.EMPTY; + } + + /** + * 获取请求url中的uri + * + * @param url + * @return + */ + public static String getUri(String url){ + if(StringUtils.isEmpty(url)) { + return null; + } + + String uri = url; + //uri中去掉 http:// 或者https + if(uri.contains("http://") ){ + uri = uri.replace("http://", StrUtil.EMPTY); + }else if(uri.contains("https://")){ + uri = uri.replace("https://", StrUtil.EMPTY); + } + + int endIndex = uri.length(); //uri 在url中的最后一个字符的序号+1 + if(uri.contains("?")){ + endIndex = uri.indexOf("?"); + } + return uri.substring(uri.indexOf("/"), endIndex); + } + + public static String getRemoteAddr() { + HttpServletRequest request = getRequest(); + if (request == null) { + return ""; + } + return request.getRemoteAddr(); + } + + public static CookieBuilder cookieBuilder(){ + return new CookieBuilder(getRequest(), getResponse()); + } +} diff --git a/hm-common/src/main/resources/META-INF/spring-configuration-metadata.json b/hm-common/src/main/resources/META-INF/spring-configuration-metadata.json new file mode 100644 index 0000000..c939abe --- /dev/null +++ b/hm-common/src/main/resources/META-INF/spring-configuration-metadata.json @@ -0,0 +1,171 @@ +{ + "groups": [ + { + "name": "hm.db" + }, + { + "name": "hm.mq" + }, + { + "name": "hm.swagger" + }, + { + "name": "hm.jwt", + "type": "com.hmall.config.SecurityConfig", + "sourceType": "com.hmall.config.JwtProperties" + }, + { + "name": "hm.auth", + "type": "com.hmall.config.MvcConfig", + "sourceType": "com.hmall.config.AuthProperties" + } + ], + "properties": [ + { + "name": "hm.mq.host", + "type": "java.lang.String", + "description": "rabbitmq的地址", + "defaultValue": "192.168.150.101" + }, + { + "name": "hm.mq.port", + "type": "java.lang.Integer", + "description": "rabbitmq的端口", + "defaultValue": "5672" + }, + { + "name": "hm.mq.vhost", + "type": "java.lang.String", + "description": "rabbitmq的virtual-host地址", + "defaultValue": "/hmxt" + }, + { + "name": "hm.mq.username", + "type": "java.lang.String", + "description": "rabbitmq的用户名", + "defaultValue": "hmxt" + }, + { + "name": "hm.mq.password", + "type": "java.lang.String", + "description": "rabbitmq的密码", + "defaultValue": "123321" + }, + { + "name": "hm.mq.listener.retry.enable", + "type": "java.lang.Boolean", + "description": "是否开启rabbitmq的消费者重试机制", + "defaultValue": "true" + }, + { + "name": "hm.mq.listener.retry.interval", + "type": "java.time.Duration", + "description": "消费者重试初始失败等待时长", + "defaultValue": "1000ms" + }, + { + "name": "hm.mq.listener.retry.multiplier", + "type": "java.lang.Integer", + "description": "失败等待时长的递增倍数", + "defaultValue": "1" + }, + { + "name": "hm.mq.listener.retry.max-attempts", + "type": "java.lang.Integer", + "description": "消费者重试最大重试次数", + "defaultValue": "3" + }, + { + "name": "hm.mq.listener.retry.stateless", + "type": "java.lang.Boolean", + "description": "是否是无状态,默认true", + "defaultValue": "true" + }, + { + "name": "hm.db.host", + "type": "java.lang.String", + "description": "数据库地址", + "defaultValue": "192.168.150.101" + }, + { + "name": "hm.db.port", + "type": "java.lang.Integer", + "description": "数据库端口", + "defaultValue": "3306" + }, + { + "name": "hm.db.database", + "type": "java.lang.String", + "description": "数据库database名", + "defaultValue": "" + }, + { + "name": "hm.db.un", + "type": "java.lang.String", + "description": "数据库用户名", + "defaultValue": "root" + }, + { + "name": "hm.db.pw", + "type": "java.lang.String", + "description": "数据库密码", + "defaultValue": "123" + }, + { + "name": "hm.swagger.title", + "type": "java.lang.String", + "description": "接口文档标题" + }, + { + "name": "hm.swagger.description", + "type": "java.lang.String", + "description": "接口文档描述" + }, + { + "name": "hm.swagger.email", + "type": "java.lang.String", + "description": "接口文档联系人邮箱" + }, + { + "name": "hm.swagger.concat", + "type": "java.lang.String", + "description": "接口文档联系人" + }, + { + "name": "hm.swagger.package", + "type": "java.lang.String", + "description": "接口controller扫描包" + }, + { + "name": "hm.jwt.location", + "type": "java.lang.String", + "description": "秘钥存储地址" + }, + { + "name": "hm.jwt.alias", + "type": "java.lang.String", + "description": "秘钥别名" + }, + { + "name": "hm.jwt.password", + "type": "java.lang.String", + "description": "秘钥文件密码" + }, + { + "name": "hm.jwt.tokenTTL", + "type": "java.time.Duration", + "description": "登录有效期" + }, + { + "name": "hm.auth.excludePaths", + "type": "java.util.List", + "description": "登录放行的路径" + }, + { + "name": "hm.auth.includePaths", + "type": "java.util.List", + "description": "登录拦截的路径" + } + ], + "hints": [] +} \ No newline at end of file diff --git a/hm-common/src/main/resources/META-INF/spring.factories b/hm-common/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..46f5f33 --- /dev/null +++ b/hm-common/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.hmall.common.config.MyBatisConfig,\ + com.hmall.common.config.JsonConfig \ No newline at end of file diff --git a/hm-service/Dockerfile b/hm-service/Dockerfile new file mode 100644 index 0000000..04922ae --- /dev/null +++ b/hm-service/Dockerfile @@ -0,0 +1,9 @@ +# 基础镜像 +FROM openjdk:11.0-jre-buster +# 设定时区 +ENV TZ=Asia/Shanghai +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone +# 拷贝jar包 +COPY hm-service.jar /app.jar +# 入口 +ENTRYPOINT ["java", "-jar", "/app.jar"] \ No newline at end of file diff --git a/hm-service/pom.xml b/hm-service/pom.xml new file mode 100644 index 0000000..00cc5b0 --- /dev/null +++ b/hm-service/pom.xml @@ -0,0 +1,71 @@ + + + + hmall + com.heima + 1.0.0 + + 4.0.0 + + hm-service + + + 11 + 11 + + + + + + com.heima + hm-common + 1.0.0 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.security + spring-security-crypto + + + org.springframework.security + spring-security-rsa + 1.0.9.RELEASE + + + + mysql + mysql-connector-java + + + + com.baomidou + mybatis-plus-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/hm-service/src/main/java/com/hmall/HMallApplication.java b/hm-service/src/main/java/com/hmall/HMallApplication.java new file mode 100644 index 0000000..067936c --- /dev/null +++ b/hm-service/src/main/java/com/hmall/HMallApplication.java @@ -0,0 +1,13 @@ +package com.hmall; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@MapperScan("com.hmall.mapper") +@SpringBootApplication +public class HMallApplication { + public static void main(String[] args) { + SpringApplication.run(HMallApplication.class, args); + } +} \ No newline at end of file diff --git a/hm-service/src/main/java/com/hmall/config/AuthProperties.java b/hm-service/src/main/java/com/hmall/config/AuthProperties.java new file mode 100644 index 0000000..4002eb8 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/config/AuthProperties.java @@ -0,0 +1,13 @@ +package com.hmall.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.List; + +@Data +@ConfigurationProperties(prefix = "hm.auth") +public class AuthProperties { + private List includePaths; + private List excludePaths; +} diff --git a/hm-service/src/main/java/com/hmall/config/JwtProperties.java b/hm-service/src/main/java/com/hmall/config/JwtProperties.java new file mode 100644 index 0000000..eec705d --- /dev/null +++ b/hm-service/src/main/java/com/hmall/config/JwtProperties.java @@ -0,0 +1,16 @@ +package com.hmall.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.core.io.Resource; + +import java.time.Duration; + +@Data +@ConfigurationProperties(prefix = "hm.jwt") +public class JwtProperties { + private Resource location; + private String password; + private String alias; + private Duration tokenTTL = Duration.ofMinutes(10); +} diff --git a/hm-service/src/main/java/com/hmall/config/MvcConfig.java b/hm-service/src/main/java/com/hmall/config/MvcConfig.java new file mode 100644 index 0000000..0b797c7 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/config/MvcConfig.java @@ -0,0 +1,54 @@ +package com.hmall.config; + +import cn.hutool.core.collection.CollUtil; +import com.hmall.interceptor.LoginInterceptor; +import com.hmall.utils.JwtTool; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.List; + +@Configuration +@RequiredArgsConstructor +@EnableConfigurationProperties(AuthProperties.class) +public class MvcConfig implements WebMvcConfigurer { + + private final JwtTool jwtTool; + private final AuthProperties authProperties; + +/* @Bean + public CommonExceptionAdvice commonExceptionAdvice(){ + return new CommonExceptionAdvice(); + }*/ + + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 1.添加拦截器 + LoginInterceptor loginInterceptor = new LoginInterceptor(jwtTool); + InterceptorRegistration registration = registry.addInterceptor(loginInterceptor); + // 2.配置拦截路径 + List includePaths = authProperties.getIncludePaths(); + if (CollUtil.isNotEmpty(includePaths)) { + registration.addPathPatterns(includePaths); + } + // 3.配置放行路径 + List excludePaths = authProperties.getExcludePaths(); + if (CollUtil.isNotEmpty(excludePaths)) { + registration.excludePathPatterns(excludePaths); + } + registration.excludePathPatterns( + "/error", + "/favicon.ico", + "/v2/**", + "/v3/**", + "/swagger-resources/**", + "/webjars/**", + "/doc.html" + ); + + } +} diff --git a/hm-service/src/main/java/com/hmall/config/SecurityConfig.java b/hm-service/src/main/java/com/hmall/config/SecurityConfig.java new file mode 100644 index 0000000..a8c385b --- /dev/null +++ b/hm-service/src/main/java/com/hmall/config/SecurityConfig.java @@ -0,0 +1,33 @@ +package com.hmall.config; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.rsa.crypto.KeyStoreKeyFactory; + +import java.security.KeyPair; + +@Configuration +@EnableConfigurationProperties(JwtProperties.class) +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder(){ + return new BCryptPasswordEncoder(); + } + + @Bean + public KeyPair keyPair(JwtProperties properties){ + // 获取秘钥工厂 + KeyStoreKeyFactory keyStoreKeyFactory = + new KeyStoreKeyFactory( + properties.getLocation(), + properties.getPassword().toCharArray()); + //读取钥匙对 + return keyStoreKeyFactory.getKeyPair( + properties.getAlias(), + properties.getPassword().toCharArray()); + } +} \ No newline at end of file diff --git a/hm-service/src/main/java/com/hmall/controller/AddressController.java b/hm-service/src/main/java/com/hmall/controller/AddressController.java new file mode 100644 index 0000000..2769d0c --- /dev/null +++ b/hm-service/src/main/java/com/hmall/controller/AddressController.java @@ -0,0 +1,61 @@ +package com.hmall.controller; + + +import com.hmall.common.exception.BadRequestException; +import com.hmall.common.utils.BeanUtils; +import com.hmall.common.utils.CollUtils; +import com.hmall.common.utils.UserContext; +import com.hmall.domain.dto.AddressDTO; +import com.hmall.domain.po.Address; +import com.hmall.service.IAddressService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author 虎哥 + */ +@RestController +@RequestMapping("/addresses") +@RequiredArgsConstructor +@Api(tags = "收货地址管理接口") +public class AddressController { + + private final IAddressService addressService; + + @ApiOperation("根据id查询地址") + @GetMapping("{addressId}") + public AddressDTO findAddressById(@ApiParam("地址id") @PathVariable("addressId") Long id) { + // 1.根据id查询 + Address address = addressService.getById(id); + // 2.判断当前用户 + Long userId = UserContext.getUser(); + if(!address.getUserId().equals(userId)){ + throw new BadRequestException("地址不属于当前登录用户"); + } + return BeanUtils.copyBean(address, AddressDTO.class); + } + @ApiOperation("查询当前用户地址列表") + @GetMapping + public List findMyAddresses() { + // 1.查询列表 + List
list = addressService.query().eq("user_id", UserContext.getUser()).list(); + // 2.判空 + if (CollUtils.isEmpty(list)) { + return CollUtils.emptyList(); + } + // 3.转vo + return BeanUtils.copyList(list, AddressDTO.class); + } +} diff --git a/hm-service/src/main/java/com/hmall/controller/CartController.java b/hm-service/src/main/java/com/hmall/controller/CartController.java new file mode 100644 index 0000000..94b747c --- /dev/null +++ b/hm-service/src/main/java/com/hmall/controller/CartController.java @@ -0,0 +1,54 @@ +package com.hmall.controller; + + +import com.hmall.domain.dto.CartFormDTO; +import com.hmall.domain.po.Cart; +import com.hmall.domain.vo.CartVO; +import com.hmall.service.ICartService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.apache.ibatis.annotations.Param; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +@Api(tags = "购物车相关接口") +@RestController +@RequestMapping("/carts") +@RequiredArgsConstructor +public class CartController { + private final ICartService cartService; + + @ApiOperation("添加商品到购物车") + @PostMapping + public void addItem2Cart(@Valid @RequestBody CartFormDTO cartFormDTO){ + cartService.addItem2Cart(cartFormDTO); + } + + @ApiOperation("更新购物车数据") + @PutMapping + public void updateCart(@RequestBody Cart cart){ + cartService.updateById(cart); + } + + @ApiOperation("删除购物车中商品") + @DeleteMapping("{id}") + public void deleteCartItem(@Param ("购物车条目id")@PathVariable("id") Long id){ + cartService.removeById(id); + } + + @ApiOperation("查询购物车列表") + @GetMapping + public List queryMyCarts(){ + return cartService.queryMyCarts(); + } + @ApiOperation("批量删除购物车中商品") + @ApiImplicitParam(name = "ids", value = "购物车条目id集合") + @DeleteMapping + public void deleteCartItemByIds(@RequestParam("ids") List ids){ + cartService.removeByItemIds(ids); + } +} diff --git a/hm-service/src/main/java/com/hmall/controller/HelloController.java b/hm-service/src/main/java/com/hmall/controller/HelloController.java new file mode 100644 index 0000000..7cc259d --- /dev/null +++ b/hm-service/src/main/java/com/hmall/controller/HelloController.java @@ -0,0 +1,29 @@ +package com.hmall.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +@RestController +@RequestMapping("hi") +public class HelloController { + + private final Map countMap = new HashMap<>(); + + @GetMapping + public String hello(HttpServletRequest request) throws InterruptedException { + Thread.sleep(300); + String ip = request.getRemoteAddr(); + AtomicInteger ai = countMap.get(ip); + if (ai == null) { + ai = new AtomicInteger(0); + countMap.put(ip, ai); + } + return String.format("
欢迎访问黑马商城, 这是您第%d次访问
", ai.incrementAndGet()); + } +} diff --git a/hm-service/src/main/java/com/hmall/controller/ItemController.java b/hm-service/src/main/java/com/hmall/controller/ItemController.java new file mode 100644 index 0000000..40003dd --- /dev/null +++ b/hm-service/src/main/java/com/hmall/controller/ItemController.java @@ -0,0 +1,83 @@ +package com.hmall.controller; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.hmall.common.domain.PageDTO; +import com.hmall.common.domain.PageQuery; +import com.hmall.common.utils.BeanUtils; + +import com.hmall.domain.dto.ItemDTO; +import com.hmall.domain.dto.OrderDetailDTO; +import com.hmall.domain.po.Item; +import com.hmall.service.IItemService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Api(tags = "商品管理相关接口") +@RestController +@RequestMapping("/items") +@RequiredArgsConstructor +public class ItemController { + + private final IItemService itemService; + + @ApiOperation("分页查询商品") + @GetMapping("/page") + public PageDTO queryItemByPage(PageQuery query) { + // 1.分页查询 + Page result = itemService.page(query.toMpPage("update_time", false)); + // 2.封装并返回 + return PageDTO.of(result, ItemDTO.class); + } + + @ApiOperation("根据id批量查询商品") + @GetMapping + public List queryItemByIds(@RequestParam("ids") List ids){ + return itemService.queryItemByIds(ids); + } + + @ApiOperation("根据id查询商品") + @GetMapping("{id}") + public ItemDTO queryItemById(@PathVariable("id") Long id) { + return BeanUtils.copyBean(itemService.getById(id), ItemDTO.class); + } + + @ApiOperation("新增商品") + @PostMapping + public void saveItem(@RequestBody ItemDTO item) { + // 新增 + itemService.save(BeanUtils.copyBean(item, Item.class)); + } + + @ApiOperation("更新商品状态") + @PutMapping("/status/{id}/{status}") + public void updateItemStatus(@PathVariable("id") Long id, @PathVariable("status") Integer status){ + Item item = new Item(); + item.setId(id); + item.setStatus(status); + itemService.updateById(item); + } + + @ApiOperation("更新商品") + @PutMapping + public void updateItem(@RequestBody ItemDTO item) { + // 不允许修改商品状态,所以强制设置为null,更新时,就会忽略该字段 + item.setStatus(null); + // 更新 + itemService.updateById(BeanUtils.copyBean(item, Item.class)); + } + + @ApiOperation("根据id删除商品") + @DeleteMapping("{id}") + public void deleteItemById(@PathVariable("id") Long id) { + itemService.removeById(id); + } + + @ApiOperation("批量扣减库存") + @PutMapping("/stock/deduct") + public void deductStock(@RequestBody List items){ + itemService.deductStock(items); + } +} diff --git a/hm-service/src/main/java/com/hmall/controller/OrderController.java b/hm-service/src/main/java/com/hmall/controller/OrderController.java new file mode 100644 index 0000000..55f5b8d --- /dev/null +++ b/hm-service/src/main/java/com/hmall/controller/OrderController.java @@ -0,0 +1,39 @@ +package com.hmall.controller; + +import com.hmall.common.utils.BeanUtils; +import com.hmall.domain.dto.OrderFormDTO; +import com.hmall.domain.vo.OrderVO; +import com.hmall.service.IOrderService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.apache.ibatis.annotations.Param; +import org.springframework.web.bind.annotation.*; + +@Api(tags = "订单管理接口") +@RestController +@RequestMapping("/orders") +@RequiredArgsConstructor +public class OrderController { + private final IOrderService orderService; + + @ApiOperation("根据id查询订单") + @GetMapping("{id}") + public OrderVO queryOrderById(@Param ("订单id")@PathVariable("id") Long orderId) { + return BeanUtils.copyBean(orderService.getById(orderId), OrderVO.class); + } + + @ApiOperation("创建订单") + @PostMapping + public Long createOrder(@RequestBody OrderFormDTO orderFormDTO){ + return orderService.createOrder(orderFormDTO); + } + + @ApiOperation("标记订单已支付") + @ApiImplicitParam(name = "orderId", value = "订单id", paramType = "path") + @PutMapping("/{orderId}") + public void markOrderPaySuccess(@PathVariable("orderId") Long orderId) { + orderService.markOrderPaySuccess(orderId); + } +} diff --git a/hm-service/src/main/java/com/hmall/controller/PayController.java b/hm-service/src/main/java/com/hmall/controller/PayController.java new file mode 100644 index 0000000..9316cdf --- /dev/null +++ b/hm-service/src/main/java/com/hmall/controller/PayController.java @@ -0,0 +1,39 @@ +package com.hmall.controller; + +import com.hmall.common.exception.BizIllegalException; +import com.hmall.domain.dto.PayApplyDTO; +import com.hmall.domain.dto.PayOrderFormDTO; +import com.hmall.enums.PayType; +import com.hmall.service.IPayOrderService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@Api(tags = "支付相关接口") +@RestController +@RequestMapping("pay-orders") +@RequiredArgsConstructor +public class PayController { + + private final IPayOrderService payOrderService; + + @ApiOperation("生成支付单") + @PostMapping + public String applyPayOrder(@RequestBody PayApplyDTO applyDTO){ + if(!PayType.BALANCE.equalsValue(applyDTO.getPayType())){ + // 目前只支持余额支付 + throw new BizIllegalException("抱歉,目前只支持余额支付"); + } + return payOrderService.applyPayOrder(applyDTO); + } + + @ApiOperation("尝试基于用户余额支付") + @ApiImplicitParam(value = "支付单id", name = "id") + @PostMapping("{id}") + public void tryPayOrderByBalance(@PathVariable("id") Long id, @RequestBody PayOrderFormDTO payOrderFormDTO){ + payOrderFormDTO.setId(id); + payOrderService.tryPayOrderByBalance(payOrderFormDTO); + } +} diff --git a/hm-service/src/main/java/com/hmall/controller/SearchController.java b/hm-service/src/main/java/com/hmall/controller/SearchController.java new file mode 100644 index 0000000..ca21873 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/controller/SearchController.java @@ -0,0 +1,39 @@ +package com.hmall.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.hmall.common.domain.PageDTO; +import com.hmall.domain.dto.ItemDTO; +import com.hmall.domain.po.Item; +import com.hmall.domain.query.ItemPageQuery; +import com.hmall.service.IItemService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = "搜索相关接口") +@RestController +@RequestMapping("/search") +@RequiredArgsConstructor +public class SearchController { + + private final IItemService itemService; + + @ApiOperation("搜索商品") + @GetMapping("/list") + public PageDTO search(ItemPageQuery query) { + // 分页查询 + Page result = itemService.lambdaQuery() + .like(StrUtil.isNotBlank(query.getKey()), Item::getName, query.getKey()) + .eq(StrUtil.isNotBlank(query.getBrand()), Item::getBrand, query.getBrand()) + .eq(StrUtil.isNotBlank(query.getCategory()), Item::getCategory, query.getCategory()) + .eq(Item::getStatus, 1) + .between(query.getMaxPrice() != null, Item::getPrice, query.getMinPrice(), query.getMaxPrice()) + .page(query.toMpPage("update_time", false)); + // 封装并返回 + return PageDTO.of(result, ItemDTO.class); + } +} diff --git a/hm-service/src/main/java/com/hmall/controller/UserController.java b/hm-service/src/main/java/com/hmall/controller/UserController.java new file mode 100644 index 0000000..d328c9e --- /dev/null +++ b/hm-service/src/main/java/com/hmall/controller/UserController.java @@ -0,0 +1,38 @@ +package com.hmall.controller; + +import com.hmall.domain.dto.LoginFormDTO; +import com.hmall.domain.vo.UserLoginVO; +import com.hmall.service.IUserService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +@Api(tags = "用户相关接口") +@RestController +@RequestMapping("/users") +@RequiredArgsConstructor +public class UserController { + + private final IUserService userService; + + @ApiOperation("用户登录接口") + @PostMapping("login") + public UserLoginVO login(@RequestBody @Validated LoginFormDTO loginFormDTO){ + return userService.login(loginFormDTO); + } + + @ApiOperation("扣减余额") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pw", value = "支付密码"), + @ApiImplicitParam(name = "amount", value = "支付金额") + }) + @PutMapping("/money/deduct") + public void deductMoney(@RequestParam("pw") String pw,@RequestParam("amount") Integer amount){ + userService.deductMoney(pw, amount); + } +} + diff --git a/hm-service/src/main/java/com/hmall/domain/dto/AddressDTO.java b/hm-service/src/main/java/com/hmall/domain/dto/AddressDTO.java new file mode 100644 index 0000000..8c3a617 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/dto/AddressDTO.java @@ -0,0 +1,28 @@ +package com.hmall.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(description = "收货地址实体") +public class AddressDTO { + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("省") + private String province; + @ApiModelProperty("市") + private String city; + @ApiModelProperty("县/区") + private String town; + @ApiModelProperty("手机") + private String mobile; + @ApiModelProperty("详细地址") + private String street; + @ApiModelProperty("联系人") + private String contact; + @ApiModelProperty("是否是默认 1默认 0否") + private Integer isDefault; + @ApiModelProperty("备注") + private String notes; +} diff --git a/hm-service/src/main/java/com/hmall/domain/dto/CartFormDTO.java b/hm-service/src/main/java/com/hmall/domain/dto/CartFormDTO.java new file mode 100644 index 0000000..28d0f71 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/dto/CartFormDTO.java @@ -0,0 +1,20 @@ +package com.hmall.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(description = "新增购物车商品表单实体") +public class CartFormDTO { + @ApiModelProperty("商品id") + private Long itemId; + @ApiModelProperty("商品标题") + private String name; + @ApiModelProperty("商品动态属性键值集") + private String spec; + @ApiModelProperty("价格,单位:分") + private Integer price; + @ApiModelProperty("商品图片") + private String image; +} diff --git a/hm-service/src/main/java/com/hmall/domain/dto/ItemDTO.java b/hm-service/src/main/java/com/hmall/domain/dto/ItemDTO.java new file mode 100644 index 0000000..9a109a1 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/dto/ItemDTO.java @@ -0,0 +1,34 @@ +package com.hmall.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(description = "商品实体") +public class ItemDTO { + @ApiModelProperty("商品id") + private Long id; + @ApiModelProperty("SKU名称") + private String name; + @ApiModelProperty("价格(分)") + private Integer price; + @ApiModelProperty("库存数量") + private Integer stock; + @ApiModelProperty("商品图片") + private String image; + @ApiModelProperty("类目名称") + private String category; + @ApiModelProperty("品牌名称") + private String brand; + @ApiModelProperty("规格") + private String spec; + @ApiModelProperty("销量") + private Integer sold; + @ApiModelProperty("评论数") + private Integer commentCount; + @ApiModelProperty("是否是推广广告,true/false") + private Boolean isAD; + @ApiModelProperty("商品状态 1-正常,2-下架,3-删除") + private Integer status; +} diff --git a/hm-service/src/main/java/com/hmall/domain/dto/LoginFormDTO.java b/hm-service/src/main/java/com/hmall/domain/dto/LoginFormDTO.java new file mode 100644 index 0000000..5a048d6 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/dto/LoginFormDTO.java @@ -0,0 +1,20 @@ +package com.hmall.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +@ApiModel(description = "登录表单实体") +public class LoginFormDTO { + @ApiModelProperty(value = "用户名", required = true) + @NotNull(message = "用户名不能为空") + private String username; + @NotNull(message = "密码不能为空") + @ApiModelProperty(value = "用户名", required = true) + private String password; + @ApiModelProperty(value = "是否记住我", required = false) + private Boolean rememberMe = false; +} diff --git a/hm-service/src/main/java/com/hmall/domain/dto/OrderDetailDTO.java b/hm-service/src/main/java/com/hmall/domain/dto/OrderDetailDTO.java new file mode 100644 index 0000000..b8f7eed --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/dto/OrderDetailDTO.java @@ -0,0 +1,16 @@ +package com.hmall.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +@ApiModel(description = "订单明细条目") +@Data +@Accessors(chain = true) +public class OrderDetailDTO { + @ApiModelProperty("商品id") + private Long itemId; + @ApiModelProperty("商品购买数量") + private Integer num; +} diff --git a/hm-service/src/main/java/com/hmall/domain/dto/OrderFormDTO.java b/hm-service/src/main/java/com/hmall/domain/dto/OrderFormDTO.java new file mode 100644 index 0000000..30fed22 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/dto/OrderFormDTO.java @@ -0,0 +1,18 @@ +package com.hmall.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +@ApiModel(description = "交易下单表单实体") +public class OrderFormDTO { + @ApiModelProperty("收货地址id") + private Long addressId; + @ApiModelProperty("支付类型") + private Integer paymentType; + @ApiModelProperty("下单商品列表") + private List details; +} diff --git a/hm-service/src/main/java/com/hmall/domain/dto/PayApplyDTO.java b/hm-service/src/main/java/com/hmall/domain/dto/PayApplyDTO.java new file mode 100644 index 0000000..36dd256 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/dto/PayApplyDTO.java @@ -0,0 +1,30 @@ +package com.hmall.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +@Data +@Builder +@ApiModel(description = "支付下单表单实体") +public class PayApplyDTO { + @ApiModelProperty("业务订单id不能为空") + @NotNull(message = "业务订单id不能为空") + private Long bizOrderNo; + @ApiModelProperty("支付金额必须为正数") + @Min(value = 1, message = "支付金额必须为正数") + private Integer amount; + @ApiModelProperty("支付渠道编码不能为空") + @NotNull(message = "支付渠道编码不能为空") + private String payChannelCode; + @ApiModelProperty("支付方式不能为空") + @NotNull(message = "支付方式不能为空") + private Integer payType; + @ApiModelProperty("订单中的商品信息不能为空") + @NotNull(message = "订单中的商品信息不能为空") + private String orderInfo; +} \ No newline at end of file diff --git a/hm-service/src/main/java/com/hmall/domain/dto/PayOrderFormDTO.java b/hm-service/src/main/java/com/hmall/domain/dto/PayOrderFormDTO.java new file mode 100644 index 0000000..5a4c49b --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/dto/PayOrderFormDTO.java @@ -0,0 +1,20 @@ +package com.hmall.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +@Builder +@ApiModel(description = "支付确认表单实体") +public class PayOrderFormDTO { + @ApiModelProperty("支付订单id不能为空") + @NotNull(message = "支付订单id不能为空") + private Long id; + @ApiModelProperty("支付密码") + @NotNull(message = "支付密码") + private String pw; +} \ No newline at end of file diff --git a/hm-service/src/main/java/com/hmall/domain/po/Address.java b/hm-service/src/main/java/com/hmall/domain/po/Address.java new file mode 100644 index 0000000..89c46d6 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/po/Address.java @@ -0,0 +1,77 @@ +package com.hmall.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("address") +public class Address implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 省 + */ + private String province; + + /** + * 市 + */ + private String city; + + /** + * 县/区 + */ + private String town; + + /** + * 手机 + */ + private String mobile; + + /** + * 详细地址 + */ + private String street; + + /** + * 联系人 + */ + private String contact; + + /** + * 是否是默认 1默认 0否 + */ + private Integer isDefault; + + /** + * 备注 + */ + private String notes; + + +} diff --git a/hm-service/src/main/java/com/hmall/domain/po/Cart.java b/hm-service/src/main/java/com/hmall/domain/po/Cart.java new file mode 100644 index 0000000..a9aaf61 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/po/Cart.java @@ -0,0 +1,80 @@ +package com.hmall.domain.po; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 订单详情表 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("cart") +public class Cart implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 购物车条目id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 用户id + */ + private Long userId; + + /** + * sku商品id + */ + private Long itemId; + + /** + * 购买数量 + */ + private Integer num; + + /** + * 商品标题 + */ + private String name; + + /** + * 商品动态属性键值集 + */ + private String spec; + + /** + * 价格,单位:分 + */ + private Integer price; + + /** + * 商品图片 + */ + private String image; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/hm-service/src/main/java/com/hmall/domain/po/Item.java b/hm-service/src/main/java/com/hmall/domain/po/Item.java new file mode 100644 index 0000000..af468f9 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/po/Item.java @@ -0,0 +1,113 @@ +package com.hmall.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 商品表 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("item") +public class Item implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * SKU名称 + */ + private String name; + + /** + * 价格(分) + */ + private Integer price; + + /** + * 库存数量 + */ + private Integer stock; + + /** + * 商品图片 + */ + private String image; + + /** + * 类目名称 + */ + private String category; + + /** + * 品牌名称 + */ + private String brand; + + /** + * 规格 + */ + private String spec; + + /** + * 销量 + */ + private Integer sold; + + /** + * 评论数 + */ + private Integer commentCount; + + /** + * 是否是推广广告,true/false + */ + @TableField("isAD") + private Boolean isAD; + + /** + * 商品状态 1-正常,2-下架,3-删除 + */ + private Integer status; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建人 + */ + private Long creater; + + /** + * 修改人 + */ + private Long updater; + + +} diff --git a/hm-service/src/main/java/com/hmall/domain/po/Order.java b/hm-service/src/main/java/com/hmall/domain/po/Order.java new file mode 100644 index 0000000..cc86949 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/po/Order.java @@ -0,0 +1,91 @@ +package com.hmall.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("`order`") +public class Order implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 总金额,单位为分 + */ + private Integer totalFee; + + /** + * 支付类型,1、支付宝,2、微信,3、扣减余额 + */ + private Integer paymentType; + + /** + * 用户id + */ + private Long userId; + + /** + * 订单的状态,1、未付款 2、已付款,未发货 3、已发货,未确认 4、确认收货,交易成功 5、交易取消,订单关闭 6、交易结束,已评价 + */ + private Integer status; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 支付时间 + */ + private LocalDateTime payTime; + + /** + * 发货时间 + */ + private LocalDateTime consignTime; + + /** + * 交易完成时间 + */ + private LocalDateTime endTime; + + /** + * 交易关闭时间 + */ + private LocalDateTime closeTime; + + /** + * 评价时间 + */ + private LocalDateTime commentTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/hm-service/src/main/java/com/hmall/domain/po/OrderDetail.java b/hm-service/src/main/java/com/hmall/domain/po/OrderDetail.java new file mode 100644 index 0000000..1ff6808 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/po/OrderDetail.java @@ -0,0 +1,80 @@ +package com.hmall.domain.po; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 订单详情表 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("order_detail") +public class OrderDetail implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单详情id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 订单id + */ + private Long orderId; + + /** + * sku商品id + */ + private Long itemId; + + /** + * 购买数量 + */ + private Integer num; + + /** + * 商品标题 + */ + private String name; + + /** + * 商品动态属性键值集 + */ + private String spec; + + /** + * 价格,单位:分 + */ + private Integer price; + + /** + * 商品图片 + */ + private String image; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/hm-service/src/main/java/com/hmall/domain/po/OrderLogistics.java b/hm-service/src/main/java/com/hmall/domain/po/OrderLogistics.java new file mode 100644 index 0000000..790b7f7 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/po/OrderLogistics.java @@ -0,0 +1,86 @@ +package com.hmall.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("order_logistics") +public class OrderLogistics implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id,与订单表一对一 + */ + @TableId(value = "order_id", type = IdType.INPUT) + private Long orderId; + + /** + * 物流单号 + */ + private String logisticsNumber; + + /** + * 物流公司名称 + */ + private String logisticsCompany; + + /** + * 收件人 + */ + private String contact; + + /** + * 收件人手机号码 + */ + private String mobile; + + /** + * 省 + */ + private String province; + + /** + * 市 + */ + private String city; + + /** + * 区 + */ + private String town; + + /** + * 街道 + */ + private String street; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/hm-service/src/main/java/com/hmall/domain/po/PayOrder.java b/hm-service/src/main/java/com/hmall/domain/po/PayOrder.java new file mode 100644 index 0000000..7e8f40d --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/po/PayOrder.java @@ -0,0 +1,123 @@ +package com.hmall.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 支付订单 + *

+ */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("pay_order") +public class PayOrder implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 业务订单号 + */ + private Long bizOrderNo; + + /** + * 支付单号 + */ + private Long payOrderNo; + + /** + * 支付用户id + */ + private Long bizUserId; + + /** + * 支付渠道编码 + */ + private String payChannelCode; + + /** + * 支付金额,单位分 + */ + private Integer amount; + + /** + * 支付类型,1:h5,2:小程序,3:公众号,4:扫码,5:余额支付 + */ + private Integer payType; + + /** + * 支付状态,0:待提交,1:待支付,2:支付超时或取消,3:支付成功 + */ + private Integer status; + + /** + * 拓展字段,用于传递不同渠道单独处理的字段 + */ + private String expandJson; + + /** + * 第三方返回业务码 + */ + private String resultCode; + + /** + * 第三方返回提示信息 + */ + private String resultMsg; + + /** + * 支付成功时间 + */ + private LocalDateTime paySuccessTime; + + /** + * 支付超时时间 + */ + private LocalDateTime payOverTime; + + /** + * 支付二维码链接 + */ + private String qrCodeUrl; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建人 + */ + private Long creater; + + /** + * 更新人 + */ + private Long updater; + + /** + * 逻辑删除 + */ + private Boolean isDelete; + + +} diff --git a/hm-service/src/main/java/com/hmall/domain/po/User.java b/hm-service/src/main/java/com/hmall/domain/po/User.java new file mode 100644 index 0000000..d45f74f --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/po/User.java @@ -0,0 +1,66 @@ +package com.hmall.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.hmall.enums.UserStatus; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 用户表 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("user") +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 用户名 + */ + private String username; + + /** + * 密码,加密存储 + */ + private String password; + + /** + * 注册手机号 + */ + private String phone; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + private LocalDateTime updateTime; + + /** + * 使用状态(1正常 2冻结) + */ + private UserStatus status; + + /** + * 账户余额 + */ + private Integer balance; + + +} diff --git a/hm-service/src/main/java/com/hmall/domain/query/ItemPageQuery.java b/hm-service/src/main/java/com/hmall/domain/query/ItemPageQuery.java new file mode 100644 index 0000000..852e643 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/query/ItemPageQuery.java @@ -0,0 +1,23 @@ +package com.hmall.domain.query; + +import com.hmall.common.domain.PageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(description = "商品分页查询条件") +public class ItemPageQuery extends PageQuery { + @ApiModelProperty("搜索关键字") + private String key; + @ApiModelProperty("商品分类") + private String category; + @ApiModelProperty("商品品牌") + private String brand; + @ApiModelProperty("价格最小值") + private Integer minPrice; + @ApiModelProperty("价格最大值") + private Integer maxPrice; +} diff --git a/hm-service/src/main/java/com/hmall/domain/vo/CartVO.java b/hm-service/src/main/java/com/hmall/domain/vo/CartVO.java new file mode 100644 index 0000000..3247323 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/vo/CartVO.java @@ -0,0 +1,43 @@ +package com.hmall.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 订单详情表 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@ApiModel(description = "购物车VO实体") +public class CartVO { + @ApiModelProperty("购物车条目id ") + private Long id; + @ApiModelProperty("sku商品id") + private Long itemId; + @ApiModelProperty("购买数量") + private Integer num; + @ApiModelProperty("商品标题") + private String name; + @ApiModelProperty("商品动态属性键值集") + private String spec; + @ApiModelProperty("价格,单位:分") + private Integer price; + @ApiModelProperty("商品最新价格") + private Integer newPrice; + @ApiModelProperty("商品最新状态") + private Integer status = 1; + @ApiModelProperty("商品最新库存") + private Integer stock = 10; + @ApiModelProperty("商品图片") + private String image; + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/hm-service/src/main/java/com/hmall/domain/vo/OrderVO.java b/hm-service/src/main/java/com/hmall/domain/vo/OrderVO.java new file mode 100644 index 0000000..e4a5ba4 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/vo/OrderVO.java @@ -0,0 +1,34 @@ +package com.hmall.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@ApiModel(description = "订单页面VO") +public class OrderVO { + @ApiModelProperty("订单id") + private Long id; + @ApiModelProperty("总金额,单位为分") + private Integer totalFee; + @ApiModelProperty("支付类型,1、支付宝,2、微信,3、扣减余额") + private Integer paymentType; + @ApiModelProperty("用户id") + private Long userId; + @ApiModelProperty("订单的状态,1、未付款 2、已付款,未发货 3、已发货,未确认 4、确认收货,交易成功 5、交易取消,订单关闭 6、交易结束,已评价") + private Integer status; + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + @ApiModelProperty("支付时间") + private LocalDateTime payTime; + @ApiModelProperty("发货时间") + private LocalDateTime consignTime; + @ApiModelProperty("交易完成时间") + private LocalDateTime endTime; + @ApiModelProperty("交易关闭时间") + private LocalDateTime closeTime; + @ApiModelProperty("评价时间") + private LocalDateTime commentTime; +} diff --git a/hm-service/src/main/java/com/hmall/domain/vo/PayOrderVO.java b/hm-service/src/main/java/com/hmall/domain/vo/PayOrderVO.java new file mode 100644 index 0000000..c577a55 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/vo/PayOrderVO.java @@ -0,0 +1,49 @@ +package com.hmall.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 支付订单 + *

+ */ +@Data +@ApiModel(description = "支付单vo实体") +public class PayOrderVO { + @ApiModelProperty("id") + private Long id; + @ApiModelProperty("业务订单号") + private Long bizOrderNo; + @ApiModelProperty("支付单号") + private Long payOrderNo; + @ApiModelProperty("支付用户id") + private Long bizUserId; + @ApiModelProperty("支付渠道编码") + private String payChannelCode; + @ApiModelProperty("支付金额,单位分") + private Integer amount; + @ApiModelProperty("付类型,1:h5,2:小程序,3:公众号,4:扫码,5:余额支付") + private Integer payType; + @ApiModelProperty("付状态,0:待提交,1:待支付,2:支付超时或取消,3:支付成功") + private Integer status; + @ApiModelProperty("拓展字段,用于传递不同渠道单独处理的字段") + private String expandJson; + @ApiModelProperty("第三方返回业务码") + private String resultCode; + @ApiModelProperty("第三方返回提示信息") + private String resultMsg; + @ApiModelProperty("支付成功时间") + private LocalDateTime paySuccessTime; + @ApiModelProperty("支付超时时间") + private LocalDateTime payOverTime; + @ApiModelProperty("支付二维码链接") + private String qrCodeUrl; + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + @ApiModelProperty("更新时间") + private LocalDateTime updateTime; +} diff --git a/hm-service/src/main/java/com/hmall/domain/vo/UserLoginVO.java b/hm-service/src/main/java/com/hmall/domain/vo/UserLoginVO.java new file mode 100644 index 0000000..563a664 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/domain/vo/UserLoginVO.java @@ -0,0 +1,11 @@ +package com.hmall.domain.vo; + +import lombok.Data; + +@Data +public class UserLoginVO { + private String token; + private Long userId; + private String username; + private Integer balance; +} diff --git a/hm-service/src/main/java/com/hmall/enums/PayChannel.java b/hm-service/src/main/java/com/hmall/enums/PayChannel.java new file mode 100644 index 0000000..a0e5f14 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/enums/PayChannel.java @@ -0,0 +1,25 @@ +package com.hmall.enums; + +import cn.hutool.core.util.StrUtil; +import lombok.Getter; + +@Getter +public enum PayChannel { + wxPay("微信支付"), + aliPay("支付宝支付"), + balance("余额支付"), + ; + + private final String desc; + + PayChannel(String desc) { + this.desc = desc; + } + + public static String desc(String value){ + if (StrUtil.isBlank(value)) { + return ""; + } + return PayChannel.valueOf(value).getDesc(); + } +} diff --git a/hm-service/src/main/java/com/hmall/enums/PayStatus.java b/hm-service/src/main/java/com/hmall/enums/PayStatus.java new file mode 100644 index 0000000..9540d4f --- /dev/null +++ b/hm-service/src/main/java/com/hmall/enums/PayStatus.java @@ -0,0 +1,27 @@ +package com.hmall.enums; + +import lombok.Getter; + +@Getter +public enum PayStatus { + NOT_COMMIT(0, "未提交"), + WAIT_BUYER_PAY(1, "待支付"), + TRADE_CLOSED(2, "已关闭"), + TRADE_SUCCESS(3, "支付成功"), + TRADE_FINISHED(3, "支付成功"), + ; + private final int value; + private final String desc; + + PayStatus(int value, String desc) { + this.value = value; + this.desc = desc; + } + + public boolean equalsValue(Integer value){ + if (value == null) { + return false; + } + return getValue() == value; + } +} \ No newline at end of file diff --git a/hm-service/src/main/java/com/hmall/enums/PayType.java b/hm-service/src/main/java/com/hmall/enums/PayType.java new file mode 100644 index 0000000..ad8dc6b --- /dev/null +++ b/hm-service/src/main/java/com/hmall/enums/PayType.java @@ -0,0 +1,27 @@ +package com.hmall.enums; + +import lombok.Getter; + +@Getter +public enum PayType{ + JSAPI(1, "网页支付JS"), + MINI_APP(2, "小程序支付"), + APP(3, "APP支付"), + NATIVE(4, "扫码支付"), + BALANCE(5, "余额支付"), + ; + private final int value; + private final String desc; + + PayType(int value, String desc) { + this.value = value; + this.desc = desc; + } + + public boolean equalsValue(Integer value){ + if (value == null) { + return false; + } + return getValue() == value; + } +} diff --git a/hm-service/src/main/java/com/hmall/enums/UserStatus.java b/hm-service/src/main/java/com/hmall/enums/UserStatus.java new file mode 100644 index 0000000..190d48e --- /dev/null +++ b/hm-service/src/main/java/com/hmall/enums/UserStatus.java @@ -0,0 +1,30 @@ +package com.hmall.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.hmall.common.exception.BadRequestException; +import lombok.Getter; + +@Getter +public enum UserStatus { + FROZEN(0, "禁止使用"), + NORMAL(1, "已激活"), + ; + @EnumValue + int value; + String desc; + + UserStatus(Integer value, String desc) { + this.value = value; + this.desc = desc; + } + + public static UserStatus of(int value) { + if (value == 0) { + return FROZEN; + } + if (value == 1) { + return NORMAL; + } + throw new BadRequestException("账户状态错误"); + } +} \ No newline at end of file diff --git a/hm-service/src/main/java/com/hmall/interceptor/LoginInterceptor.java b/hm-service/src/main/java/com/hmall/interceptor/LoginInterceptor.java new file mode 100644 index 0000000..f3fbe24 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/interceptor/LoginInterceptor.java @@ -0,0 +1,33 @@ +package com.hmall.interceptor; + +import com.hmall.common.utils.UserContext; +import com.hmall.utils.JwtTool; +import lombok.RequiredArgsConstructor; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@RequiredArgsConstructor +public class LoginInterceptor implements HandlerInterceptor { + + private final JwtTool jwtTool; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + // 1.获取请求头中的 token + String token = request.getHeader("authorization"); + // 2.校验token + Long userId = jwtTool.parseToken(token); + // 3.存入上下文 + UserContext.setUser(userId); + // 4.放行 + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + // 清理用户 + UserContext.removeUser(); + } +} diff --git a/hm-service/src/main/java/com/hmall/mapper/AddressMapper.java b/hm-service/src/main/java/com/hmall/mapper/AddressMapper.java new file mode 100644 index 0000000..09ac39e --- /dev/null +++ b/hm-service/src/main/java/com/hmall/mapper/AddressMapper.java @@ -0,0 +1,16 @@ +package com.hmall.mapper; + +import com.hmall.domain.po.Address; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface AddressMapper extends BaseMapper
{ + +} diff --git a/hm-service/src/main/java/com/hmall/mapper/CartMapper.java b/hm-service/src/main/java/com/hmall/mapper/CartMapper.java new file mode 100644 index 0000000..f4df4e1 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/mapper/CartMapper.java @@ -0,0 +1,20 @@ +package com.hmall.mapper; + +import com.hmall.domain.po.Cart; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + *

+ * 订单详情表 Mapper 接口 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface CartMapper extends BaseMapper { + + @Update("UPDATE cart SET num = num + 1 WHERE user_id = #{userId} AND item_id = #{itemId}") + void updateNum(@Param("itemId") Long itemId, @Param("userId") Long userId); +} diff --git a/hm-service/src/main/java/com/hmall/mapper/ItemMapper.java b/hm-service/src/main/java/com/hmall/mapper/ItemMapper.java new file mode 100644 index 0000000..4e239a6 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/mapper/ItemMapper.java @@ -0,0 +1,21 @@ +package com.hmall.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.hmall.domain.dto.OrderDetailDTO; +import com.hmall.domain.po.Item; +import org.apache.ibatis.annotations.Update; + +/** + *

+ * 商品表 Mapper 接口 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface ItemMapper extends BaseMapper { + + @Update("UPDATE item SET stock = stock - #{num} WHERE id = #{itemId}") + void updateStock(OrderDetailDTO orderDetail); +} diff --git a/hm-service/src/main/java/com/hmall/mapper/OrderDetailMapper.java b/hm-service/src/main/java/com/hmall/mapper/OrderDetailMapper.java new file mode 100644 index 0000000..747fb31 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/mapper/OrderDetailMapper.java @@ -0,0 +1,16 @@ +package com.hmall.mapper; + +import com.hmall.domain.po.OrderDetail; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单详情表 Mapper 接口 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface OrderDetailMapper extends BaseMapper { + +} diff --git a/hm-service/src/main/java/com/hmall/mapper/OrderLogisticsMapper.java b/hm-service/src/main/java/com/hmall/mapper/OrderLogisticsMapper.java new file mode 100644 index 0000000..45cd6af --- /dev/null +++ b/hm-service/src/main/java/com/hmall/mapper/OrderLogisticsMapper.java @@ -0,0 +1,16 @@ +package com.hmall.mapper; + +import com.hmall.domain.po.OrderLogistics; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface OrderLogisticsMapper extends BaseMapper { + +} diff --git a/hm-service/src/main/java/com/hmall/mapper/OrderMapper.java b/hm-service/src/main/java/com/hmall/mapper/OrderMapper.java new file mode 100644 index 0000000..478940b --- /dev/null +++ b/hm-service/src/main/java/com/hmall/mapper/OrderMapper.java @@ -0,0 +1,16 @@ +package com.hmall.mapper; + +import com.hmall.domain.po.Order; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface OrderMapper extends BaseMapper { + +} diff --git a/hm-service/src/main/java/com/hmall/mapper/PayOrderMapper.java b/hm-service/src/main/java/com/hmall/mapper/PayOrderMapper.java new file mode 100644 index 0000000..f331c37 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/mapper/PayOrderMapper.java @@ -0,0 +1,16 @@ +package com.hmall.mapper; + +import com.hmall.domain.po.PayOrder; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 支付订单 Mapper 接口 + *

+ * + * @author 虎哥 + * @since 2023-05-16 + */ +public interface PayOrderMapper extends BaseMapper { + +} diff --git a/hm-service/src/main/java/com/hmall/mapper/UserMapper.java b/hm-service/src/main/java/com/hmall/mapper/UserMapper.java new file mode 100644 index 0000000..4ec0724 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/mapper/UserMapper.java @@ -0,0 +1,19 @@ +package com.hmall.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.hmall.domain.po.User; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + *

+ * 用户表 Mapper 接口 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface UserMapper extends BaseMapper { + @Update("update user set balance = balance - ${totalFee} where id = #{userId}") + void updateMoney(@Param("userId") Long userId, @Param("totalFee") Integer totalFee); +} diff --git a/hm-service/src/main/java/com/hmall/service/IAddressService.java b/hm-service/src/main/java/com/hmall/service/IAddressService.java new file mode 100644 index 0000000..5cdb4e8 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/IAddressService.java @@ -0,0 +1,16 @@ +package com.hmall.service; + +import com.hmall.domain.po.Address; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface IAddressService extends IService
{ + +} diff --git a/hm-service/src/main/java/com/hmall/service/ICartService.java b/hm-service/src/main/java/com/hmall/service/ICartService.java new file mode 100644 index 0000000..32c9041 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/ICartService.java @@ -0,0 +1,26 @@ +package com.hmall.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.hmall.domain.dto.CartFormDTO; +import com.hmall.domain.po.Cart; +import com.hmall.domain.vo.CartVO; + +import java.util.Collection; +import java.util.List; + +/** + *

+ * 订单详情表 服务类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface ICartService extends IService { + + void addItem2Cart(CartFormDTO cartFormDTO); + + List queryMyCarts(); + + void removeByItemIds(Collection itemIds); +} diff --git a/hm-service/src/main/java/com/hmall/service/IItemService.java b/hm-service/src/main/java/com/hmall/service/IItemService.java new file mode 100644 index 0000000..18514ee --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/IItemService.java @@ -0,0 +1,24 @@ +package com.hmall.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.hmall.domain.dto.ItemDTO; +import com.hmall.domain.dto.OrderDetailDTO; +import com.hmall.domain.po.Item; + +import java.util.Collection; +import java.util.List; + +/** + *

+ * 商品表 服务类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface IItemService extends IService { + + void deductStock(List items); + + List queryItemByIds(Collection ids); +} diff --git a/hm-service/src/main/java/com/hmall/service/IOrderDetailService.java b/hm-service/src/main/java/com/hmall/service/IOrderDetailService.java new file mode 100644 index 0000000..cb25e96 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/IOrderDetailService.java @@ -0,0 +1,16 @@ +package com.hmall.service; + +import com.hmall.domain.po.OrderDetail; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 订单详情表 服务类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface IOrderDetailService extends IService { + +} diff --git a/hm-service/src/main/java/com/hmall/service/IOrderLogisticsService.java b/hm-service/src/main/java/com/hmall/service/IOrderLogisticsService.java new file mode 100644 index 0000000..c815efb --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/IOrderLogisticsService.java @@ -0,0 +1,16 @@ +package com.hmall.service; + +import com.hmall.domain.po.OrderLogistics; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface IOrderLogisticsService extends IService { + +} diff --git a/hm-service/src/main/java/com/hmall/service/IOrderService.java b/hm-service/src/main/java/com/hmall/service/IOrderService.java new file mode 100644 index 0000000..0249fb3 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/IOrderService.java @@ -0,0 +1,20 @@ +package com.hmall.service; + +import com.hmall.domain.dto.OrderFormDTO; +import com.hmall.domain.po.Order; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface IOrderService extends IService { + + Long createOrder(OrderFormDTO orderFormDTO); + + void markOrderPaySuccess(Long orderId); +} diff --git a/hm-service/src/main/java/com/hmall/service/IPayOrderService.java b/hm-service/src/main/java/com/hmall/service/IPayOrderService.java new file mode 100644 index 0000000..117f6fd --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/IPayOrderService.java @@ -0,0 +1,21 @@ +package com.hmall.service; + +import com.hmall.domain.dto.PayApplyDTO; +import com.hmall.domain.dto.PayOrderFormDTO; +import com.hmall.domain.po.PayOrder; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 支付订单 服务类 + *

+ * + * @author 虎哥 + * @since 2023-05-16 + */ +public interface IPayOrderService extends IService { + + String applyPayOrder(PayApplyDTO applyDTO); + + void tryPayOrderByBalance(PayOrderFormDTO payOrderFormDTO); +} diff --git a/hm-service/src/main/java/com/hmall/service/IUserService.java b/hm-service/src/main/java/com/hmall/service/IUserService.java new file mode 100644 index 0000000..d7626f2 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/IUserService.java @@ -0,0 +1,21 @@ +package com.hmall.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.hmall.domain.dto.LoginFormDTO; +import com.hmall.domain.po.User; +import com.hmall.domain.vo.UserLoginVO; + +/** + *

+ * 用户表 服务类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface IUserService extends IService { + + UserLoginVO login(LoginFormDTO loginFormDTO); + + void deductMoney(String pw, Integer totalFee); +} diff --git a/hm-service/src/main/java/com/hmall/service/impl/AddressServiceImpl.java b/hm-service/src/main/java/com/hmall/service/impl/AddressServiceImpl.java new file mode 100644 index 0000000..24c6d3e --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/impl/AddressServiceImpl.java @@ -0,0 +1,20 @@ +package com.hmall.service.impl; + +import com.hmall.domain.po.Address; +import com.hmall.mapper.AddressMapper; +import com.hmall.service.IAddressService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Service +public class AddressServiceImpl extends ServiceImpl implements IAddressService { + +} diff --git a/hm-service/src/main/java/com/hmall/service/impl/CartServiceImpl.java b/hm-service/src/main/java/com/hmall/service/impl/CartServiceImpl.java new file mode 100644 index 0000000..9fc791a --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/impl/CartServiceImpl.java @@ -0,0 +1,133 @@ +package com.hmall.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.hmall.common.exception.BizIllegalException; +import com.hmall.common.utils.BeanUtils; +import com.hmall.common.utils.CollUtils; +import com.hmall.common.utils.UserContext; +import com.hmall.domain.dto.CartFormDTO; +import com.hmall.domain.dto.ItemDTO; +import com.hmall.domain.po.Cart; +import com.hmall.domain.vo.CartVO; +import com.hmall.mapper.CartMapper; +import com.hmall.service.ICartService; +import com.hmall.service.IItemService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + *

+ * 订单详情表 服务实现类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Service +@RequiredArgsConstructor +public class CartServiceImpl extends ServiceImpl implements ICartService { + + private final IItemService itemService; + + @Override + public void addItem2Cart(CartFormDTO cartFormDTO) { + // 1.获取登录用户 + Long userId = UserContext.getUser(); + + // 2.判断是否已经存在 + if(checkItemExists(cartFormDTO.getItemId(), userId)){ + // 2.1.存在,则更新数量 + baseMapper.updateNum(cartFormDTO.getItemId(), userId); + return; + } + // 2.2.不存在,判断是否超过购物车数量 + checkCartsFull(userId); + + // 3.新增购物车条目 + // 3.1.转换PO + Cart cart = BeanUtils.copyBean(cartFormDTO, Cart.class); + // 3.2.保存当前用户 + cart.setUserId(userId); + // 3.3.保存到数据库 + save(cart); + } + + @Override + public List queryMyCarts() { + // 1.查询我的购物车列表 + List carts = lambdaQuery().eq(Cart::getUserId, UserContext.getUser()).list(); + if (CollUtils.isEmpty(carts)) { + return CollUtils.emptyList(); + } + + // 2.转换VO + List vos = BeanUtils.copyList(carts, CartVO.class); + + // 3.处理VO中的商品信息 + handleCartItems(vos); + + // 4.返回 + return vos; + } + + private void handleCartItems(List vos) { + // 1.获取商品id + Set itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet()); + // 2.查询商品 + List items = itemService.queryItemByIds(itemIds); + if (CollUtils.isEmpty(items)) { + return; + } + // 3.转为 id 到 item的map + Map itemMap = items.stream().collect(Collectors.toMap(ItemDTO::getId, Function.identity())); + // 4.写入vo + for (CartVO v : vos) { + ItemDTO item = itemMap.get(v.getItemId()); + if (item == null) { + continue; + } + v.setNewPrice(item.getPrice()); + v.setStatus(item.getStatus()); + v.setStock(item.getStock()); + } + } + + @Override + public void removeByItemIds(Collection itemIds) { + // 1.构建删除条件,userId和itemId + QueryWrapper queryWrapper = new QueryWrapper(); + queryWrapper.lambda() + .eq(Cart::getUserId, UserContext.getUser()) + .in(Cart::getItemId, itemIds); + // 2.删除 + remove(queryWrapper); + } + + private void checkCartsFull(Long userId) { + long count = lambdaQuery() + .eq(Cart::getUserId, userId) + .count(); // ← 这里返回 long + if (count >= 10) { + throw new BizIllegalException( + StrUtil.format("用户购物车课程不能超过{}", 10) + ); + } + } + + private boolean checkItemExists(Long itemId, Long userId) { + long count = lambdaQuery() + .eq(Cart::getUserId, userId) + .eq(Cart::getItemId, itemId) + .count(); + return count > 0; + } +} diff --git a/hm-service/src/main/java/com/hmall/service/impl/ItemServiceImpl.java b/hm-service/src/main/java/com/hmall/service/impl/ItemServiceImpl.java new file mode 100644 index 0000000..60aa6db --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/impl/ItemServiceImpl.java @@ -0,0 +1,46 @@ +package com.hmall.service.impl; + + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.hmall.common.exception.BizIllegalException; +import com.hmall.common.utils.BeanUtils; + +import com.hmall.domain.dto.ItemDTO; +import com.hmall.domain.dto.OrderDetailDTO; +import com.hmall.domain.po.Item; +import com.hmall.mapper.ItemMapper; +import com.hmall.service.IItemService; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; + +/** + *

+ * 商品表 服务实现类 + *

+ * + * @author 虎哥 + */ +@Service +public class ItemServiceImpl extends ServiceImpl implements IItemService { + + @Override + public void deductStock(List items) { + String sqlStatement = "com.hmall.item.mapper.ItemMapper.updateStock"; + boolean r = false; + try { + r = executeBatch(items, (sqlSession, entity) -> sqlSession.update(sqlStatement, entity)); + } catch (Exception e) { + throw new BizIllegalException("更新库存异常,可能是库存不足!", e); + } + if (!r) { + throw new BizIllegalException("库存不足!"); + } + } + + @Override + public List queryItemByIds(Collection ids) { + return BeanUtils.copyList(listByIds(ids), ItemDTO.class); + } +} diff --git a/hm-service/src/main/java/com/hmall/service/impl/OrderDetailServiceImpl.java b/hm-service/src/main/java/com/hmall/service/impl/OrderDetailServiceImpl.java new file mode 100644 index 0000000..13bd1d9 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/impl/OrderDetailServiceImpl.java @@ -0,0 +1,20 @@ +package com.hmall.service.impl; + +import com.hmall.domain.po.OrderDetail; +import com.hmall.mapper.OrderDetailMapper; +import com.hmall.service.IOrderDetailService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单详情表 服务实现类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Service +public class OrderDetailServiceImpl extends ServiceImpl implements IOrderDetailService { + +} diff --git a/hm-service/src/main/java/com/hmall/service/impl/OrderLogisticsServiceImpl.java b/hm-service/src/main/java/com/hmall/service/impl/OrderLogisticsServiceImpl.java new file mode 100644 index 0000000..e8cd888 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/impl/OrderLogisticsServiceImpl.java @@ -0,0 +1,20 @@ +package com.hmall.service.impl; + +import com.hmall.domain.po.OrderLogistics; +import com.hmall.mapper.OrderLogisticsMapper; +import com.hmall.service.IOrderLogisticsService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Service +public class OrderLogisticsServiceImpl extends ServiceImpl implements IOrderLogisticsService { + +} diff --git a/hm-service/src/main/java/com/hmall/service/impl/OrderServiceImpl.java b/hm-service/src/main/java/com/hmall/service/impl/OrderServiceImpl.java new file mode 100644 index 0000000..c2e3411 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/impl/OrderServiceImpl.java @@ -0,0 +1,112 @@ +package com.hmall.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.hmall.common.exception.BadRequestException; +import com.hmall.common.utils.UserContext; +import com.hmall.domain.dto.ItemDTO; +import com.hmall.domain.dto.OrderDetailDTO; +import com.hmall.domain.dto.OrderFormDTO; +import com.hmall.domain.po.Order; +import com.hmall.domain.po.OrderDetail; +import com.hmall.mapper.OrderMapper; +import com.hmall.service.ICartService; +import com.hmall.service.IItemService; +import com.hmall.service.IOrderDetailService; +import com.hmall.service.IOrderService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + *

+ * 服务实现类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Service +@RequiredArgsConstructor +public class OrderServiceImpl extends ServiceImpl implements IOrderService { + + private final IItemService itemService; + private final IOrderDetailService detailService; + private final ICartService cartService; + + @Override + @Transactional + public Long createOrder(OrderFormDTO orderFormDTO) { + // 1.订单数据 + Order order = new Order(); + // 1.1.查询商品 + List detailDTOS = orderFormDTO.getDetails(); + // 1.2.获取商品id和数量的Map + Map itemNumMap = detailDTOS.stream() + .collect(Collectors.toMap(OrderDetailDTO::getItemId, OrderDetailDTO::getNum)); + Set itemIds = itemNumMap.keySet(); + // 1.3.查询商品 + List items = itemService.queryItemByIds(itemIds); + if (items == null || items.size() < itemIds.size()) { + throw new BadRequestException("商品不存在"); + } + // 1.4.基于商品价格、购买数量计算商品总价:totalFee + int total = 0; + for (ItemDTO item : items) { + total += item.getPrice() * itemNumMap.get(item.getId()); + } + order.setTotalFee(total); + // 1.5.其它属性 + order.setPaymentType(orderFormDTO.getPaymentType()); + order.setUserId(UserContext.getUser()); + order.setStatus(1); + // 1.6.将Order写入数据库order表中 + save(order); + + // 2.保存订单详情 + List details = buildDetails(order.getId(), items, itemNumMap); + detailService.saveBatch(details); + + // 3.清理购物车商品 + cartService.removeByItemIds(itemIds); + + // 4.扣减库存 + try { + itemService.deductStock(detailDTOS); + } catch (Exception e) { + throw new RuntimeException("库存不足!"); + } + return order.getId(); + } + + @Override + public void markOrderPaySuccess(Long orderId) { + Order order = new Order(); + order.setId(orderId); + order.setStatus(2); + order.setPayTime(LocalDateTime.now()); + updateById(order); + } + + private List buildDetails(Long orderId, List items, Map numMap) { + List details = new ArrayList<>(items.size()); + for (ItemDTO item : items) { + OrderDetail detail = new OrderDetail(); + detail.setName(item.getName()); + detail.setSpec(item.getSpec()); + detail.setPrice(item.getPrice()); + detail.setNum(numMap.get(item.getId())); + detail.setItemId(item.getId()); + detail.setImage(item.getImage()); + detail.setOrderId(orderId); + details.add(detail); + } + return details; + } +} diff --git a/hm-service/src/main/java/com/hmall/service/impl/PayOrderServiceImpl.java b/hm-service/src/main/java/com/hmall/service/impl/PayOrderServiceImpl.java new file mode 100644 index 0000000..5048e02 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/impl/PayOrderServiceImpl.java @@ -0,0 +1,133 @@ +package com.hmall.service.impl; + +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.hmall.common.exception.BizIllegalException; +import com.hmall.common.utils.BeanUtils; +import com.hmall.common.utils.UserContext; +import com.hmall.domain.dto.PayApplyDTO; +import com.hmall.domain.dto.PayOrderFormDTO; +import com.hmall.domain.po.Order; +import com.hmall.domain.po.PayOrder; +import com.hmall.enums.PayStatus; +import com.hmall.mapper.PayOrderMapper; +import com.hmall.service.IOrderService; +import com.hmall.service.IPayOrderService; +import com.hmall.service.IUserService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +/** + *

+ * 支付订单 服务实现类 + *

+ * + * @author 虎哥 + * @since 2023-05-16 + */ +@Service +@RequiredArgsConstructor +public class PayOrderServiceImpl extends ServiceImpl implements IPayOrderService { + + private final IUserService userService; + + private final IOrderService orderService; + + @Override + public String applyPayOrder(PayApplyDTO applyDTO) { + // 1.幂等性校验 + PayOrder payOrder = checkIdempotent(applyDTO); + // 2.返回结果 + return payOrder.getId().toString(); + } + + @Override + @Transactional + public void tryPayOrderByBalance(PayOrderFormDTO payOrderFormDTO) { + // 1.查询支付单 + PayOrder po = getById(payOrderFormDTO.getId()); + // 2.判断状态 + if(!PayStatus.WAIT_BUYER_PAY.equalsValue(po.getStatus())){ + // 订单不是未支付,状态异常 + throw new BizIllegalException("交易已支付或关闭!"); + } + // 3.尝试扣减余额 + userService.deductMoney(payOrderFormDTO.getPw(), po.getAmount()); + // 4.修改支付单状态 + boolean success = markPayOrderSuccess(payOrderFormDTO.getId(), LocalDateTime.now()); + if (!success) { + throw new BizIllegalException("交易已支付或关闭!"); + } + // 5.修改订单状态 + Order order = new Order(); + order.setId(po.getBizOrderNo()); + order.setStatus(2); + order.setPayTime(LocalDateTime.now()); + orderService.updateById(order); + } + + public boolean markPayOrderSuccess(Long id, LocalDateTime successTime) { + return lambdaUpdate() + .set(PayOrder::getStatus, PayStatus.TRADE_SUCCESS.getValue()) + .set(PayOrder::getPaySuccessTime, successTime) + .eq(PayOrder::getId, id) + // 支付状态的乐观锁判断 + .in(PayOrder::getStatus, PayStatus.NOT_COMMIT.getValue(), PayStatus.WAIT_BUYER_PAY.getValue()) + .update(); + } + + + private PayOrder checkIdempotent(PayApplyDTO applyDTO) { + // 1.首先查询支付单 + PayOrder oldOrder = queryByBizOrderNo(applyDTO.getBizOrderNo()); + // 2.判断是否存在 + if (oldOrder == null) { + // 不存在支付单,说明是第一次,写入新的支付单并返回 + PayOrder payOrder = buildPayOrder(applyDTO); + payOrder.setPayOrderNo(IdWorker.getId()); + save(payOrder); + return payOrder; + } + // 3.旧单已经存在,判断是否支付成功 + if (PayStatus.TRADE_SUCCESS.equalsValue(oldOrder.getStatus())) { + // 已经支付成功,抛出异常 + throw new BizIllegalException("订单已经支付!"); + } + // 4.旧单已经存在,判断是否已经关闭 + if (PayStatus.TRADE_CLOSED.equalsValue(oldOrder.getStatus())) { + // 已经关闭,抛出异常 + throw new BizIllegalException("订单已关闭"); + } + // 5.旧单已经存在,判断支付渠道是否一致 + if (!StringUtils.equals(oldOrder.getPayChannelCode(), applyDTO.getPayChannelCode())) { + // 支付渠道不一致,需要重置数据,然后重新申请支付单 + PayOrder payOrder = buildPayOrder(applyDTO); + payOrder.setId(oldOrder.getId()); + payOrder.setQrCodeUrl(""); + updateById(payOrder); + payOrder.setPayOrderNo(oldOrder.getPayOrderNo()); + return payOrder; + } + // 6.旧单已经存在,且可能是未支付或未提交,且支付渠道一致,直接返回旧数据 + return oldOrder; + } + + private PayOrder buildPayOrder(PayApplyDTO payApplyDTO) { + // 1.数据转换 + PayOrder payOrder = BeanUtils.toBean(payApplyDTO, PayOrder.class); + // 2.初始化数据 + payOrder.setPayOverTime(LocalDateTime.now().plusMinutes(120L)); + payOrder.setStatus(PayStatus.WAIT_BUYER_PAY.getValue()); + payOrder.setBizUserId(UserContext.getUser()); + return payOrder; + } + public PayOrder queryByBizOrderNo(Long bizOrderNo) { + return lambdaQuery() + .eq(PayOrder::getBizOrderNo, bizOrderNo) + .one(); + } +} diff --git a/hm-service/src/main/java/com/hmall/service/impl/UserServiceImpl.java b/hm-service/src/main/java/com/hmall/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..57df208 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/service/impl/UserServiceImpl.java @@ -0,0 +1,85 @@ +package com.hmall.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.hmall.common.exception.BadRequestException; +import com.hmall.common.exception.BizIllegalException; +import com.hmall.common.exception.ForbiddenException; +import com.hmall.common.utils.UserContext; +import com.hmall.config.JwtProperties; +import com.hmall.domain.dto.LoginFormDTO; +import com.hmall.domain.po.User; +import com.hmall.domain.vo.UserLoginVO; +import com.hmall.enums.UserStatus; +import com.hmall.mapper.UserMapper; +import com.hmall.service.IUserService; +import com.hmall.utils.JwtTool; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +/** + *

+ * 用户表 服务实现类 + *

+ * + * @author 虎哥 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class UserServiceImpl extends ServiceImpl implements IUserService { + + private final PasswordEncoder passwordEncoder; + + private final JwtTool jwtTool; + + private final JwtProperties jwtProperties; + + @Override + public UserLoginVO login(LoginFormDTO loginDTO) { + // 1.数据校验 + String username = loginDTO.getUsername(); + String password = loginDTO.getPassword(); + // 2.根据用户名或手机号查询 + User user = lambdaQuery().eq(User::getUsername, username).one(); + Assert.notNull(user, "用户名错误"); + // 3.校验是否禁用 + if (user.getStatus() == UserStatus.FROZEN) { + throw new ForbiddenException("用户被冻结"); + } + // 4.校验密码 + if (!passwordEncoder.matches(password, user.getPassword())) { + throw new BadRequestException("用户名或密码错误"); + } + // 5.生成TOKEN + String token = jwtTool.createToken(user.getId(), jwtProperties.getTokenTTL()); + // 6.封装VO返回 + UserLoginVO vo = new UserLoginVO(); + vo.setUserId(user.getId()); + vo.setUsername(user.getUsername()); + vo.setBalance(user.getBalance()); + vo.setToken(token); + return vo; + } + + @Override + public void deductMoney(String pw, Integer totalFee) { + log.info("开始扣款"); + // 1.校验密码 + User user = getById(UserContext.getUser()); + if(user == null || !passwordEncoder.matches(pw, user.getPassword())){ + // 密码错误 + throw new BizIllegalException("用户密码错误"); + } + + // 2.尝试扣款 + try { + baseMapper.updateMoney(UserContext.getUser(), totalFee); + } catch (Exception e) { + throw new RuntimeException("扣款失败,可能是余额不足!", e); + } + log.info("扣款成功"); + } +} diff --git a/hm-service/src/main/java/com/hmall/utils/JwtTool.java b/hm-service/src/main/java/com/hmall/utils/JwtTool.java new file mode 100644 index 0000000..e321d04 --- /dev/null +++ b/hm-service/src/main/java/com/hmall/utils/JwtTool.java @@ -0,0 +1,82 @@ +package com.hmall.utils; + +import cn.hutool.core.exceptions.ValidateException; +import cn.hutool.jwt.JWT; +import cn.hutool.jwt.JWTValidator; +import cn.hutool.jwt.signers.JWTSigner; +import cn.hutool.jwt.signers.JWTSignerUtil; +import com.hmall.common.exception.UnauthorizedException; +import org.springframework.stereotype.Component; + +import java.security.KeyPair; +import java.time.Duration; +import java.util.Date; + +@Component +public class JwtTool { + private final JWTSigner jwtSigner; + + public JwtTool(KeyPair keyPair) { + this.jwtSigner = JWTSignerUtil.createSigner("rs256", keyPair); + } + + /** + * 创建 access-token + * + * @param userDTO 用户信息 + * @return access-token + */ + public String createToken(Long userId, Duration ttl) { + // 1.生成jws + return JWT.create() + .setPayload("user", userId) + .setExpiresAt(new Date(System.currentTimeMillis() + ttl.toMillis())) + .setSigner(jwtSigner) + .sign(); + } + + /** + * 解析token + * + * @param token token + * @return 解析刷新token得到的用户信息 + */ + public Long parseToken(String token) { + // 1.校验token是否为空 + if (token == null) { + throw new UnauthorizedException("未登录"); + } + // 2.校验并解析jwt + JWT jwt; + try { + jwt = JWT.of(token).setSigner(jwtSigner); + } catch (Exception e) { + throw new UnauthorizedException("无效的token", e); + } + // 2.校验jwt是否有效 + if (!jwt.verify()) { + // 验证失败 + throw new UnauthorizedException("无效的token"); + } + // 3.校验是否过期 + try { + JWTValidator.of(jwt).validateDate(); + } catch (ValidateException e) { + throw new UnauthorizedException("token已经过期"); + } + // 4.数据格式校验 + Object userPayload = jwt.getPayload("user"); + if (userPayload == null) { + // 数据为空 + throw new UnauthorizedException("无效的token"); + } + + // 5.数据解析 + try { + return Long.valueOf(userPayload.toString()); + } catch (RuntimeException e) { + // 数据格式有误 + throw new UnauthorizedException("无效的token"); + } + } +} \ No newline at end of file diff --git a/hm-service/src/main/resources/application-dev.yaml b/hm-service/src/main/resources/application-dev.yaml new file mode 100644 index 0000000..a6fa71e --- /dev/null +++ b/hm-service/src/main/resources/application-dev.yaml @@ -0,0 +1,4 @@ +hm: + db: + host: mysql + pw: 123 \ No newline at end of file diff --git a/hm-service/src/main/resources/application-local.yaml b/hm-service/src/main/resources/application-local.yaml new file mode 100644 index 0000000..707fb24 --- /dev/null +++ b/hm-service/src/main/resources/application-local.yaml @@ -0,0 +1,4 @@ +hm: + db: + host: localhost # 修改为你自己的虚拟机IP地址 + pw: 123456 # 修改为docker中的MySQL密码 \ No newline at end of file diff --git a/hm-service/src/main/resources/application.yaml b/hm-service/src/main/resources/application.yaml new file mode 100644 index 0000000..cac3313 --- /dev/null +++ b/hm-service/src/main/resources/application.yaml @@ -0,0 +1,54 @@ +server: + port: 8080 +spring: + application: + name: hm-service + profiles: + active: local + datasource: + url: jdbc:mysql://${hm.db.host}:3306/hmall?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai + driver-class-name: com.mysql.cj.jdbc.Driver + username: root + password: ${hm.db.pw} +mybatis-plus: + configuration: + default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler + global-config: + db-config: + update-strategy: not_null + id-type: auto +logging: + level: + com.hmall: debug + pattern: + dateformat: HH:mm:ss:SSS + file: + path: "logs/${spring.application.name}" +knife4j: + enable: true + openapi: + title: 黑马商城接口文档 + description: "黑马商城接口文档" + email: zhanghuyi@itcast.cn + concat: 虎哥 + url: https://www.itcast.cn + version: v1.0.0 + group: + default: + group-name: default + api-rule: package + api-rule-resources: + - com.hmall.controller +hm: + jwt: + location: classpath:hmall.jks + alias: hmall + password: hmall123 + tokenTTL: 30m + auth: + excludePaths: + - /search/** + - /users/login + - /items/** + - /hi +# keytool -genkeypair -alias hmall -keyalg RSA -keypass hmall123 -keystore hmall.jks -storepass hmall123 \ No newline at end of file diff --git a/hm-service/src/main/resources/hmall.jks b/hm-service/src/main/resources/hmall.jks new file mode 100644 index 0000000000000000000000000000000000000000..a34bd33d09d4c33b13769213e6c07c2267cce162 GIT binary patch literal 2711 zcma)+cQhM}8pe}ILhLW9P(T2^2!cTX2w^D9HO>_1K?erP zf!Uc1xM1i=8tQB9Awe=@l?En&N0I{yr?ks8q1gUD&77!=1Il1w;7shw{+Js>*%oqg zSaod~_JhF?7#x(IlDw`8d&6Rn{fmebw+~9^WwB($~{W{}M zpGa6hl2804zbZ5mHOUf*nNvZHABX#t3QXF9<9Y*-0gO2do~=SNqIbGdb$}Y)1C8 zXyuL#^haq!isIQ=PhfX)K0*-oToJxIUrTVp-UBAmhGS%wbeA9{FxRv$+Zlf#2D| zMJPQu*9*5PmUNM8e3M^%bkgcZQgd9U7qYXEdv5k)!7bFtdeIZcmx8??ATNnJa!L8_ zq>D3x$L$92p-sjtn0T9$LkF<>#xIN+!}2799QHL><8SfuG*Vo*Uw0dM+3D^J7RLGV zEVdc_`3EY^N@%yzh@V8a?vqzkNa^f(>Fhkp2F#sE#o4g+33mG7RHuthC*=ki2k@VP zI9Y{g%iz(_dUpMWE(~zYwi5-SopTQ(Ug-h8Geoe5vJhjvCQkdnw zhQY@{A*x+HudUCz?t2zh-F9Nt<_>~A={_Evb9{1qtE$8XZX$z%b&tA-cWUfLL^$F< zefSyUbsPieS>?MB9k2E?_h9O53vuM+98wx#CMb4&_SN0k>&3Lt{Lex1>n3vpS=hBt z;iee+B4-058Pj9_=_&CHIYQDE)hYAVr~(YPeL#D*-u_K!`&rhW^-fqAA~B#et&y%3 zh+U42Ee#L}<_2DgXbsoYfSn<~&) zPAuX;y7D?am}5j@gLPS|lf7r2oX&Jm`F8_#NGUx7a8Z6_;Ih-@@Xf8)8$_Eb-a{ug zlbMlzTku5T;)B%kvQjA)ZX7T2=J+(PT^&!{>oQ-*iKjhp_mL-Cci_Z1Yt}IC;&Je_ zQGe!`FXu3mC>QG8<7v4rf<=))YP7EDZVauv!1B1U0;ilS8DDMQ92(7W2VVFi|-SfYKtfYRN9Wp1Gfyy=9BhjP7J zzHpH6rn84Xd%1e)&Tu9}h>-AwXAVsAvgz;JpzhBV6W0wybUaF|-M7lF27g}Nz{RA` ztLPyFe%B?8TZLJK5#R;z1z-R;01hGkkHn+G4d%R#_4N=_(a=&;)lySYQB_mdKoG$A z-%s>VG68(|7xDuE0l${#KML@Fm2{gBo?s0-dQ(_!0nRM#r?rzVyk!q_YTy!Iq z{qe%~o7z^B=4b0t!lLM1lQ2s9ovH!hdW`xdR0AH3!M^$PX5{1kh?cCrXVaQf8SpkV(G z;$ih>F6ZPoId*Fmz4pd(rMG`9uUAV!Hdzbx@?)5FpUAJEG<+#kt-QV)M{~-tL3(OK z0k@oWin}_43UlNem~W)VERM?YixKY`*FVa@eCx2|@V3pXS*QH1U|r$0l~ms59{OoG z_hzw5*z40b8fI;mp40d?IIhcW8iV`6Bs1dhbW}ZnAm(h^3#7 z{sbPTc-9oy=)oB&kYL}$eJt|$uvgGAmn6;fv0mMu_o_LSu~c#zr0eexhge@A(MZnK zYjzqltUoI`T5i65c`#ohqZaX`v<=%XnfyIsl@ZrLQUBt|kMe=)ugtQ$C*smS9>#`f z^ABuErq!HX>EdW!&%%x|ZMJ)@jGZc$XiEd9bRAz&A>@$L zxlxwP!)E&Vf?@t{vvo#Yc!b2kxb7O)SF4M+(=$+N17nGYwW{;rxWE~fJE%W7)cEIV zGG)dUD;!+3mKSXCM@V7%wxYB}PU%@s7W8{KrzR1hhY&}=pb&XhI*=d)0Oo$!({e_C uQpH62W+}}XVj|zYG4BNCPS~2Erd)e6g7$a0VPy&!oz{sz1 + + + + diff --git a/hm-service/src/main/resources/mapper/ItemMapper.xml b/hm-service/src/main/resources/mapper/ItemMapper.xml new file mode 100644 index 0000000..95597f1 --- /dev/null +++ b/hm-service/src/main/resources/mapper/ItemMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/hm-service/src/main/resources/mapper/OrderDetailMapper.xml b/hm-service/src/main/resources/mapper/OrderDetailMapper.xml new file mode 100644 index 0000000..c79277d --- /dev/null +++ b/hm-service/src/main/resources/mapper/OrderDetailMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/hm-service/src/main/resources/mapper/OrderLogisticsMapper.xml b/hm-service/src/main/resources/mapper/OrderLogisticsMapper.xml new file mode 100644 index 0000000..bb4feb1 --- /dev/null +++ b/hm-service/src/main/resources/mapper/OrderLogisticsMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/hm-service/src/main/resources/mapper/OrderMapper.xml b/hm-service/src/main/resources/mapper/OrderMapper.xml new file mode 100644 index 0000000..a7969a5 --- /dev/null +++ b/hm-service/src/main/resources/mapper/OrderMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/hm-service/src/main/resources/mapper/PayOrderMapper.xml b/hm-service/src/main/resources/mapper/PayOrderMapper.xml new file mode 100644 index 0000000..9e40c40 --- /dev/null +++ b/hm-service/src/main/resources/mapper/PayOrderMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/hm-service/src/main/resources/mapper/TradeClient.xml b/hm-service/src/main/resources/mapper/TradeClient.xml new file mode 100644 index 0000000..28c06ab --- /dev/null +++ b/hm-service/src/main/resources/mapper/TradeClient.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/hm-service/src/main/resources/mapper/UserMapper.xml b/hm-service/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..e885a29 --- /dev/null +++ b/hm-service/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/item-service/pom.xml b/item-service/pom.xml new file mode 100644 index 0000000..eb305e1 --- /dev/null +++ b/item-service/pom.xml @@ -0,0 +1,58 @@ + + + + hmall + com.heima + 1.0.0 + + 4.0.0 + + item-service + + + 17 + 17 + + + + + com.heima + hm-common + 1.0.0 + + + + org.springframework.boot + spring-boot-starter-web + + + + + mysql + mysql-connector-java + + + + com.baomidou + mybatis-plus-boot-starter + + + com.heima + hm-service + 1.0.0 + compile + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/item-service/src/main/java/com/hmall/item/ItemApplication.java b/item-service/src/main/java/com/hmall/item/ItemApplication.java new file mode 100644 index 0000000..e76b736 --- /dev/null +++ b/item-service/src/main/java/com/hmall/item/ItemApplication.java @@ -0,0 +1,13 @@ +package com.hmall.item; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@MapperScan("com.hmall.item.mapper") +@SpringBootApplication +public class ItemApplication { + public static void main(String[] args) { + SpringApplication.run(ItemApplication.class, args); + } +} \ No newline at end of file diff --git a/item-service/src/main/java/com/hmall/item/controller/ItemController.java b/item-service/src/main/java/com/hmall/item/controller/ItemController.java new file mode 100644 index 0000000..f1d3c4a --- /dev/null +++ b/item-service/src/main/java/com/hmall/item/controller/ItemController.java @@ -0,0 +1,82 @@ +package com.hmall.item.controller; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.hmall.common.domain.PageDTO; +import com.hmall.common.domain.PageQuery; +import com.hmall.common.utils.BeanUtils; +import com.hmall.item.domain.dto.ItemDTO; +import com.hmall.item.domain.dto.OrderDetailDTO; +import com.hmall.item.domain.po.Item; +import com.hmall.item.service.IItemService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Api(tags = "商品管理相关接口") +@RestController +@RequestMapping("/items") +@RequiredArgsConstructor +public class ItemController { + + private final IItemService itemService; + + @ApiOperation("分页查询商品") + @GetMapping("/page") + public PageDTO queryItemByPage(PageQuery query) { + // 1.分页查询 + Page result = itemService.page(query.toMpPage("update_time", false)); + // 2.封装并返回 + return PageDTO.of(result, ItemDTO.class); + } + + @ApiOperation("根据id批量查询商品") + @GetMapping + public List queryItemByIds(@RequestParam("ids") List ids){ + return itemService.queryItemByIds(ids); + } + + @ApiOperation("根据id查询商品") + @GetMapping("{id}") + public ItemDTO queryItemById(@PathVariable("id") Long id) { + return BeanUtils.copyBean(itemService.getById(id), ItemDTO.class); + } + + @ApiOperation("新增商品") + @PostMapping + public void saveItem(@RequestBody ItemDTO item) { + // 新增 + itemService.save(BeanUtils.copyBean(item, Item.class)); + } + + @ApiOperation("更新商品状态") + @PutMapping("/status/{id}/{status}") + public void updateItemStatus(@PathVariable("id") Long id, @PathVariable("status") Integer status){ + Item item = new Item(); + item.setId(id); + item.setStatus(status); + itemService.updateById(item); + } + + @ApiOperation("更新商品") + @PutMapping + public void updateItem(@RequestBody ItemDTO item) { + // 不允许修改商品状态,所以强制设置为null,更新时,就会忽略该字段 + item.setStatus(null); + // 更新 + itemService.updateById(BeanUtils.copyBean(item, Item.class)); + } + + @ApiOperation("根据id删除商品") + @DeleteMapping("{id}") + public void deleteItemById(@PathVariable("id") Long id) { + itemService.removeById(id); + } + + @ApiOperation("批量扣减库存") + @PutMapping("/stock/deduct") + public void deductStock(@RequestBody List items){ + itemService.deductStock(items); + } +} diff --git a/item-service/src/main/java/com/hmall/item/domain/dto/ItemDTO.java b/item-service/src/main/java/com/hmall/item/domain/dto/ItemDTO.java new file mode 100644 index 0000000..457f16d --- /dev/null +++ b/item-service/src/main/java/com/hmall/item/domain/dto/ItemDTO.java @@ -0,0 +1,34 @@ +package com.hmall.item.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(description = "商品实体") +public class ItemDTO { + @ApiModelProperty("商品id") + private Long id; + @ApiModelProperty("SKU名称") + private String name; + @ApiModelProperty("价格(分)") + private Integer price; + @ApiModelProperty("库存数量") + private Integer stock; + @ApiModelProperty("商品图片") + private String image; + @ApiModelProperty("类目名称") + private String category; + @ApiModelProperty("品牌名称") + private String brand; + @ApiModelProperty("规格") + private String spec; + @ApiModelProperty("销量") + private Integer sold; + @ApiModelProperty("评论数") + private Integer commentCount; + @ApiModelProperty("是否是推广广告,true/false") + private Boolean isAD; + @ApiModelProperty("商品状态 1-正常,2-下架,3-删除") + private Integer status; +} diff --git a/item-service/src/main/java/com/hmall/item/domain/dto/OrderDetailDTO.java b/item-service/src/main/java/com/hmall/item/domain/dto/OrderDetailDTO.java new file mode 100644 index 0000000..6d2088b --- /dev/null +++ b/item-service/src/main/java/com/hmall/item/domain/dto/OrderDetailDTO.java @@ -0,0 +1,16 @@ +package com.hmall.item.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +@ApiModel(description = "订单明细条目") +@Data +@Accessors(chain = true) +public class OrderDetailDTO { + @ApiModelProperty("商品id") + private Long itemId; + @ApiModelProperty("商品购买数量") + private Integer num; +} diff --git a/item-service/src/main/java/com/hmall/item/domain/po/Item.java b/item-service/src/main/java/com/hmall/item/domain/po/Item.java new file mode 100644 index 0000000..dda3a95 --- /dev/null +++ b/item-service/src/main/java/com/hmall/item/domain/po/Item.java @@ -0,0 +1,113 @@ +package com.hmall.item.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 商品表 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("item") +public class Item implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商品id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * SKU名称 + */ + private String name; + + /** + * 价格(分) + */ + private Integer price; + + /** + * 库存数量 + */ + private Integer stock; + + /** + * 商品图片 + */ + private String image; + + /** + * 类目名称 + */ + private String category; + + /** + * 品牌名称 + */ + private String brand; + + /** + * 规格 + */ + private String spec; + + /** + * 销量 + */ + private Integer sold; + + /** + * 评论数 + */ + private Integer commentCount; + + /** + * 是否是推广广告,true/false + */ + @TableField("isAD") + private Boolean isAD; + + /** + * 商品状态 1-正常,2-下架,3-删除 + */ + private Integer status; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建人 + */ + private Long creater; + + /** + * 修改人 + */ + private Long updater; + + +} diff --git a/item-service/src/main/java/com/hmall/item/domain/query/ItemPageQuery.java b/item-service/src/main/java/com/hmall/item/domain/query/ItemPageQuery.java new file mode 100644 index 0000000..bff2ca4 --- /dev/null +++ b/item-service/src/main/java/com/hmall/item/domain/query/ItemPageQuery.java @@ -0,0 +1,23 @@ +package com.hmall.item.domain.query; + +import com.hmall.common.domain.PageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(description = "商品分页查询条件") +public class ItemPageQuery extends PageQuery { + @ApiModelProperty("搜索关键字") + private String key; + @ApiModelProperty("商品分类") + private String category; + @ApiModelProperty("商品品牌") + private String brand; + @ApiModelProperty("价格最小值") + private Integer minPrice; + @ApiModelProperty("价格最大值") + private Integer maxPrice; +} diff --git a/item-service/src/main/java/com/hmall/item/mapper/ItemMapper.java b/item-service/src/main/java/com/hmall/item/mapper/ItemMapper.java new file mode 100644 index 0000000..179ff7a --- /dev/null +++ b/item-service/src/main/java/com/hmall/item/mapper/ItemMapper.java @@ -0,0 +1,21 @@ +package com.hmall.item.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.hmall.item.domain.po.Item; +import com.hmall.item.domain.dto.OrderDetailDTO; +import org.apache.ibatis.annotations.Update; + +/** + *

+ * 商品表 Mapper 接口 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface ItemMapper extends BaseMapper { + + @Update("UPDATE item SET stock = stock - #{num} WHERE id = #{itemId}") + void updateStock(OrderDetailDTO orderDetail); +} diff --git a/item-service/src/main/java/com/hmall/item/service/IItemService.java b/item-service/src/main/java/com/hmall/item/service/IItemService.java new file mode 100644 index 0000000..dfe6a9e --- /dev/null +++ b/item-service/src/main/java/com/hmall/item/service/IItemService.java @@ -0,0 +1,24 @@ +package com.hmall.item.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.hmall.item.domain.dto.ItemDTO; +import com.hmall.item.domain.dto.OrderDetailDTO; +import com.hmall.item.domain.po.Item; + +import java.util.Collection; +import java.util.List; + +/** + *

+ * 商品表 服务类 + *

+ * + * @author 虎哥 + * @since 2023-05-05 + */ +public interface IItemService extends IService { + + void deductStock(List items); + + List queryItemByIds(Collection ids); +} diff --git a/item-service/src/main/java/com/hmall/item/service/impl/ItemServiceImpl.java b/item-service/src/main/java/com/hmall/item/service/impl/ItemServiceImpl.java new file mode 100644 index 0000000..f7fcc1d --- /dev/null +++ b/item-service/src/main/java/com/hmall/item/service/impl/ItemServiceImpl.java @@ -0,0 +1,46 @@ +package com.hmall.item.service.impl; + + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.hmall.common.exception.BizIllegalException; + +import com.hmall.common.utils.BeanUtils; +import com.hmall.item.domain.dto.ItemDTO; +import com.hmall.item.domain.dto.OrderDetailDTO; +import com.hmall.item.domain.po.Item; +import com.hmall.item.mapper.ItemMapper; +import com.hmall.item.service.IItemService; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; + +/** + *

+ * 商品表 服务实现类 + *

+ * + * @author 虎哥 + */ +@Service +public class ItemServiceImpl extends ServiceImpl implements IItemService { + + @Override + public void deductStock(List items) { + String sqlStatement = "com.hmall.item.mapper.ItemMapper.updateStock"; + boolean r = false; + try { + r = executeBatch(items, (sqlSession, entity) -> sqlSession.update(sqlStatement, entity)); + } catch (Exception e) { + throw new BizIllegalException("更新库存异常,可能是库存不足!", e); + } + if (!r) { + throw new BizIllegalException("库存不足!"); + } + } + + @Override + public List queryItemByIds(Collection ids) { + return BeanUtils.copyList(listByIds(ids), ItemDTO.class); + } +} diff --git a/item-service/src/main/resources/application-dev.yaml b/item-service/src/main/resources/application-dev.yaml new file mode 100644 index 0000000..a6fa71e --- /dev/null +++ b/item-service/src/main/resources/application-dev.yaml @@ -0,0 +1,4 @@ +hm: + db: + host: mysql + pw: 123 \ No newline at end of file diff --git a/item-service/src/main/resources/application-local.yaml b/item-service/src/main/resources/application-local.yaml new file mode 100644 index 0000000..707fb24 --- /dev/null +++ b/item-service/src/main/resources/application-local.yaml @@ -0,0 +1,4 @@ +hm: + db: + host: localhost # 修改为你自己的虚拟机IP地址 + pw: 123456 # 修改为docker中的MySQL密码 \ No newline at end of file diff --git a/item-service/src/main/resources/application.yaml b/item-service/src/main/resources/application.yaml new file mode 100644 index 0000000..b564328 --- /dev/null +++ b/item-service/src/main/resources/application.yaml @@ -0,0 +1,43 @@ +server: + port: 8081 +spring: + application: + name: item-service + profiles: + active: local + datasource: + url: jdbc:mysql://${hm.db.host}:3306/hm-item?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai + driver-class-name: com.mysql.cj.jdbc.Driver + username: root + password: ${hm.db.pw} +mybatis-plus: + configuration: + default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler + global-config: + db-config: + update-strategy: not_null + id-type: auto +logging: + level: + com.hmall: debug + pattern: + dateformat: HH:mm:ss:SSS + file: + path: "logs/${spring.application.name}" +knife4j: + enable: true + openapi: + title: 黑马商城商品管理接口文档 + description: "黑马商城商品管理接口文档" + email: zhangsan@itcast.cn + concat: 宇哥 + url: https://www.itcast.cn + version: v1.0.0 + group: + default: + group-name: default + api-rule: package + api-rule-resources: + - com.hmall.item.controller + +# keytool -genkeypair -alias hmall -keyalg RSA -keypass hmall123 -keystore hmall.jks -storepass hmall123 \ No newline at end of file diff --git a/item-service/src/main/resources/mapper/ItemMapper.xml b/item-service/src/main/resources/mapper/ItemMapper.xml new file mode 100644 index 0000000..95597f1 --- /dev/null +++ b/item-service/src/main/resources/mapper/ItemMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/logs/hm-service/spring.log.2024-06-01.0.gz b/logs/hm-service/spring.log.2024-06-01.0.gz new file mode 100644 index 0000000000000000000000000000000000000000..c0148e9634c9609a2096ba0fbfadabb5916aecee GIT binary patch literal 4098 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 A&;S4c literal 0 HcmV?d00001 diff --git a/logs/hm-service/spring.log.2025-05-19.0.gz b/logs/hm-service/spring.log.2025-05-19.0.gz new file mode 100644 index 0000000000000000000000000000000000000000..2bab01b439f1d12ba1ed8dd5bdbb6a35d1f70196 GIT binary patch literal 8775 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 + + 4.0.0 + + com.heima + hmall + pom + 1.0.0 + + hm-common + hm-service + item-service + cart-service + user-service + + + + org.springframework.boot + spring-boot-starter-parent + 2.7.12 + + + + + 11 + 11 + UTF-8 + UTF-8 + 1.18.20 + 2021.0.3 + 2021.0.4.0 + 3.5.2 + 5.8.11 + 8.0.23 + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring-cloud-alibaba.version} + pom + import + + + + mysql + mysql-connector-java + ${mysql.version} + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + cn.hutool + hutool-all + ${hutool.version} + + + + + + + org.projectlombok + lombok + ${org.projectlombok.version} + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + 11 + + + + + + \ No newline at end of file diff --git a/user-service/pom.xml b/user-service/pom.xml new file mode 100644 index 0000000..4629c82 --- /dev/null +++ b/user-service/pom.xml @@ -0,0 +1,19 @@ + + + + hmall + com.heima + 1.0.0 + + 4.0.0 + + user-service + + + 17 + 17 + + + \ No newline at end of file