first commit
This commit is contained in:
commit
a3e7faed94
72
.gitignore
vendored
Normal file
72
.gitignore
vendored
Normal file
@ -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
|
58
cart-service/pom.xml
Normal file
58
cart-service/pom.xml
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>hmall</artifactId>
|
||||
<groupId>com.heima</groupId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>cart-service</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!--common-->
|
||||
<dependency>
|
||||
<groupId>com.heima</groupId>
|
||||
<artifactId>hm-common</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<!--web-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--数据库-->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
<!--mybatis-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.heima</groupId>
|
||||
<artifactId>hm-service</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -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);
|
||||
}
|
||||
}
|
@ -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<CartVO> queryMyCarts(){
|
||||
return cartService.queryMyCarts();
|
||||
}
|
||||
@ApiOperation("批量删除购物车中商品")
|
||||
@ApiImplicitParam(name = "ids", value = "购物车条目id集合")
|
||||
@DeleteMapping
|
||||
public void deleteCartItemByIds(@RequestParam("ids") List<Long> ids){
|
||||
cartService.removeByItemIds(ids);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface CartMapper extends BaseMapper<Cart> {
|
||||
|
||||
@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);
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface ICartService extends IService<Cart> {
|
||||
|
||||
void addItem2Cart(CartFormDTO cartFormDTO);
|
||||
|
||||
List<CartVO> queryMyCarts();
|
||||
|
||||
void removeByItemIds(Collection<Long> itemIds);
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CartServiceImpl extends ServiceImpl<CartMapper, Cart> 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<CartVO> queryMyCarts() {
|
||||
// 1.查询我的购物车列表
|
||||
List<Cart> carts = lambdaQuery().eq(Cart::getUserId,1L /*UserContext.getUser()*/).list();
|
||||
if (CollUtils.isEmpty(carts)) {
|
||||
return CollUtils.emptyList();
|
||||
}
|
||||
|
||||
// 2.转换VO
|
||||
List<CartVO> vos = BeanUtils.copyList(carts, CartVO.class);
|
||||
|
||||
// 3.处理VO中的商品信息
|
||||
handleCartItems(vos);
|
||||
|
||||
// 4.返回
|
||||
return vos;
|
||||
}
|
||||
|
||||
private void handleCartItems(List<CartVO> vos) {
|
||||
// // 1.获取商品id
|
||||
// Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
|
||||
// // 2.查询商品
|
||||
// List<ItemDTO> items = itemService.queryItemByIds(itemIds);
|
||||
// if (CollUtils.isEmpty(items)) {
|
||||
// return;
|
||||
// }
|
||||
// // 3.转为 id 到 item的map
|
||||
// Map<Long, ItemDTO> 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<Long> itemIds) {
|
||||
// 1.构建删除条件,userId和itemId
|
||||
QueryWrapper<Cart> queryWrapper = new QueryWrapper<Cart>();
|
||||
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;
|
||||
}
|
||||
}
|
4
cart-service/src/main/resources/application-dev.yaml
Normal file
4
cart-service/src/main/resources/application-dev.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
hm:
|
||||
db:
|
||||
host: mysql
|
||||
pw: 123
|
4
cart-service/src/main/resources/application-local.yaml
Normal file
4
cart-service/src/main/resources/application-local.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
hm:
|
||||
db:
|
||||
host: localhost # 修改为你自己的虚拟机IP地址
|
||||
pw: 123456 # 修改为docker中的MySQL密码
|
43
cart-service/src/main/resources/application.yaml
Normal file
43
cart-service/src/main/resources/application.yaml
Normal file
@ -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
|
5
cart-service/src/main/resources/mapper/CartMapper.xml
Normal file
5
cart-service/src/main/resources/mapper/CartMapper.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.hmall.mapper.CartMapper">
|
||||
|
||||
</mapper>
|
95
hm-common/pom.xml
Normal file
95
hm-common/pom.xml
Normal file
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>hmall</artifactId>
|
||||
<groupId>com.heima</groupId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>hm-common</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
<!--hutool工具包-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
<!--完成SpringMVC自动装配-->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!--日志-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<version>9.0.73</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-core</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-extension</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
|
||||
<version>4.1.0</version>
|
||||
</dependency>
|
||||
<!--caffeine-->
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
</dependency>
|
||||
<!--AMQP依赖-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.amqp</groupId>
|
||||
<artifactId>spring-amqp</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!--Spring整合Rabbit依赖-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.amqp</groupId>
|
||||
<artifactId>spring-rabbit</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!--json处理-->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -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<R<Void>> processResponse(CommonException e){
|
||||
return ResponseEntity.status(e.getCode()).body(R.error(e));
|
||||
}
|
||||
}
|
@ -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);
|
||||
};
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
61
hm-common/src/main/java/com/hmall/common/domain/PageDTO.java
Normal file
61
hm-common/src/main/java/com/hmall/common/domain/PageDTO.java
Normal file
@ -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<T> {
|
||||
protected Long total;
|
||||
protected Long pages;
|
||||
protected List<T> list;
|
||||
|
||||
public static <T> PageDTO<T> empty(Long total, Long pages) {
|
||||
return new PageDTO<>(total, pages, CollUtils.emptyList());
|
||||
}
|
||||
public static <T> PageDTO<T> empty(Page<?> page) {
|
||||
return new PageDTO<>(page.getTotal(), page.getPages(), CollUtils.emptyList());
|
||||
}
|
||||
|
||||
public static <T> PageDTO<T> of(Page<T> 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 <T,R> PageDTO<T> of(Page<R> page, Function<R, T> 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 <T> PageDTO<T> of(Page<?> page, List<T> list) {
|
||||
return new PageDTO<>(page.getTotal(), page.getPages(), list);
|
||||
}
|
||||
|
||||
public static <T, R> PageDTO<T> of(Page<R> page, Class<T> clazz) {
|
||||
return new PageDTO<>(page.getTotal(), page.getPages(), BeanUtils.copyList(page.getRecords(), clazz));
|
||||
}
|
||||
|
||||
public static <T, R> PageDTO<T> of(Page<R> page, Class<T> clazz, Convert<R, T> convert) {
|
||||
return new PageDTO<>(page.getTotal(), page.getPages(), BeanUtils.copyList(page.getRecords(), clazz, convert));
|
||||
}
|
||||
}
|
@ -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 <T> Page<T> toMpPage(OrderItem... orderItems) {
|
||||
Page<T> 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 <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc) {
|
||||
if (StringUtils.isBlank(sortBy)){
|
||||
sortBy = defaultSortBy;
|
||||
this.isAsc = isAsc;
|
||||
}
|
||||
Page<T> page = new Page<>(pageNo, pageSize);
|
||||
OrderItem orderItem = new OrderItem();
|
||||
orderItem.setAsc(this.isAsc);
|
||||
orderItem.setColumn(sortBy);
|
||||
page.addOrder(orderItem);
|
||||
return page;
|
||||
}
|
||||
public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {
|
||||
return toMpPage("create_time", false);
|
||||
}
|
||||
}
|
45
hm-common/src/main/java/com/hmall/common/domain/R.java
Normal file
45
hm-common/src/main/java/com/hmall/common/domain/R.java
Normal file
@ -0,0 +1,45 @@
|
||||
package com.hmall.common.domain;
|
||||
|
||||
import com.hmall.common.exception.CommonException;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
public class R<T> {
|
||||
private int code;
|
||||
private String msg;
|
||||
private T data;
|
||||
|
||||
public static R<Void> ok() {
|
||||
return ok(null);
|
||||
}
|
||||
|
||||
public static <T> R<T> ok(T data) {
|
||||
return new R<>(200, "OK", data);
|
||||
}
|
||||
|
||||
public static <T> R<T> error(String msg) {
|
||||
return new R<>(500, msg, null);
|
||||
}
|
||||
|
||||
public static <T> R<T> error(int code, String msg) {
|
||||
return new R<>(code, msg, null);
|
||||
}
|
||||
|
||||
public static <T> R<T> 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 <R> 原对象类型
|
||||
* @param <T> 目标对象类型
|
||||
* @return 目标对象
|
||||
*/
|
||||
public static <R, T> T copyBean(R source, Class<T> clazz, Convert<R, T> convert) {
|
||||
T target = copyBean(source, clazz);
|
||||
if (convert != null) {
|
||||
convert.convert(source, target);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
/**
|
||||
* 将原对象转换成目标对象,对于字段不匹配的字段可以使用转换器处理
|
||||
*
|
||||
* @param source 原对象
|
||||
* @param clazz 目标对象的class
|
||||
* @param <R> 原对象类型
|
||||
* @param <T> 目标对象类型
|
||||
* @return 目标对象
|
||||
*/
|
||||
public static <R, T> T copyBean(R source, Class<T> clazz){
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return toBean(source, clazz);
|
||||
}
|
||||
|
||||
public static <R, T> List<T> copyList(List<R> list, Class<T> clazz) {
|
||||
if (list == null || list.size() == 0) {
|
||||
return CollUtils.emptyList();
|
||||
}
|
||||
return copyToList(list, clazz);
|
||||
}
|
||||
|
||||
public static <R, T> List<T> copyList(List<R> list, Class<T> clazz, Convert<R, T> convert) {
|
||||
if (list == null || list.size() == 0) {
|
||||
return CollUtils.emptyList();
|
||||
}
|
||||
return list.stream().map(r -> copyBean(r, clazz, convert)).collect(Collectors.toList());
|
||||
}
|
||||
}
|
@ -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 <T> List<T> emptyList() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public static <T> Set<T> emptySet() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public static <K,V> Map<K, V> emptyMap() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
public static <T> Set<T> singletonSet(T t) {
|
||||
return Collections.singleton(t);
|
||||
}
|
||||
|
||||
public static <T> List<T> singletonList(T t) {
|
||||
return Collections.singletonList(t);
|
||||
}
|
||||
|
||||
public static List<Integer> convertToInteger(List<String> originList){
|
||||
return CollUtils.isNotEmpty(originList) ? originList.stream().map(NumberUtil::parseInt).collect(Collectors.toList()) : null;
|
||||
}
|
||||
|
||||
public static List<Long> convertToLong(List<String> originLIst){
|
||||
return CollUtils.isNotEmpty(originLIst) ? originLIst.stream().map(NumberUtil::parseLong).collect(Collectors.toList()) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 以 conjunction 为分隔符将集合转换为字符串 如果集合元素为数组、Iterable或Iterator,则递归组合其为字符串
|
||||
* @param collection 集合
|
||||
* @param conjunction 分隔符
|
||||
* @param <T> 集合元素类型
|
||||
* @return 连接后的字符串
|
||||
* See Also: IterUtil.join(Iterator, CharSequence)
|
||||
*/
|
||||
public static <T> String join(Collection<T> collection, CharSequence conjunction) {
|
||||
if (null == collection || collection.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return IterUtil.join(collection.iterator(), conjunction);
|
||||
}
|
||||
|
||||
public static <T> String joinIgnoreNull(Collection<T> 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();
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.hmall.common.utils;
|
||||
|
||||
/**
|
||||
* 对原对象进行计算,设置到目标对象中
|
||||
**/
|
||||
public interface Convert<R,T>{
|
||||
void convert(R origin, T target);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.hmall.common.utils;
|
||||
|
||||
public class UserContext {
|
||||
private static final ThreadLocal<Long> 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();
|
||||
}
|
||||
}
|
151
hm-common/src/main/java/com/hmall/common/utils/WebUtils.java
Normal file
151
hm-common/src/main/java/com/hmall/common/utils/WebUtils.java
Normal file
@ -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<String, String[]> 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 <T> String getParameters(final Map<String, T> queries) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
for (Map.Entry<String, T> 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<String>)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());
|
||||
}
|
||||
}
|
@ -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": []
|
||||
}
|
3
hm-common/src/main/resources/META-INF/spring.factories
Normal file
3
hm-common/src/main/resources/META-INF/spring.factories
Normal file
@ -0,0 +1,3 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.hmall.common.config.MyBatisConfig,\
|
||||
com.hmall.common.config.JsonConfig
|
9
hm-service/Dockerfile
Normal file
9
hm-service/Dockerfile
Normal file
@ -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"]
|
71
hm-service/pom.xml
Normal file
71
hm-service/pom.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>hmall</artifactId>
|
||||
<groupId>com.heima</groupId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>hm-service</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!--common-->
|
||||
<dependency>
|
||||
<groupId>com.heima</groupId>
|
||||
<artifactId>hm-common</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<!--web-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!--加密-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-crypto</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-rsa</artifactId>
|
||||
<version>1.0.9.RELEASE</version>
|
||||
</dependency>
|
||||
<!--数据库-->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
<!--mybatis-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!--单元测试-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<!--redis-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
13
hm-service/src/main/java/com/hmall/HMallApplication.java
Normal file
13
hm-service/src/main/java/com/hmall/HMallApplication.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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<String> includePaths;
|
||||
private List<String> excludePaths;
|
||||
}
|
16
hm-service/src/main/java/com/hmall/config/JwtProperties.java
Normal file
16
hm-service/src/main/java/com/hmall/config/JwtProperties.java
Normal file
@ -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);
|
||||
}
|
54
hm-service/src/main/java/com/hmall/config/MvcConfig.java
Normal file
54
hm-service/src/main/java/com/hmall/config/MvcConfig.java
Normal file
@ -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<String> includePaths = authProperties.getIncludePaths();
|
||||
if (CollUtil.isNotEmpty(includePaths)) {
|
||||
registration.addPathPatterns(includePaths);
|
||||
}
|
||||
// 3.配置放行路径
|
||||
List<String> excludePaths = authProperties.getExcludePaths();
|
||||
if (CollUtil.isNotEmpty(excludePaths)) {
|
||||
registration.excludePathPatterns(excludePaths);
|
||||
}
|
||||
registration.excludePathPatterns(
|
||||
"/error",
|
||||
"/favicon.ico",
|
||||
"/v2/**",
|
||||
"/v3/**",
|
||||
"/swagger-resources/**",
|
||||
"/webjars/**",
|
||||
"/doc.html"
|
||||
);
|
||||
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @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<AddressDTO> findMyAddresses() {
|
||||
// 1.查询列表
|
||||
List<Address> 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);
|
||||
}
|
||||
}
|
@ -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<CartVO> queryMyCarts(){
|
||||
return cartService.queryMyCarts();
|
||||
}
|
||||
@ApiOperation("批量删除购物车中商品")
|
||||
@ApiImplicitParam(name = "ids", value = "购物车条目id集合")
|
||||
@DeleteMapping
|
||||
public void deleteCartItemByIds(@RequestParam("ids") List<Long> ids){
|
||||
cartService.removeByItemIds(ids);
|
||||
}
|
||||
}
|
@ -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<String, AtomicInteger> 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("<h5>欢迎访问黑马商城, 这是您第%d次访问<h5>", ai.incrementAndGet());
|
||||
}
|
||||
}
|
@ -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<ItemDTO> queryItemByPage(PageQuery query) {
|
||||
// 1.分页查询
|
||||
Page<Item> result = itemService.page(query.toMpPage("update_time", false));
|
||||
// 2.封装并返回
|
||||
return PageDTO.of(result, ItemDTO.class);
|
||||
}
|
||||
|
||||
@ApiOperation("根据id批量查询商品")
|
||||
@GetMapping
|
||||
public List<ItemDTO> queryItemByIds(@RequestParam("ids") List<Long> 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<OrderDetailDTO> items){
|
||||
itemService.deductStock(items);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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<ItemDTO> search(ItemPageQuery query) {
|
||||
// 分页查询
|
||||
Page<Item> 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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
34
hm-service/src/main/java/com/hmall/domain/dto/ItemDTO.java
Normal file
34
hm-service/src/main/java/com/hmall/domain/dto/ItemDTO.java
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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<OrderDetailDTO> details;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
77
hm-service/src/main/java/com/hmall/domain/po/Address.java
Normal file
77
hm-service/src/main/java/com/hmall/domain/po/Address.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
|
||||
}
|
80
hm-service/src/main/java/com/hmall/domain/po/Cart.java
Normal file
80
hm-service/src/main/java/com/hmall/domain/po/Cart.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
|
||||
}
|
113
hm-service/src/main/java/com/hmall/domain/po/Item.java
Normal file
113
hm-service/src/main/java/com/hmall/domain/po/Item.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 商品表
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
|
||||
}
|
91
hm-service/src/main/java/com/hmall/domain/po/Order.java
Normal file
91
hm-service/src/main/java/com/hmall/domain/po/Order.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
|
||||
}
|
123
hm-service/src/main/java/com/hmall/domain/po/PayOrder.java
Normal file
123
hm-service/src/main/java/com/hmall/domain/po/PayOrder.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付订单
|
||||
* </p>
|
||||
*/
|
||||
@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;
|
||||
|
||||
|
||||
}
|
66
hm-service/src/main/java/com/hmall/domain/po/User.java
Normal file
66
hm-service/src/main/java/com/hmall/domain/po/User.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户表
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
43
hm-service/src/main/java/com/hmall/domain/vo/CartVO.java
Normal file
43
hm-service/src/main/java/com/hmall/domain/vo/CartVO.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
}
|
34
hm-service/src/main/java/com/hmall/domain/vo/OrderVO.java
Normal file
34
hm-service/src/main/java/com/hmall/domain/vo/OrderVO.java
Normal file
@ -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;
|
||||
}
|
49
hm-service/src/main/java/com/hmall/domain/vo/PayOrderVO.java
Normal file
49
hm-service/src/main/java/com/hmall/domain/vo/PayOrderVO.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付订单
|
||||
* </p>
|
||||
*/
|
||||
@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;
|
||||
}
|
@ -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;
|
||||
}
|
25
hm-service/src/main/java/com/hmall/enums/PayChannel.java
Normal file
25
hm-service/src/main/java/com/hmall/enums/PayChannel.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
27
hm-service/src/main/java/com/hmall/enums/PayStatus.java
Normal file
27
hm-service/src/main/java/com/hmall/enums/PayStatus.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
27
hm-service/src/main/java/com/hmall/enums/PayType.java
Normal file
27
hm-service/src/main/java/com/hmall/enums/PayType.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
30
hm-service/src/main/java/com/hmall/enums/UserStatus.java
Normal file
30
hm-service/src/main/java/com/hmall/enums/UserStatus.java
Normal file
@ -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("账户状态错误");
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
16
hm-service/src/main/java/com/hmall/mapper/AddressMapper.java
Normal file
16
hm-service/src/main/java/com/hmall/mapper/AddressMapper.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.hmall.mapper;
|
||||
|
||||
import com.hmall.domain.po.Address;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface AddressMapper extends BaseMapper<Address> {
|
||||
|
||||
}
|
20
hm-service/src/main/java/com/hmall/mapper/CartMapper.java
Normal file
20
hm-service/src/main/java/com/hmall/mapper/CartMapper.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface CartMapper extends BaseMapper<Cart> {
|
||||
|
||||
@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);
|
||||
}
|
21
hm-service/src/main/java/com/hmall/mapper/ItemMapper.java
Normal file
21
hm-service/src/main/java/com/hmall/mapper/ItemMapper.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 商品表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface ItemMapper extends BaseMapper<Item> {
|
||||
|
||||
@Update("UPDATE item SET stock = stock - #{num} WHERE id = #{itemId}")
|
||||
void updateStock(OrderDetailDTO orderDetail);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.hmall.mapper;
|
||||
|
||||
import com.hmall.domain.po.OrderDetail;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface OrderDetailMapper extends BaseMapper<OrderDetail> {
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.hmall.mapper;
|
||||
|
||||
import com.hmall.domain.po.OrderLogistics;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface OrderLogisticsMapper extends BaseMapper<OrderLogistics> {
|
||||
|
||||
}
|
16
hm-service/src/main/java/com/hmall/mapper/OrderMapper.java
Normal file
16
hm-service/src/main/java/com/hmall/mapper/OrderMapper.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.hmall.mapper;
|
||||
|
||||
import com.hmall.domain.po.Order;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface OrderMapper extends BaseMapper<Order> {
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.hmall.mapper;
|
||||
|
||||
import com.hmall.domain.po.PayOrder;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付订单 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-16
|
||||
*/
|
||||
public interface PayOrderMapper extends BaseMapper<PayOrder> {
|
||||
|
||||
}
|
19
hm-service/src/main/java/com/hmall/mapper/UserMapper.java
Normal file
19
hm-service/src/main/java/com/hmall/mapper/UserMapper.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface UserMapper extends BaseMapper<User> {
|
||||
@Update("update user set balance = balance - ${totalFee} where id = #{userId}")
|
||||
void updateMoney(@Param("userId") Long userId, @Param("totalFee") Integer totalFee);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.hmall.service;
|
||||
|
||||
import com.hmall.domain.po.Address;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface IAddressService extends IService<Address> {
|
||||
|
||||
}
|
26
hm-service/src/main/java/com/hmall/service/ICartService.java
Normal file
26
hm-service/src/main/java/com/hmall/service/ICartService.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface ICartService extends IService<Cart> {
|
||||
|
||||
void addItem2Cart(CartFormDTO cartFormDTO);
|
||||
|
||||
List<CartVO> queryMyCarts();
|
||||
|
||||
void removeByItemIds(Collection<Long> itemIds);
|
||||
}
|
24
hm-service/src/main/java/com/hmall/service/IItemService.java
Normal file
24
hm-service/src/main/java/com/hmall/service/IItemService.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 商品表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface IItemService extends IService<Item> {
|
||||
|
||||
void deductStock(List<OrderDetailDTO> items);
|
||||
|
||||
List<ItemDTO> queryItemByIds(Collection<Long> ids);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.hmall.service;
|
||||
|
||||
import com.hmall.domain.po.OrderDetail;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface IOrderDetailService extends IService<OrderDetail> {
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.hmall.service;
|
||||
|
||||
import com.hmall.domain.po.OrderLogistics;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface IOrderLogisticsService extends IService<OrderLogistics> {
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface IOrderService extends IService<Order> {
|
||||
|
||||
Long createOrder(OrderFormDTO orderFormDTO);
|
||||
|
||||
void markOrderPaySuccess(Long orderId);
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付订单 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-16
|
||||
*/
|
||||
public interface IPayOrderService extends IService<PayOrder> {
|
||||
|
||||
String applyPayOrder(PayApplyDTO applyDTO);
|
||||
|
||||
void tryPayOrderByBalance(PayOrderFormDTO payOrderFormDTO);
|
||||
}
|
21
hm-service/src/main/java/com/hmall/service/IUserService.java
Normal file
21
hm-service/src/main/java/com/hmall/service/IUserService.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
public interface IUserService extends IService<User> {
|
||||
|
||||
UserLoginVO login(LoginFormDTO loginFormDTO);
|
||||
|
||||
void deductMoney(String pw, Integer totalFee);
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
@Service
|
||||
public class AddressServiceImpl extends ServiceImpl<AddressMapper, Address> implements IAddressService {
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CartServiceImpl extends ServiceImpl<CartMapper, Cart> 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<CartVO> queryMyCarts() {
|
||||
// 1.查询我的购物车列表
|
||||
List<Cart> carts = lambdaQuery().eq(Cart::getUserId, UserContext.getUser()).list();
|
||||
if (CollUtils.isEmpty(carts)) {
|
||||
return CollUtils.emptyList();
|
||||
}
|
||||
|
||||
// 2.转换VO
|
||||
List<CartVO> vos = BeanUtils.copyList(carts, CartVO.class);
|
||||
|
||||
// 3.处理VO中的商品信息
|
||||
handleCartItems(vos);
|
||||
|
||||
// 4.返回
|
||||
return vos;
|
||||
}
|
||||
|
||||
private void handleCartItems(List<CartVO> vos) {
|
||||
// 1.获取商品id
|
||||
Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
|
||||
// 2.查询商品
|
||||
List<ItemDTO> items = itemService.queryItemByIds(itemIds);
|
||||
if (CollUtils.isEmpty(items)) {
|
||||
return;
|
||||
}
|
||||
// 3.转为 id 到 item的map
|
||||
Map<Long, ItemDTO> 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<Long> itemIds) {
|
||||
// 1.构建删除条件,userId和itemId
|
||||
QueryWrapper<Cart> queryWrapper = new QueryWrapper<Cart>();
|
||||
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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 商品表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
*/
|
||||
@Service
|
||||
public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements IItemService {
|
||||
|
||||
@Override
|
||||
public void deductStock(List<OrderDetailDTO> 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<ItemDTO> queryItemByIds(Collection<Long> ids) {
|
||||
return BeanUtils.copyList(listByIds(ids), ItemDTO.class);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单详情表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
@Service
|
||||
public class OrderDetailServiceImpl extends ServiceImpl<OrderDetailMapper, OrderDetail> implements IOrderDetailService {
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
@Service
|
||||
public class OrderLogisticsServiceImpl extends ServiceImpl<OrderLogisticsMapper, OrderLogistics> implements IOrderLogisticsService {
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-05
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> 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<OrderDetailDTO> detailDTOS = orderFormDTO.getDetails();
|
||||
// 1.2.获取商品id和数量的Map
|
||||
Map<Long, Integer> itemNumMap = detailDTOS.stream()
|
||||
.collect(Collectors.toMap(OrderDetailDTO::getItemId, OrderDetailDTO::getNum));
|
||||
Set<Long> itemIds = itemNumMap.keySet();
|
||||
// 1.3.查询商品
|
||||
List<ItemDTO> 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<OrderDetail> 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<OrderDetail> buildDetails(Long orderId, List<ItemDTO> items, Map<Long, Integer> numMap) {
|
||||
List<OrderDetail> 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 支付订单 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
* @since 2023-05-16
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PayOrderServiceImpl extends ServiceImpl<PayOrderMapper, PayOrder> 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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author 虎哥
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User> 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("扣款成功");
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user