273 Commits
v4.1 ... v4.2.0

Author SHA1 Message Date
OceansDeep
e38f9aa2ff !13 fix https://gitee.com/beijing_hongye_huicheng/lilishop/issues/I3YFU4
Merge pull request !13 from OceansDeep/feature/pg
2021-07-01 02:16:42 +00:00
paulGao
696e075fcd Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop into feature/pg 2021-07-01 10:12:40 +08:00
paulGao
d25ba76094 fix https://gitee.com/beijing_hongye_huicheng/lilishop/issues/I3YFU4 2021-07-01 10:12:33 +08:00
Chopper
7e3a9eb904 Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-30 19:59:42 +08:00
Chopper
079437100d 版本好升级 2021-06-30 19:59:36 +08:00
lifenlong
d7ce709ce6 使用hutool进行格式转换 2021-06-30 16:29:19 +08:00
lifenlong
cff2b95c48 同步 2021-06-30 15:47:33 +08:00
lifenlong
1a77b3cec7 商品数据转换问题 2021-06-30 15:46:52 +08:00
Chopper
23388eff6b 升级项目版本号 2021-06-30 14:53:26 +08:00
lifenlong
46f216c191 1.店铺关闭,批量下架店铺商品问题。
2.解决实物/虚拟订单发货逻辑判断问题
2021-06-30 10:26:32 +08:00
lifenlong
a60a535708 修改分销可提现金额 2021-06-30 08:41:04 +08:00
lifenlong
888b5e2558 解决直播间时间不正确问题 2021-06-29 17:01:55 +08:00
lifenlong
1431d990f9 解决直播间时间不正确问题 2021-06-29 16:58:54 +08:00
Chopper
f509b8745d token生成时权限过滤问题处理 2021-06-29 16:43:38 +08:00
Chopper
c1b9f287c7 新增管理员即赋予权限无法生效问题处理。直播间未登录用户报错问题处理 2021-06-29 16:26:52 +08:00
Chopper
3ee3e49d0b 用户在请求直播时没有登录抛出异常问题处理。 2021-06-29 15:40:37 +08:00
Chopper
05904b25c4 Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-29 11:56:45 +08:00
Chopper
5e54b2f179 规格值字段新增 2021-06-29 11:56:40 +08:00
lifenlong
e6d045c663 同步 2021-06-29 11:29:05 +08:00
lifenlong
50f96727b3 分销商品VO返回GoodsId 2021-06-29 11:24:53 +08:00
Chopper
39e851ee78 aop积分日志记录兼容问题处理 2021-06-29 11:15:27 +08:00
Chopper
5a415ffc77 条件判定语句顺序调整 2021-06-29 10:25:45 +08:00
Chopper
6a9ba13fc0 Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-29 10:13:24 +08:00
Chopper
d96d5edcd5 会员提现api注解问题处理 2021-06-29 10:13:18 +08:00
lifenlong
d35eb293dd Merge branch 'master' of https://gitee.com/beijing_hongye_huicheng/lilishop 2021-06-29 09:23:37 +08:00
lifenlong
fcfa140a0a 添加注释 2021-06-29 09:23:22 +08:00
chopper711
707c4dbec2 !12 会员消息问题整改
Merge pull request !12 from chopper711/qiuqiu
2021-06-29 01:05:15 +00:00
pikachu
13b1c353b9 Merge branch 'master' into qiuqiu 2021-06-29 08:26:22 +08:00
pikachu
8ed54e061f 会员消息修改 2021-06-29 08:25:54 +08:00
lifenlong
d5fab95707 1.优惠券活动由定时器修改为延时任务执行。
2.修改shopEditDTO,不继承ShopDetail
2021-06-28 18:18:23 +08:00
lifenlong
bbf18b7b0a Merge branch 'master' of https://gitee.com/beijing_hongye_huicheng/lilishop 2021-06-28 16:09:13 +08:00
lifenlong
fe06555a0b 初始化30天的秒杀活动 2021-06-28 16:09:03 +08:00
Chopper
cf9e6a659a qq联合登录openid问题处理 2021-06-28 15:16:32 +08:00
Chopper
c628c0ebb2 店铺入驻字段缺失问题处理 2021-06-28 14:56:34 +08:00
lifenlong
31479bab19 同步 2021-06-28 11:31:42 +08:00
lifenlong
63802a596b 添加秒杀设置 2021-06-28 11:30:37 +08:00
Chopper
84f6f0e7ee 评价判定问题处理 2021-06-28 11:28:09 +08:00
chopper711
98a2da489d !11 商品参数校验,在线充值回调
Merge pull request !11 from chopper711/qiuqiu
2021-06-28 01:03:41 +00:00
pikachu
5786cb9e55 修改商品参数校验以及充值回调接口 2021-06-26 16:48:06 +08:00
lifenlong
1cbab4a219 店铺评价列表,展示当前店铺数据 2021-06-26 15:24:59 +08:00
lifenlong
873a960d3a 店铺直播列表,展示当前店铺数据 2021-06-26 15:23:00 +08:00
lifenlong
80007a6b86 设定默认商家结算日 2021-06-26 14:44:55 +08:00
lifenlong
467e9887d0 本地校验直播间开始、结束时间 2021-06-26 14:38:27 +08:00
lifenlong
2d5c0d6a1f 删除优惠券,删除优惠券活动关联 2021-06-26 14:07:21 +08:00
lifenlong
d047546374 直播间去重复商品 2021-06-26 11:18:14 +08:00
lifenlong
788e9ca239 添加电话校验 2021-06-26 11:04:20 +08:00
lifenlong
4939e31e71 添加电话校验 2021-06-26 11:02:42 +08:00
pikachu
701ea240ab Merge branch 'master' into qiuqiu 2021-06-26 10:58:57 +08:00
Chopper
b5088415ce Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-25 18:30:03 +08:00
Chopper
df44a7ae30 不能使用余额支付进行充值 2021-06-25 18:29:58 +08:00
lifenlong
4b3c2cbea5 微信小程序接口,调用成功统一处理返回 2021-06-25 17:34:00 +08:00
lifenlong
7dfbb164ae Merge branch 'master' of https://gitee.com/beijing_hongye_huicheng/lilishop 2021-06-25 16:03:18 +08:00
lifenlong
3c2cf69cbe 微信媒体返回 2021-06-25 16:03:14 +08:00
Chopper
0d6d92139b 余额支付错误的判定问题处理 2021-06-25 16:00:23 +08:00
Chopper
f725b64345 微信退款状态无法变更问题处理 2021-06-25 14:56:16 +08:00
Chopper
efb226b37b 投诉展示相关问题完善 2021-06-25 14:32:39 +08:00
Chopper
14ff0a3501 交易支付后不会自动跳转问题处理 2021-06-25 11:43:56 +08:00
Chopper
39d6032152 订单取消异常 2021-06-25 11:40:05 +08:00
Chopper
b6062f4fb9 订单统计时,店铺参数传递后台,统计结果不变问题处理 2021-06-25 11:35:02 +08:00
Chopper
47c42db720 创建订单,校验参数相关流程调整 2021-06-25 10:48:21 +08:00
Chopper
ac68acda50 兼容性问题处理 2021-06-25 10:37:31 +08:00
Chopper
d99a4d2d50 商品参数编辑问题处理 2021-06-25 10:35:22 +08:00
Chopper
1b5add1d13 购物车获取数量问题 2021-06-25 10:31:10 +08:00
Chopper
54320499e5 错误消息完善 2021-06-25 10:17:58 +08:00
Chopper
e4dd156ae7 Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-25 09:47:12 +08:00
Chopper
02d23dc217 1、主要解决商品参数后端存储格式问题,结构问题等
2、配送商品超出配送区域提出警告,但是依然可以下单问题处理
2021-06-25 09:46:38 +08:00
lifenlong
4fd8e4ecef 修改虚拟订单售后类型只支持退款 2021-06-24 18:17:16 +08:00
lifenlong
83367ca96d 解决微信媒体返回错误问题。 2021-06-24 17:30:03 +08:00
lifenlong
30846819d8 解决线上、本地开发重复调用微信token的问题 2021-06-24 17:19:17 +08:00
lifenlong
9c574ad9b7 微信上传媒体提示 2021-06-24 16:03:49 +08:00
lifenlong
e6ad65d8c0 如果发行数量是0,则不限制数量 2021-06-24 15:51:14 +08:00
lifenlong
02becd70b2 Merge branch 'master' of https://gitee.com/beijing_hongye_huicheng/lilishop 2021-06-24 15:29:29 +08:00
lifenlong
bd82387a76 虚拟订单不能修改收件人信息 2021-06-24 15:29:23 +08:00
Chopper
158234412c uv统计 2021-06-24 11:18:13 +08:00
Chopper
d185de27dd Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-24 10:57:40 +08:00
Chopper
c9b7ee2c81 商品发布模块更新 2021-06-24 10:57:27 +08:00
OceansDeep
cf1c138fe8 !10 修复分类参数修改索引属性后没有同步到商品参数问题
Merge pull request !10 from OceansDeep/feature/pg
2021-06-24 01:21:39 +00:00
paulGao
0121c546f4 修复分类参数修改索引属性后没有同步到商品参数问题 2021-06-24 09:20:13 +08:00
lifenlong
155c648186 整理之后新版本功能 2021-06-23 18:58:20 +08:00
lifenlong
943d31de9d 显示小程序的客服配置 2021-06-23 18:06:38 +08:00
lifenlong
8a10382787 Merge branch 'master' of https://gitee.com/beijing_hongye_huicheng/lilishop 2021-06-23 17:44:31 +08:00
lifenlong
3aacd1efbd 修改商品模板的详情字段类型 2021-06-23 17:44:24 +08:00
Chopper
f667822daf Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-23 16:47:45 +08:00
Chopper
8d5d902550 管理端验证码登录校验 2021-06-23 16:47:16 +08:00
Chopper
8cecb69c01 异常模块进一步完善 2021-06-23 16:47:05 +08:00
Chopper
7851e8af39 规格代码相关改版 2021-06-23 16:46:52 +08:00
lifenlong
34ed19373b 修改update.sql,添加新增的表结构 2021-06-23 16:06:50 +08:00
lifenlong
abaf32f3dc Merge branch 'master' into Bulbasaur 2021-06-23 15:38:43 +08:00
lifenlong
ae4253d146 Merge branch 'Bulbasaur' of https://gitee.com/beijing_hongye_huicheng/lilishop into Bulbasaur 2021-06-23 15:38:03 +08:00
lifenlong
c1bce3fc3b 直播间删除商品,返回错误 2021-06-23 15:37:49 +08:00
Chopper
a5fa7cadcd 规格搜索以规格id为准 2021-06-23 09:44:53 +08:00
OceansDeep
6419d5b7e8 !9 修复更新商品状态不会更新缓存商品数据问题
Merge pull request !9 from OceansDeep/feature/pg
2021-06-22 14:43:53 +00:00
paulGao
117fe762a8 修复更新商品状态不会 2021-06-22 22:36:28 +08:00
paulGao
bf67a45d53 Merge branch 'feature/pg' of gitee.com:beijing_hongye_huicheng/lilishop into feature/pg 2021-06-22 22:34:02 +08:00
paulGao
12238d3989 修复更新商品状态不会更新缓存商品数据问题 2021-06-22 22:33:10 +08:00
Chopper
911df97422 商品规格相关问题处理 2021-06-22 18:58:55 +08:00
Chopper
a3085405fe 消费者配置文件还原 2021-06-22 15:47:44 +08:00
Chopper
d40869fe2a consumer 数据库还原 2021-06-22 15:40:08 +08:00
Chopper
3e237a8488 商品创建订单,提示语问题处理 2021-06-22 15:21:02 +08:00
Chopper
19154aa2b8 虚拟商品重量字段兼容问题处理 2021-06-22 15:08:06 +08:00
Chopper
8f93ac4d49 修改默认错误提示语 2021-06-22 11:50:08 +08:00
Chopper
cfd8bceb10 索引字段问题处理 2021-06-22 09:23:50 +08:00
OceansDeep
5fc1e7b30f !8 修复商品索引参数问题
Merge pull request !8 from OceansDeep/feature/pg
2021-06-21 16:10:17 +00:00
OceansDeep
54408db0f0 Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop into feature/pg 2021-06-21 16:10:06 +00:00
paulGao
41a86ff7dc 修复商品索引参数问题 2021-06-22 00:07:33 +08:00
Chopper
65d106e515 商品信息编辑时,参数校验问题处理 2021-06-21 17:30:28 +08:00
Chopper
74ae262e79 商品保存时,部分参数逻辑校验 2021-06-21 17:12:55 +08:00
Chopper
cdbaed22d9 验证码模块提交 2021-06-21 16:38:29 +08:00
Chopper
2db8eb7324 订单查询失败问题处理 2021-06-21 15:37:08 +08:00
Chopper
b8a2e90592 规范sql升级 2021-06-21 14:57:20 +08:00
chopper711
eb1b6fac5c !7 会员站内信功能相关合并
Merge pull request !7 from chopper711/qiuqiu
2021-06-21 14:16:44 +08:00
chopper711
4bd4ba7e08 !6 4.1.0功能合并
Merge pull request !6 from chopper711/Bulbasaur
2021-06-21 14:15:41 +08:00
Chopper
c7e4af6175 注释规范 2021-06-21 14:14:07 +08:00
OceansDeep
8403db9e75 !5 修复拼团商品限购数量问题,添加创建订单流程过后清除缓存key
Merge pull request !5 from OceansDeep/feature/pg
2021-06-21 14:03:22 +08:00
paulGao
337775013e 修复拼团商品限购数量问题,添加创建订单流程过后清除缓存key 2021-06-21 14:02:31 +08:00
paulGao
7564a4627a Merge branch 'Bulbasaur' of gitee.com:beijing_hongye_huicheng/lilishop into feature/pg 2021-06-21 11:56:25 +08:00
Chopper
1943f0ddea Merge branch 'Bulbasaur' of gitee.com:beijing_hongye_huicheng/lilishop into Bulbasaur 2021-06-21 11:55:41 +08:00
Chopper
50911137cb 购物车逻辑相关处理 2021-06-21 11:55:08 +08:00
lifenlong
b574dfb04f 解决优惠券活动发送多个优惠券问题。 2021-06-21 11:36:14 +08:00
Chopper
9546807031 流量限制设定更合理 2021-06-21 10:53:04 +08:00
pikachu
aaf53440ac 完善消息注视 2021-06-20 11:05:14 +08:00
lifenlong
d7b0ff4cd1 优惠券动态时间判定。 2021-06-19 17:43:04 +08:00
lifenlong
4e87ad22c1 虚拟订单,订单核验码修改为8位 2021-06-19 14:31:56 +08:00
lifenlong
859689eec2 1.直播商品名称不能超过14位。
2.添加虚拟订单类型
2021-06-19 14:11:57 +08:00
Chopper
738a95edb6 分类信息保存增加校验 2021-06-18 17:33:45 +08:00
Chopper
e5b9280b7e 关闭券活动 2021-06-18 16:36:53 +08:00
lifenlong
c20f3ff04d 查询分类下是否存在商品,去除掉已删除商品 2021-06-18 16:22:49 +08:00
Chopper
c787b4762b 优惠券问题粗粝 2021-06-18 16:20:00 +08:00
Chopper
30d34d69f1 Merge branch 'Bulbasaur' of gitee.com:beijing_hongye_huicheng/lilishop into Bulbasaur 2021-06-18 14:23:54 +08:00
Chopper
7113914ccd 交互对象调整 2021-06-18 14:23:51 +08:00
lifenlong
78b5b5a324 冲突 2021-06-18 11:29:46 +08:00
lifenlong
b361fe7d95 展示优惠券活动下的优惠券列表详情 2021-06-18 11:27:38 +08:00
Chopper
daa6236b37 自定义分类无法保存问题处理 2021-06-18 10:27:33 +08:00
lifenlong
24be8f342d 解决冲突 2021-06-18 10:12:15 +08:00
lifenlong
bfc76f7ceb 同步master 2021-06-18 10:03:34 +08:00
pikachu
0cfb196918 Merge branch 'master' into qiuqiu 2021-06-18 07:55:53 +08:00
pikachu
975550374a 新增会员站内信消息 2021-06-18 07:55:25 +08:00
Chopper
cbcadc21a2 xss还原 2021-06-17 16:43:37 +08:00
Chopper
e01c279cfe 支付宝支付h5 无法支付成功,检查时回调参数格式问题,现重新整理上线 2021-06-17 16:31:40 +08:00
Chopper
897600335e 支付title 字符串过滤 2021-06-17 15:06:24 +08:00
Chopper
383dbb2d4e 测试环境短信问题处理 ,默认6个1发送 2021-06-17 15:05:50 +08:00
Chopper
4bc5cb0f1b wap支付失败,看起来是因为超时原因,调试一下 2021-06-17 12:21:41 +08:00
Chopper
4a9d54cbf4 增加日志答应,wap支付3m超时问题尝试解决 2021-06-17 12:12:45 +08:00
lifenlong
67e31bff07 同步master 2021-06-17 11:15:56 +08:00
Chopper
bf023ccad5 去除无效的代码 2021-06-17 10:41:53 +08:00
Chopper
0995a3b75f Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-17 10:38:07 +08:00
Chopper
e4b968e0af 库存扣减,库存回滚问题处理。
之前存在商品取消后,自动回滚库存,可是忽略了商品取消可能是因为库存不足导致的问题。
2021-06-17 10:37:45 +08:00
Chopper
7ce5b517fc 商品评价场景,查询业务重构,代码复用增强,前端可以查看到后端设置隐藏的评价内容问题解决 2021-06-17 10:37:11 +08:00
OceansDeep
9c5cc0bf36 !4 修复拼团商品下单问题和添加商品是否需要索引
Merge pull request !4 from OceansDeep/feature/pg
2021-06-17 09:31:47 +08:00
paulGao
c69cd0c22d 修复拼团商品下单问题和添加商品是否需要索引 2021-06-17 09:11:16 +08:00
lifenlong
fbcd5b7470 app版本修改,过滤当前版本 2021-06-17 00:28:36 +08:00
Chopper
6205693df6 增加下单部分注视,支付宝h5支付日志记录内容 2021-06-16 15:54:54 +08:00
Chopper
00182f5cfb 限制官网地区同步功能 2021-06-16 10:49:17 +08:00
Chopper
841903d2a6 优惠券活动问题处理 2021-06-15 18:10:25 +08:00
Chopper
5f403ec675 合并master业务代码 2021-06-15 16:21:03 +08:00
Chopper
a97b698d8e Merge branch 'master' into Bulbasaur
# Conflicts:
#	consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/PromotionEverydayExecute.java
#	consumer/src/main/java/cn/lili/trigger/executor/PromotionTimeTriggerExecutor.java
#	framework/src/main/java/cn/lili/common/trigger/delay/AbstractDelayQueueMachineFactory.java
#	framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java
#	framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponServiceImpl.java
2021-06-15 15:50:54 +08:00
Chopper
24bb6a4169 代码同步 2021-06-15 15:28:33 +08:00
lifenlong
44d6edd53b 演示站点,支持商品分类添加 2021-06-15 09:59:32 +08:00
lifenlong
10dbed04b6 初始化秒杀活动 2021-06-13 16:27:40 +08:00
lifenlong
a159c0d0db 下载批量发货订单列表 2021-06-13 15:53:19 +08:00
lifenlong
3814b4a9a5 暂提 2021-06-13 14:51:39 +08:00
Chopper
2472cfd93b 批量关闭活动问题处理 2021-06-13 14:48:45 +08:00
lifenlong
5a4f8e2a72 同步 2021-06-13 09:03:16 +08:00
lifenlong
6ef71d9dfe 解决PC页面不传递开启关闭 2021-06-12 15:16:22 +08:00
Chopper
ee01a65d92 买家端登录跳转问题处理 2021-06-11 15:39:55 +08:00
Chopper
8913f37f33 qq联合登录问题处理 2021-06-11 14:48:20 +08:00
Chopper
fcca848e40 去除引用 2021-06-11 12:00:01 +08:00
Chopper
ebebbcac69 延时任务规范,任务调度机制,修改为consumer执行,不再被每个进程监控。 2021-06-11 11:59:21 +08:00
lifenlong
332e287675 修改虚拟订单类型 2021-06-10 20:13:21 +08:00
Chopper
9195292aa9 演示站点部分权限控制 2021-06-10 17:40:53 +08:00
lifenlong
34e5488b9d 创建虚拟订单
由前台处理待发货订单导出
2021-06-10 16:25:40 +08:00
Chopper
89f4b71301 Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-10 09:16:36 +08:00
Chopper
fc66db2d13 修改注释 2021-06-10 09:15:31 +08:00
lifenlong
7c8c692e87 去除xss空格过滤 2021-06-09 18:21:11 +08:00
lifenlong
19ae44f851 商品规格添加商品类型 2021-06-09 17:39:57 +08:00
Chopper
590a039f10 商品索引需要手动删除的问题处理 2021-06-09 17:11:21 +08:00
Chopper
f7201342d9 代码规范度问题处理,注释补充。 2021-06-09 16:29:49 +08:00
lifenlong
cf4f9dd6bc 商品模板支持虚拟商品 2021-06-09 16:29:25 +08:00
Chopper
b30a55eafa 收银台参数问题优化,如果不匹配直接跳过。 2021-06-09 09:24:35 +08:00
Chopper
da1863850a 主要完善延时任务相关,缺失的注释信息,log记录的信息完善。目录结构优化。
sql数据过大,展示sql默认为false,需要打开手动打开就好。
2021-06-08 18:40:32 +08:00
Chopper
91baf22841 无效类去除 2021-06-08 09:36:35 +08:00
Chopper
c2367f763f 订单支付金额为0时问题解决。 2021-06-07 17:36:48 +08:00
lifenlong
a51e86fd98 去除e.printStackTrace();使用slf4j实现 2021-06-07 16:49:59 +08:00
Chopper
203abe1087 Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-07 16:13:50 +08:00
Chopper
6d7e9e7fdd 阿里sms默认短信验证码配置问题处理 2021-06-07 16:12:07 +08:00
lifenlong
762a7335fe Merge branch 'master' of https://gitee.com/beijing_hongye_huicheng/lilishop 2021-06-07 15:50:45 +08:00
lifenlong
0bca2d9026 店铺结算设置开始、结束时间 2021-06-07 15:50:36 +08:00
Chopper
0fc179cff2 地区相关问题处理 2021-06-07 15:28:36 +08:00
Chopper
f949896685 地区数据初始化之后,数据无法访问,因为缓存没有更新。现在更新为初始化完成,即清空与地区相关的缓存 2021-06-07 15:27:48 +08:00
lifenlong
86360cf5f8 Merge branch 'master' into Bulbasaur 2021-06-07 15:08:36 +08:00
lifenlong
e176d920cc 店铺结算设置开始、结束时间 2021-06-07 15:08:12 +08:00
Chopper
f9f8cce13e xss防御相关更改策略,调整代码 2021-06-07 15:00:36 +08:00
Chopper
4b8fff1e56 地区初始化数据结构错误问题,提前设置id,构造出父类id 2021-06-07 10:16:16 +08:00
Chopper
03f54f470a Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-06-07 10:13:19 +08:00
Chopper
886ea29c6d 对数据保存做一个判定,如果模型设置id,则不复盖模型原有的id 2021-06-07 10:12:42 +08:00
lifenlong
4849e7d57e 同步 master 2021-06-07 10:02:23 +08:00
lifenlong
7e8ba50970 添加页面,判断是否发布页面 2021-06-07 10:00:07 +08:00
lifenlong
431f7c014f 添加页面,判断是否发布页面
添加update.sql
2021-06-07 09:59:09 +08:00
lifenlong
bbe01e9e67 用户经验值设置 2021-06-05 17:13:04 +08:00
lifenlong
e379a2eb34 导出售后单 2021-06-05 14:48:16 +08:00
lifenlong
b7e439e177 店铺导出订单列表 2021-06-05 14:04:56 +08:00
lifenlong
73002148d4 1.展示店铺的商品数量、收藏数量
2.动态时间优惠券进行状态判断。
3.导出订单API
2021-06-04 15:42:35 +08:00
Chopper
9fedc25f3f 安全问题 2021-06-04 10:55:35 +08:00
Chopper
f11c3205ee 攻击sql阻断解析器 2021-06-04 10:21:54 +08:00
Chopper
94bb98bf1f 去除Mapper 采用注解来实现相关查询 2021-06-03 15:35:20 +08:00
lifenlong
9db40c197d 延时任务修改直播间状态 2021-06-03 10:54:48 +08:00
lifenlong
b842daa609 Merge branch 'master' of https://gitee.com/beijing_hongye_huicheng/lilishop 2021-06-02 17:57:07 +08:00
lifenlong
ce70a93ff5 买家过滤拼团内容 2021-06-02 17:56:59 +08:00
lifenlong
f3faec3f72 买家过滤拼团内容 2021-06-02 17:54:40 +08:00
lifenlong
07b9e413d6 添加秒杀活动设置 2021-06-02 17:30:32 +08:00
Chopper
80ca2b6388 在线人数展示时间字段完整展示 2021-06-02 17:28:43 +08:00
Chopper
571bc0ed93 首页统计排序优化 2021-06-02 16:05:55 +08:00
Chopper
83c86ab1da 优化管理端首页数据统计 2021-06-02 15:42:54 +08:00
Chopper
393c246018 再次缩短在线人数vo的返回日期长度 2021-06-02 14:49:48 +08:00
Chopper
46d937270d 调整返回日期的格式 2021-06-02 14:48:40 +08:00
Chopper
7a4ca67784 会员统计当日数据问题处理 2021-06-02 10:37:01 +08:00
lifenlong
b2d149c714 支持使用促销类型进行筛选订单:拼团、积分、赠品 2021-06-01 22:10:28 +08:00
lifenlong
f802810330 添加直播间状态变化延时任务 2021-06-01 17:23:32 +08:00
lifenlong
6fb7322e3e Merge branch 'master' into Bulbasaur 2021-06-01 15:51:50 +08:00
lifenlong
b70da68761 Merge branch 'Bulbasaur' of https://gitee.com/beijing_hongye_huicheng/lilishop into Bulbasaur 2021-06-01 15:51:30 +08:00
lifenlong
0324951d9a 微信小程序优化 2021-06-01 15:51:19 +08:00
Chopper
d01bd1581e 店铺流水交易趋势问题 2021-06-01 09:43:02 +08:00
Chopper
56c532349b 店铺uv条件判定问题处理 2021-06-01 09:29:03 +08:00
Chopper
79461c3768 uv统计异常问题处理 2021-06-01 09:16:15 +08:00
Chopper
2d1140df40 会员积分默认倒序 2021-06-01 08:52:33 +08:00
Chopper
5b162d0f8c 增加star标记 2021-05-31 11:47:44 +08:00
Chopper
78aee87b45 Merge branch 'Bulbasaur' of gitee.com:beijing_hongye_huicheng/lilishop into Bulbasaur 2021-05-31 11:34:47 +08:00
Chopper
e09747c410 支持elk 2021-05-31 11:34:43 +08:00
lifenlong
7fa0fb75b1 订单付款后添加是否支持原路退款。 2021-05-31 08:37:15 +08:00
lifenlong
3639ed731b 虚拟订单核验 2021-05-29 12:31:38 +08:00
lifenlong
e5d4207839 虚拟商品订单创建核验码 2021-05-29 11:37:55 +08:00
lifenlong
969437fc34 添加商品类型:实物商品、虚拟商品、电子卡券 2021-05-28 17:43:55 +08:00
lifenlong
814d118d77 运营后台可设置推荐直播间 2021-05-28 12:10:33 +08:00
Chopper
28d8efb8cb Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-05-27 11:39:15 +08:00
Chopper
fb93625c60 增加环境安装文档 2021-05-27 11:38:55 +08:00
lifenlong
c58524cf94 创建直播商品VO,显示直播商品的库存以及店铺名称 2021-05-26 18:40:54 +08:00
lifenlong
5b5681d748 支持短信验证码登录 2021-05-26 17:57:51 +08:00
lifenlong
99b9e8cf91 导出订单发货Excel,上传Excel订单批量发货 2021-05-26 17:09:55 +08:00
Chopper
f82fef9f3d 授权返回 readme 修改 2021-05-26 09:28:52 +08:00
Chopper
18d3401d01 Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop 2021-05-26 09:27:33 +08:00
Chopper
b855cfb5f8 积分商品店铺名称问题处理 2021-05-26 09:27:27 +08:00
lifenlong
5f93ce3851 会员精准发券,更改改分页进行发送 2021-05-26 08:42:12 +08:00
lifenlong
b4240ae2c0 商品去除买家承担运费、卖家承担运费,配送模板增加选项:包邮 2021-05-26 08:18:28 +08:00
lifenlong
a9ec03f0a4 1.增加直播商品
2.同步直播商品状态
3.展示状态展示直播商品列表
2021-05-25 16:10:16 +08:00
lifenlong
d9ccc4a7b7 添加秒杀活动设置 2021-05-25 08:29:07 +08:00
lifenlong
116a52ea14 合并 2021-05-25 08:10:41 +08:00
lifenlong
e7e29da455 秒杀活动增加活动商品数量 2021-05-25 08:02:31 +08:00
lifenlong
00a0edeade 批量添加直播商品 2021-05-24 18:24:19 +08:00
lifenlong
16cc989cdf 设置秒杀活动为自动开启 2021-05-24 18:18:24 +08:00
lifenlong
5c32fd9d7c 优惠券有效期时间判定,如果是1则是当天 2021-05-24 14:06:22 +08:00
lifenlong
639435ec45 新增优惠券有限期设置类型 2021-05-24 14:00:07 +08:00
lifenlong
777226dc95 优惠券活动发送/触发 2021-05-24 11:09:21 +08:00
lifenlong
8924981556 创建优惠券活动 2021-05-21 19:54:25 +08:00
lifenlong
16498a6850 Merge branch 'master' into Bulbasaur 2021-05-21 17:25:15 +08:00
lifenlong
fa59c9ca73 优惠券活动 2021-05-21 09:11:40 +08:00
lifenlong
a15d5d7c36 Merge branch 'master' into Bulbasaur 2021-05-20 16:42:06 +08:00
lifenlong
a8a6506516 同步直播状态、直播间新增商品数量 2021-05-20 14:56:15 +08:00
lifenlong
2326a5963f Merge branch 'master' into Bulbasaur 2021-05-20 11:36:09 +08:00
lifenlong
cd60eba7a4 微信媒体工具类(临时图片上传) 2021-05-20 09:00:46 +08:00
lifenlong
273d0abbc7 解决冲突 2021-05-19 19:38:17 +08:00
lifenlong
250fffab77 merge master 2021-05-19 19:29:51 +08:00
lifenlong
48f24b675b merge master 2021-05-19 14:26:35 +08:00
lifenlong
37a6455e56 会员积分历史 2021-05-19 09:05:44 +08:00
lifenlong
02827a2f8b 微信小程序直播V0.2 2021-05-18 23:34:05 +08:00
lifenlong
0173ba814e Merge branch 'master' into Bulbasaur 2021-05-18 17:35:48 +08:00
lifenlong
0c3a1928ff merge master 2021-05-18 08:17:14 +08:00
lifenlong
910b665d8a 微信小程序直播V0.2 2021-05-17 17:03:28 +08:00
lifenlong
c049552fc7 去除冗余代码 2021-05-17 12:55:40 +08:00
lifenlong
b0f46a78a6 微信小程序直播间创建、微信小程序直播商品添加、删除、查询状态 2021-05-17 12:00:45 +08:00
lifenlong
591ce04e42 会员经验值设置 2021-05-17 09:24:58 +08:00
lifenlong
c8a43573fd 会员积分设置,会员下单赠送积分(非积分订单),订单售后扣除积分 2021-05-17 09:04:10 +08:00
lifenlong
9fae7ac565 Merge branch 'master' into Bulbasaur 2021-05-17 08:18:58 +08:00
lifenlong
57d65f3fd9 会员等级V0.1 2021-05-16 23:41:33 +08:00
584 changed files with 9591 additions and 7359 deletions

106
README.md
View File

@@ -5,6 +5,8 @@
[![star](https://gitee.com/beijing_hongye_huicheng/lilishop/badge/star.svg?theme=dark)](https://gitee.com/beijing_hongye_huicheng/lilishop/stargazers)
![github](https://img.shields.io/github/stars/hongyehuicheng/lilishop.svg?style=social&logo=#181717)
### 介绍
**官网**https://pickmall.cn
@@ -24,7 +26,7 @@ Lilishop 是一款Java开发基于SpringBoot研发的B2B2C多用户商城
### 文档
**产品文档**需求、架构、使用、部署、开发https://docs.pickmall.cn
**功能清单** 功能列表https://docs.qq.com/sheet/DQ1Z2dWJKUnBRZEt5
### 项目链接(gitee)
@@ -62,8 +64,32 @@ Lilishop 是一款Java开发基于SpringBoot研发的B2B2C多用户商城
温馨提示由于服务较多如果笔记本环境启动内存没有32g可能无法启动成功macbookpro 2020 16g内存启动无法成功台式机在16g内存、AMD 3700x 的ubuntu系统成功运行。
##### 下载docker脚本
##### docker环境安装已安装的用户可跳过
```shell
#安装依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
#设置源
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum makecache fast
#安装docker
sudo yum install docker-ce
#启动服务
sudo systemctl start docker
#安装docker-compose
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
#授权
sudo chmod +x /usr/local/bin/docker-compose
#检测版本号
docker-compose -v
```
##### 下载docker-compose脚本
`git clone https://gitee.com/beijing_hongye_huicheng/docker.git `
##### 部署基础环境
`docker-compose up -d`
@@ -118,8 +144,6 @@ PS:单独部署的话数据库文件访问这里https://gitee.com/beijing_
#### 移动端
<img src="https://pickmall.cn/assets/imgs/other/app.gif" alt="管理端功能展示" style="zoom:50%;" />
<img src="https://pickmall.cn/assets/imgs/other/app.gif" alt="移动端功能展示" style="zoom:50%;" />
@@ -170,42 +194,23 @@ PS:单独部署的话数据库文件访问这里https://gitee.com/beijing_
#### 计划每个月发布一个版本,具体时间可能有出入
时间2021年6月15日
```
新增功能:
1.微信小程序直播
2.优惠券活动
3.新人赠券
4.准确发券
5.用户等级
6.数据导出
7.订单批量
8.APP版本升级检测
9.积分商城
功能优化:
1.优惠券有效期增加类型:设置领取后*内有效。
2.秒杀活动设置为每天开启,需设置秒杀活动开启时间。
3.店铺配送模板,配送地区如果选择省份则下方的市级地址不展示。
4.店铺配送模板支持,店铺包邮。
5.普通商品设置去除卖家承担运费。
```
时间2021年7月15日
```
新增功能:
1.会员权益
2.支持用户升级会员
3.供求
4.IM腾讯云智服
5.服务商品
6.店铺支持订单核销
7.店铺自提点
1.积分商城
2.店铺移动端
3.店铺支持发货
4.供求单
5.店铺自提点
6.移动端展示附近店铺
7.开屏广告
8.会员站内消息
9.移动端店铺入驻
功能优化:
1.用户分享商城、关注店铺、邀请新用户可获取积分、经验值。
2.隐私管理功能
2.移动端店铺首页优化
```
时间2021年8月16日
@@ -213,15 +218,37 @@ PS:单独部署的话数据库文件访问这里https://gitee.com/beijing_
```
新增功能:
1.微淘功能
2.店铺移动端
3.店铺发货单
2.相册管理功能
3.店铺申请品牌
4.第三方商品导入淘宝、99api
5.用户等级
6.用户升级会员
7.会员权益
8.促销活动:第二件*折
9.促销活动:商品打包价
10.促销活动:商品组合购
11.促销活动:进店赠券
12.代客退单
功能优化:
1.批量上传商品分类
2.店铺维护开票项目
3.店铺展示营销中心
```
时间2021年9月15日
```
新增功能:
增加供应商功能
1.增加供应商功能
2.商品预售
3.商品预约
4.电子券码
5.企业会员
6.企业会员购
7.商品批发价
功能优化:
1.店铺运费模板支持按照体积计算
2.店铺支持自定义移动端首页
```
### 版本升级
@@ -269,7 +296,10 @@ PS:单独部署的话数据库文件访问这里https://gitee.com/beijing_
2.禁止将本开源的代码和资源进行任何形式任何名义的出售.
3.限制商用如果需要商业使用请联系我们。QQ3409056806.
3.软件受国家计算机软件著作权保护登记号2021SR0805085
4.限制商用如果需要商业使用请联系我们。QQ3409056806.
### 交流群

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.lili</groupId>
<artifactId>lili-shop-parent</artifactId>
<version>1.0.1</version>
<version>4.2.0</version>
</parent>
<artifactId>admin</artifactId>

View File

@@ -37,11 +37,11 @@ public class AdminApplication {
successHandler.setDefaultTargetUrl(this.adminServer.path("/"));
http.authorizeRequests().antMatchers("/instances**").permitAll();
http.authorizeRequests(
(authorizeRequests) -> authorizeRequests.antMatchers(this.adminServer.path("/assets/**")).permitAll() // 授予公众对所有静态资产和登录页面的访问权限。
(authorizeRequests) -> authorizeRequests.antMatchers(this.adminServer.path("/assets/**")).permitAll() //授予公众对所有静态资产和登录页面的访问权限。
.antMatchers(this.adminServer.path("/login")).permitAll().anyRequest().authenticated() //其他所有请求都必须经过验证。
).formLogin(
(formLogin) -> formLogin.loginPage(this.adminServer.path("/login")).successHandler(successHandler).and() // 配置登录和注销。
).logout((logout) -> logout.logoutUrl(this.adminServer.path("/logout"))).httpBasic(Customizer.withDefaults()) // 启用HTTP基本支持。这是Spring Boot Admin Client注册所必需的。
(formLogin) -> formLogin.loginPage(this.adminServer.path("/login")).successHandler(successHandler).and() //配置登录和注销。
).logout((logout) -> logout.logoutUrl(this.adminServer.path("/logout"))).httpBasic(Customizer.withDefaults()) //启用HTTP基本支持。这是Spring Boot Admin Client注册所必需的。
.csrf().disable()
.rememberMe((rememberMe) -> rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600));
}

View File

@@ -10,14 +10,14 @@
<parent>
<groupId>cn.lili</groupId>
<artifactId>lili-shop-parent</artifactId>
<version>1.0.1</version>
<version>4.2.0</version>
</parent>
<dependencies>
<dependency>
<groupId>cn.lili</groupId>
<artifactId>framework</artifactId>
<version>1.0.1</version>
<version>4.2.0</version>
</dependency>
<dependency>

View File

@@ -1,23 +0,0 @@
package cn.lili.controller;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.spring.web.SpringfoxWebMvcConfiguration;
/**
* SwaggerBootstrapUiDemoApplication
*
* @author Chopper
* @version v1.0
* 2020-12-09 20:09
*/
@ConditionalOnClass(SpringfoxWebMvcConfiguration.class)
public class SwaggerBootstrapUiDemoApplication implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}

View File

@@ -1,6 +1,8 @@
package cn.lili.controller.goods;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.distribution.service.DistributionService;
@@ -20,6 +22,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
@@ -37,6 +40,7 @@ import java.util.Map;
* @author Chopper
* @date 2020/11/16 10:06 下午
*/
@Slf4j
@Api(tags = "买家端,商品接口")
@RestController
@RequestMapping("/buyer/goods")
@@ -80,12 +84,18 @@ public class GoodsBuyerController {
@PageViewPoint(type = PageViewEnum.SKU, id = "#id")
public ResultMessage<Map<String, Object>> getSku(@NotNull(message = "商品ID不能为空") @PathVariable("goodsId") String goodsId,
@NotNull(message = "SKU ID不能为空") @PathVariable("skuId") String skuId) {
try {
// 读取选中的列表
Map<String, Object> map = goodsSkuService.getGoodsSkuDetail(goodsId, skuId);
return ResultUtil.data(map);
} catch (ServiceException se) {
log.info(se.getMsg(), se);
throw se;
} catch (Exception e) {
log.error(ResultCode.GOODS_ERROR.message(), e);
return ResultUtil.error(ResultCode.GOODS_ERROR);
}
Map<String, Object> map = goodsSkuService.getGoodsSkuDetail(goodsId, skuId);
return ResultUtil.data(map);
}
@ApiOperation(value = "获取商品分页列表")

View File

@@ -1,5 +1,6 @@
package cn.lili.controller.member;
import cn.lili.common.enums.SwitchEnum;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.ResultMessage;
@@ -55,7 +56,7 @@ public class MemberEvaluationBuyerController {
public ResultMessage<IPage<MemberEvaluation>> queryMineEvaluation(EvaluationQueryParams evaluationQueryParams) {
//设置当前登录会员
evaluationQueryParams.setMemberId(UserContext.getCurrentUser().getId());
return ResultUtil.data(memberEvaluationService.queryByParams(evaluationQueryParams));
return ResultUtil.data(memberEvaluationService.managerQuery(evaluationQueryParams));
}
@ApiOperation(value = "查看某一个商品的评价列表")
@@ -65,7 +66,8 @@ public class MemberEvaluationBuyerController {
@NotNull @PathVariable("goodsId") String goodsId) {
//设置查询查询商品
evaluationQueryParams.setGoodsId(goodsId);
return ResultUtil.data(memberEvaluationService.queryByParams(evaluationQueryParams));
evaluationQueryParams.setStatus(SwitchEnum.OPEN.name());
return ResultUtil.data(memberEvaluationService.managerQuery(evaluationQueryParams));
}
@ApiOperation(value = "查看某一个商品的评价数量")

View File

@@ -1,12 +1,13 @@
package cn.lili.controller.member;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.message.entity.enums.MessageStatusEnum;
import cn.lili.modules.member.entity.dos.MemberMessage;
import cn.lili.modules.member.entity.vo.MemberMessageQueryVO;
import cn.lili.modules.member.service.MemberMessageService;
import cn.lili.modules.message.entity.dos.MemberMessage;
import cn.lili.modules.message.entity.vos.MemberMessageQueryVO;
import cn.lili.modules.message.service.MemberMessageService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -34,21 +35,23 @@ public class MemberMessageBuyerController {
@ApiOperation(value = "分页获取会员站内消息")
@GetMapping
public ResultMessage<IPage<MemberMessage>> page(MemberMessageQueryVO memberMessageQueryVO, PageVO page) {
memberMessageQueryVO.setMemberId(UserContext.getCurrentUser().getId());
return ResultUtil.data(memberMessageService.getPage(memberMessageQueryVO, page));
}
@ApiOperation(value = "消息已读")
@ApiImplicitParam(name = "messageId", value = "会员消息id", required = true, paramType = "path")
@PutMapping
public ResultMessage<Boolean> read(@PathVariable String messageId) {
@PutMapping("/{message_id}")
public ResultMessage<Boolean> read(@PathVariable("message_id") String messageId) {
return ResultUtil.data(memberMessageService.editStatus(MessageStatusEnum.ALREADY_READY.name(), messageId));
}
@ApiOperation(value = "消息删除")
@ApiOperation(value = "消息放入回收站")
@ApiImplicitParam(name = "messageId", value = "会员消息id", required = true, paramType = "path")
@DeleteMapping
public ResultMessage<Boolean> deleteMessage(@PathVariable String messageId) {
return ResultUtil.data(memberMessageService.deleteMessage(messageId));
@DeleteMapping("/{message_id}")
public ResultMessage<Boolean> deleteMessage(@PathVariable("message_id") String messageId) {
return ResultUtil.data(memberMessageService.editStatus(MessageStatusEnum.ALREADY_REMOVE.name(), messageId));
}

View File

@@ -1,8 +1,13 @@
package cn.lili.controller.other;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.utils.PageUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.system.entity.dos.AppVersion;
import cn.lili.modules.system.service.AppVersionService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
@@ -33,4 +38,13 @@ public class AppVersionBuyerController {
public ResultMessage<Object> getAppVersion(@PathVariable String appType) {
return ResultUtil.data(appVersionService.getAppVersion(appType));
}
@ApiOperation(value = "获取版本号列表")
@ApiImplicitParam(name = "appType", value = "app类型", required = true, paramType = "path")
@GetMapping("/appVersion/{appType}")
public ResultMessage<IPage<AppVersion>> appVersion(@PathVariable String appType, PageVO pageVO) {
IPage<AppVersion> page = appVersionService.page(PageUtil.initPage(pageVO), new LambdaQueryWrapper<AppVersion>().eq(AppVersion::getType, appType));
return ResultUtil.data(page);
}
}

View File

@@ -0,0 +1,48 @@
package cn.lili.controller.other.broadcast;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.broadcast.entity.dos.Studio;
import cn.lili.modules.broadcast.service.StudioService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 买家端,直播间接口
*
* @author Bulbasaur
* @date: 2021/5/20 12:03 下午
*/
@RestController
@Api(tags = "买家端,直播间接口")
@RequestMapping("/buyer/broadcast/studio")
public class StudioController {
@Autowired
private StudioService studioService;
@ApiOperation(value = "获取店铺直播间列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "recommend", value = "是否推荐", paramType = "query", dataType = "int"),
@ApiImplicitParam(name = "status", value = "直播间状态", paramType = "query", dataType = "String")
})
@GetMapping
public ResultMessage<IPage<Studio>> page(PageVO pageVO, Integer recommend, String status) {
return ResultUtil.data(studioService.studioList(pageVO, recommend, status));
}
@ApiOperation(value = "获取店铺直播间回放地址")
@GetMapping("/getLiveInfo/{roomId}")
public ResultMessage<Object> getLiveInfo(Integer roomId) {
return ResultUtil.data(studioService.getLiveInfo(roomId));
}
}

View File

@@ -53,7 +53,7 @@ public class DistributionBuyerController {
@ApiOperation(value = "获取分销员分页订单列表")
@GetMapping("/distributionOrder")
public ResultMessage<IPage<DistributionOrder>> distributionOrderPage(DistributionOrderSearchParams distributionOrderSearchParams) {
distributionOrderSearchParams.setDistributionId(UserContext.getCurrentUser().getId());
distributionOrderSearchParams.setDistributionId(distributionService.getDistribution().getId());
return ResultUtil.data(distributionOrderService.getDistributionOrderPage(distributionOrderSearchParams));
}

View File

@@ -63,11 +63,11 @@ public class MemberBuyerController {
public ResultMessage<Object> smsLogin(@NotNull(message = "手机号为空") @RequestParam String mobile,
@NotNull(message = "验证码为空") @RequestParam String code,
@RequestHeader String uuid) {
// if(smsUtil.verifyCode(mobile,VerificationEnums.LOGIN,uuid,code)){
return ResultUtil.data(memberService.mobilePhoneLogin(mobile));
// }else {
// throw new ServiceException("验证码错误");
// }
if (smsUtil.verifyCode(mobile, VerificationEnums.LOGIN, uuid, code)) {
return ResultUtil.data(memberService.mobilePhoneLogin(mobile));
} else {
throw new ServiceException("验证码错误");
}
}
@ApiOperation(value = "注册用户")

View File

@@ -17,9 +17,11 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@@ -29,6 +31,7 @@ import java.io.IOException;
* @author Chopper
* @date 2020-11-25 19:29
*/
@Slf4j
@RestController
@Api(tags = "买家端,web联合登录")
@RequestMapping("/buyer/connect")
@@ -60,8 +63,8 @@ public class ConnectBuyerWebController {
@ApiOperation(value = "信任登录统一回调地址", hidden = true)
@GetMapping("/callback/{type}")
public void callBack(@PathVariable String type, AuthCallback callback, HttpServletResponse httpServletResponse) throws IOException {
connectUtil.callback(type, callback, httpServletResponse);
public void callBack(@PathVariable String type, AuthCallback callback, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
connectUtil.callback(type, callback,httpServletRequest, httpServletResponse);
}
@ApiOperation(value = "信任登录响应结果获取")
@@ -92,7 +95,7 @@ public class ConnectBuyerWebController {
try {
return ResultUtil.data(connectService.appLoginCallback(authUser, uuid));
} catch (Exception e) {
e.printStackTrace();
log.error("unionID登录错误",e);
}
return null;
}

View File

@@ -2,17 +2,18 @@ package cn.lili.controller.payment;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.payment.kit.CashierSupport;
import cn.lili.modules.payment.kit.dto.PayParam;
import cn.lili.modules.payment.kit.enums.PaymentClientEnum;
import cn.lili.modules.payment.kit.enums.PaymentMethodEnum;
import cn.lili.modules.payment.kit.params.dto.CashierParam;
import cn.lili.modules.payment.service.PaymentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -26,6 +27,7 @@ import javax.servlet.http.HttpServletResponse;
* @author Chopper
* @date 2020-12-18 16:59
*/
@Slf4j
@RestController
@Api(tags = "买家端,收银台接口")
@RequestMapping("/buyer/cashier")
@@ -33,8 +35,6 @@ public class CashierController {
@Autowired
private CashierSupport cashierSupport;
@Autowired
private PaymentService paymentService;
@ApiImplicitParams({
@@ -65,8 +65,11 @@ public class CashierController {
try {
return cashierSupport.payment(paymentMethodEnum, paymentClientEnum, request, response, payParam);
} catch (ServiceException se) {
log.info("支付异常", se);
throw se;
} catch (Exception e) {
e.printStackTrace();
log.error("收银台支付错误", e);
}
return null;

View File

@@ -17,29 +17,29 @@ import java.util.List;
/**
* 买家端,限时抢购接口
* 买家端,秒杀活动接口
*
* @author paulG
* @date 2020/11/17 2:30 下午
*/
@Api(tags = "买家端,限时抢购接口")
@Api(tags = "买家端,秒杀活动接口")
@RestController
@RequestMapping("/buyer/promotion/seckill")
public class SeckillBuyerController {
/**
* 限时抢购
* 秒杀活动
*/
@Autowired
private SeckillApplyService seckillApplyService;
@ApiOperation(value = "获取当天限时抢购信息")
@ApiOperation(value = "获取当天秒杀活动信息")
@GetMapping
public ResultMessage<List<SeckillTimelineVO>> getSeckillTime() {
return ResultUtil.data(seckillApplyService.getSeckillTimeline());
}
@ApiOperation(value = "获取某个时刻的限时抢购商品信息")
@ApiOperation(value = "获取某个时刻的秒杀活动商品信息")
@GetMapping("/{timeline}")
public ResultMessage<List<SeckillGoodsVO>> getSeckillGoods(@PathVariable Integer timeline) {
return ResultUtil.data(seckillApplyService.getSeckillGoods(timeline));

View File

@@ -50,8 +50,17 @@ public class CartController {
public ResultMessage<Object> add(@NotNull(message = "产品id不能为空") String skuId,
@NotNull(message = "购买数量不能为空") @Min(value = 1, message = "加入购物车数量必须大于0") Integer num,
String cartType) {
cartService.add(skuId, num, cartType);
return ResultUtil.success();
try {
//读取选中的列表
cartService.add(skuId, num, cartType);
return ResultUtil.success();
} catch (ServiceException se) {
log.info(se.getMsg(), se);
throw se;
} catch (Exception e) {
log.error(ResultCode.CART_ERROR.message(), e);
throw new ServiceException(ResultCode.CART_ERROR);
}
}
@@ -148,10 +157,11 @@ public class CartController {
@GetMapping("/checked")
public ResultMessage<TradeDTO> cartChecked(@NotNull(message = "读取选中列表") String way) {
try {
// 读取选中的列表
//读取选中的列表
return ResultUtil.data(this.cartService.getCheckedTradeDTO(CartTypeEnum.valueOf(way)));
} catch (ServiceException e) {
throw e;
} catch (ServiceException se) {
log.error(se.getMsg(), se);
throw se;
} catch (Exception e) {
log.error(ResultCode.CART_ERROR.message(), e);
throw new ServiceException(ResultCode.CART_ERROR);
@@ -193,6 +203,9 @@ public class CartController {
try {
cartService.shippingMethod(selleId, shippingMethod, way);
return ResultUtil.success();
} catch (ServiceException se) {
log.error(se.getMsg(), se);
throw se;
} catch (Exception e) {
log.error(ResultCode.CART_ERROR.message(), e);
throw new ServiceException(ResultCode.CART_ERROR);
@@ -226,10 +239,11 @@ public class CartController {
@PostMapping(value = "/create/trade", consumes = "application/json", produces = "application/json")
public ResultMessage<Object> crateTrade(@RequestBody TradeParams tradeParams) {
try {
// 读取选中的列表
//读取选中的列表
return ResultUtil.data(this.cartService.createTrade(tradeParams));
} catch (ServiceException e) {
throw e;
} catch (ServiceException se) {
log.info(se.getMsg(), se);
throw se;
} catch (Exception e) {
log.error(ResultCode.ORDER_ERROR.message(), e);
throw new ServiceException(ResultCode.ORDER_ERROR);

View File

@@ -37,7 +37,8 @@ public class WalletLogBuyerController {
//获取当前登录用户
AuthUser authUser = UserContext.getCurrentUser();
//构建查询 返回数据
IPage<WalletLog> depositLogPage = walletLogService.page(PageUtil.initPage(page), new QueryWrapper<WalletLog>().eq("member_id", authUser.getId()));
IPage<WalletLog> depositLogPage = walletLogService.page(PageUtil.initPage(page),
new QueryWrapper<WalletLog>().eq("member_id", authUser.getId()).orderByDesc("create_time"));
return ResultUtil.data(depositLogPage);
}
}

View File

@@ -67,7 +67,7 @@ public class BuyerAuthenticationFilter extends BasicAuthenticationFilter {
//从header中获取jwt
String jwt = request.getHeader(SecurityEnum.HEADER_TOKEN.getValue());
try {
// 如果没有token 则return
//如果没有token 则return
if (StrUtil.isBlank(jwt)) {
chain.doFilter(request, response);
return;
@@ -99,7 +99,7 @@ public class BuyerAuthenticationFilter extends BasicAuthenticationFilter {
String json = claims.get(SecurityEnum.USER_CONTEXT.getValue()).toString();
AuthUser authUser = new Gson().fromJson(json, AuthUser.class);
// 校验redis中是否有权限
//校验redis中是否有权限
if (cache.hasKey(CachePrefix.ACCESS_TOKEN.getPrefix(UserEnums.MEMBER) + jwt)) {
//构造返回信息
List<GrantedAuthority> auths = new ArrayList<>();

View File

@@ -48,35 +48,35 @@ public class BuyerSecurityConfig extends WebSecurityConfigurerAdapter {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
.authorizeRequests();
// 配置的url 不需要授权
//配置的url 不需要授权
for (String url : ignoredUrlsProperties.getUrls()) {
registry.antMatchers(url).permitAll();
}
registry
.and()
// 禁止网页iframe
//禁止网页iframe
.headers().frameOptions().disable()
.and()
.logout()
.permitAll()
.and()
.authorizeRequests()
// 任何请求
//任何请求
.anyRequest()
// 需要身份认证
//需要身份认证
.authenticated()
.and()
// 允许跨域
//允许跨域
.cors().configurationSource((CorsConfigurationSource) SpringContextUtil.getBean("corsConfigurationSource")).and()
// 关闭跨站请求防护
//关闭跨站请求防护
.csrf().disable()
// 前后端分离采用JWT 不需要session
//前后端分离采用JWT 不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// 自定义权限拒绝处理类
//自定义权限拒绝处理类
.exceptionHandling().accessDeniedHandler(accessDeniedHandler)
.and()
// 添加JWT认证过滤器
//添加JWT认证过滤器
.addFilter(new BuyerAuthenticationFilter(authenticationManager(), cache));
}

View File

@@ -4,9 +4,6 @@ server:
servlet:
context-path: /
# 正式部署时候,解开此处配置,防止文件夹被清除导致的文件上传失败问题
# multipart:
# location: /Users/lifenlong/Desktop/ceshi
tomcat:
uri-encoding: UTF-8
threads:
@@ -127,7 +124,7 @@ spring:
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: true
show: false
# 忽略TOKEN 鉴权 的url
ignored:
@@ -138,21 +135,22 @@ ignored:
- /MP_verify_qSyvBPhDsPdxvOhC.txt
- /weixin/**
- /source/**
- /buyer/store/**
- /buyer/mini-program/**
- /buyer/cashier/**
- /buyer/pageData/**
- /buyer/article/**
- /buyer/goods/**
- /buyer/category/**
- /buyer/shop/**
- /buyer/store/**
- /buyer/connect/**
- /buyer/members/**
- /buyer/promotion/pintuan
- /buyer/promotion/seckill
- /buyer/promotion/pintuan/**
- /buyer/promotion/seckill/**
- /buyer/promotion/pointsGoods/**
- /buyer/memberEvaluation/**/goodsEvaluation
- /buyer/memberEvaluation/**/evaluationNumber
- /buyer/appVersion/**
- /buyer/broadcast/studio/**
- /druid/**
- /swagger-ui.html
- /doc.html
@@ -262,7 +260,8 @@ lili:
# account:
# username: elastic
# password: LiLiShopES
logstash:
server: 192.168.0.116:4560
rocketmq:
promotion-topic: lili_promotion_topic
promotion-group: lili_promotion_group

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--应用名称-->
<property name="APP_NAME" value="buyer-api"/>
<!--日志文件保存路径-->
<property name="LOG_FILE_PATH" value="lili-logs"/>
<contextName>${APP_NAME}</contextName>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--输出到elk的LOGSTASH-->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>127.0.0.1:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
</providers>
<!--自定义字段 区分项目-->
<customFields>{"appName":"${APP_NAME}"}</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="LOGSTASH"/>
</root>
</configuration>

View File

@@ -50,9 +50,9 @@ class CartTest {
@Test
void createTrade() {
// TradeDTO allTradeDTO = cartService.getAllTradeDTO();
// Assert.assertNotNull(allTradeDTO);
// System.out.println(JsonUtil.objectToJson(allTradeDTO));
// TradeDTO allTradeDTO = cartService.getAllTradeDTO();
// Assert.assertNotNull(allTradeDTO);
// System.out.println(JsonUtil.objectToJson(allTradeDTO));
cartService.createTrade(new TradeParams());
}

View File

@@ -5,6 +5,7 @@ import cn.lili.modules.file.plugin.FileManagerPlugin;
import cn.lili.modules.goods.entity.dos.Brand;
import cn.lili.modules.goods.service.BrandService;
import com.xkcoding.http.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -19,6 +20,7 @@ import java.util.List;
* @author paulG
* @since 2020/11/14
**/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
class FileTest {
@@ -40,10 +42,10 @@ class FileTest {
}
URL url = new URL(brand.getLogo());
InputStream inputStream = url.openStream();
// 上传至第三方云服务或服务器
//上传至第三方云服务或服务器
brand.setLogo(fileManagerPlugin.inputStreamUpload(inputStream, brand.getId() + ".png"));
} catch (IOException e) {
e.printStackTrace();
log.error("上传你文件出错",e);
}
}
brandService.updateBatchById(categoryList);

View File

@@ -2,9 +2,6 @@ server:
servlet:
context-path: /
# 正式部署时候,解开此处配置,防止文件夹被清除导致的文件上传失败问题
# multipart:
# location: /Users/lifenlong/Desktop/ceshi
tomcat:
uri-encoding: UTF-8
threads:
@@ -124,7 +121,7 @@ spring:
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: true
show: false
# 忽略鉴权url
ignored:

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>cn.lili</groupId>
<artifactId>lili-shop-parent</artifactId>
<version>1.0.1</version>
<version>4.2.0</version>
</parent>
<groupId>cn.lili</groupId>
@@ -17,7 +17,7 @@
<dependency>
<groupId>cn.lili</groupId>
<artifactId>framework</artifactId>
<version>1.0.1</version>
<version>4.2.0</version>
</dependency>
</dependencies>

View File

@@ -1,6 +1,7 @@
package cn.lili.controller.common;
import cn.lili.common.aop.limiter.annotation.LimitPoint;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.verification.enums.VerificationEnums;
@@ -8,6 +9,7 @@ import cn.lili.common.verification.service.VerificationService;
import cn.lili.common.vo.ResultMessage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -17,8 +19,9 @@ import org.springframework.web.bind.annotation.*;
* @author Chopper
* @date 2020/11/26 15:41
*/
@RequestMapping("/common/slider")
@Slf4j
@RestController
@RequestMapping("/common/slider")
@Api(tags = "滑块验证码接口")
public class SliderImageController {
@@ -35,8 +38,8 @@ public class SliderImageController {
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
return null;
log.error("获取校验接口错误", e);
throw new ServiceException(ResultCode.VERIFICATION_EXIST);
}
}

View File

@@ -12,6 +12,7 @@ import cn.lili.common.utils.CommonUtil;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.ResultMessage;
import cn.lili.config.properties.SystemSetting;
import cn.lili.modules.file.entity.File;
import cn.lili.modules.file.plugin.FileManagerPlugin;
import cn.lili.modules.file.service.FileService;
@@ -51,6 +52,9 @@ public class UploadController {
@Autowired
private Cache cache;
@Autowired
private SystemSetting systemSetting;
@ApiOperation(value = "文件上传")
@PostMapping(value = "/file")
public ResultMessage<Object> upload(MultipartFile file,
@@ -69,7 +73,7 @@ public class UploadController {
}
if (StringUtils.isNotBlank(base64)) {
// base64上传
//base64上传
file = Base64DecodeMultipartFile.base64Convert(base64);
}
String result = "";
@@ -77,9 +81,9 @@ public class UploadController {
File newFile = new File();
try {
InputStream inputStream = file.getInputStream();
// 上传至第三方云服务或服务器
//上传至第三方云服务或服务器
result = fileManagerPlugin.inputStreamUpload(inputStream, fileKey);
// 保存数据信息至数据库
//保存数据信息至数据库
newFile.setName(file.getOriginalFilename());
newFile.setFileSize(file.getSize());
newFile.setFileType(file.getContentType());
@@ -102,4 +106,9 @@ public class UploadController {
}
@ApiOperation(value = "返回licences")
@PostMapping(value = "/licences")
public ResultMessage<Object> licences() {
return ResultUtil.data(systemSetting.getLicences());
}
}

View File

@@ -48,18 +48,18 @@ public class CommonSecurityConfig extends WebSecurityConfigurerAdapter {
.authorizeRequests();
registry
.and()
// 禁止网页iframe
//禁止网页iframe
.headers().frameOptions().disable()
.and()
.authorizeRequests()
// 任何请求
//任何请求
.anyRequest()
// 需要身份认证
//需要身份认证
.permitAll()
.and()
// 允许跨域
//允许跨域
.cors().configurationSource(corsConfigurationSource).and()
// 关闭跨站请求防护
//关闭跨站请求防护
.csrf().disable();
}

View File

@@ -4,9 +4,6 @@ server:
servlet:
context-path: /
# 正式部署时候,解开此处配置,防止文件夹被清除导致的文件上传失败问题
# multipart:
# location: /Users/lifenlong/Desktop/ceshi
tomcat:
uri-encoding: UTF-8
threads:
@@ -124,7 +121,7 @@ spring:
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: true
show: false
# 忽略鉴权url
ignored:
@@ -212,8 +209,20 @@ jasypt:
password: lili
lili:
#短信模版配置
sms:
#登录
LOGIN: SMS_205755300
#注册
REGISTER: SMS_205755298
#找回密码
FIND_USER: SMS_205755301
#设置密码
UPDATE_PASSWORD: SMS_205755297
#支付密码
WALLET_PASSWORD: SMS_205755301
system:
isDemoSite: true
isTestModel: true
statistics:
# 在线人数统计 X 小时。这里设置48即统计过去48小时每小时在线人数
onlineMember: 48

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--应用名称-->
<property name="APP_NAME" value="common-api"/>
<!--日志文件保存路径-->
<property name="LOG_FILE_PATH" value="lili-logs"/>
<contextName>${APP_NAME}</contextName>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--输出到elk的LOGSTASH-->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!-- 配置elk日志收集 配饰的是 LOGSTASH 的地址-->
<destination>127.0.0.1:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
</providers>
<!--自定义字段 区分项目-->
<customFields>{"appName":"${APP_NAME}"}</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="LOGSTASH"/>
</root>
</configuration>

View File

@@ -2,9 +2,6 @@ server:
servlet:
context-path: /
# 正式部署时候,解开此处配置,防止文件夹被清除导致的文件上传失败问题
# multipart:
# location: /Users/lifenlong/Desktop/ceshi
tomcat:
uri-encoding: UTF-8
threads:
@@ -124,7 +121,7 @@ spring:
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: true
show: false
# 忽略鉴权url
ignored:
@@ -150,6 +147,7 @@ ignored:
- /buyer/memberEvaluation/**/goodsEvaluation
- /buyer/memberEvaluation/**/evaluationNumber
- /buyer/appVersion/**
- /buyer/broadcast/studio/**
- /store/login/**
- /manager/user/login
- /manager/user/refresh/**
@@ -196,9 +194,9 @@ logging:
# 输出级别
level:
cn.lili: info
# org.hibernate: debug
# org.springframework: debug
# org.springframework.data.mongodb.core: debug
org.hibernate: debug
org.springframework: debug
org.springframework.data.mongodb.core: debug
file:
# 指定路径
path: lili-logs
@@ -212,8 +210,21 @@ jasypt:
password: lili
lili:
#短信模版配置
sms:
#登录
LOGIN: SMS_205755300
#注册
REGISTER: SMS_205755298
#找回密码
FIND_USER: SMS_205755301
#设置密码
UPDATE_PASSWORD: SMS_205755297
#支付密码
WALLET_PASSWORD: SMS_205755301
system:
isDemoSite: false
isTestModel: true
statistics:
# 在线人数统计 X 小时。这里设置48即统计过去48小时每小时在线人数
onlineMember: 48
@@ -239,7 +250,7 @@ lili:
# jwt 细节设定
jwt-setting:
# token过期时间分钟
tokenExpireTime: 60
tokenExpireTime: 30
# 使用Spring @Cacheable注解失效时间
cache:
@@ -263,6 +274,8 @@ lili:
# username: elastic
# password: LiLiShopES
logstash:
server: 192.168.0.116:4560
rocketmq:
promotion-topic: lili_promotion_topic
promotion-group: lili_promotion_group

View File

@@ -8,14 +8,14 @@
<parent>
<groupId>cn.lili</groupId>
<artifactId>lili-shop-parent</artifactId>
<version>1.0.1</version>
<version>4.2.0</version>
</parent>
<dependencies>
<dependency>
<groupId>cn.lili</groupId>
<artifactId>framework</artifactId>
<version>1.0.1</version>
<version>4.2.0</version>
</dependency>
<dependency>

View File

@@ -15,6 +15,8 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 分销订单入库
*
@@ -28,7 +30,7 @@ public class DistributionOrderExecute implements OrderStatusChangeEvent, EveryDa
@Autowired
private DistributionOrderService distributionOrderService;
//分销订单持久层
@Autowired
@Resource
private DistributionOrderMapper distributionOrderMapper;

View File

@@ -0,0 +1,92 @@
package cn.lili.event.impl;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.event.GoodsCommentCompleteEvent;
import cn.lili.event.MemberRegisterEvent;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.service.MemberService;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.ExperienceSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 会员经验值
*
* @author Bulbasaur
* @date: 2021/5/16 11:16 下午
*/
@Service
public class MemberExperienceExecute implements MemberRegisterEvent, GoodsCommentCompleteEvent, OrderStatusChangeEvent {
//配置
@Autowired
private SettingService settingService;
//会员
@Autowired
private MemberService memberService;
//订单
@Autowired
private OrderService orderService;
/**
* 会员注册赠送经验值
* @param member 会员
*/
@Override
public void memberRegister(Member member) {
//获取经验值设置
ExperienceSetting experienceSetting = getExperienceSetting();
//赠送会员经验值
memberService.updateMemberExperience(Long.valueOf(experienceSetting.getRegister().longValue()), true, member.getId(), "会员注册,赠送经验值" + experienceSetting.getRegister());
}
/**
* 商品评价赠送经验值
* @param memberEvaluation 会员评价
*/
@Override
public void goodsComment(MemberEvaluation memberEvaluation) {
//获取经验值设置
ExperienceSetting experienceSetting = getExperienceSetting();
//赠送会员经验值
memberService.updateMemberExperience(Long.valueOf(experienceSetting.getComment().longValue()), true, memberEvaluation.getMemberId(), "会员评价,赠送经验值" + experienceSetting.getComment());
}
/**
* 完成订单赠送经验值
* @param orderMessage 订单消息
*/
@Override
public void orderChange(OrderMessage orderMessage) {
if(orderMessage.getNewStatus().equals(OrderStatusEnum.COMPLETED)){
//获取经验值设置
ExperienceSetting experienceSetting = getExperienceSetting();
//获取订单信息
Order order = orderService.getBySn(orderMessage.getOrderSn());
//计算赠送经验值数量
Double point= CurrencyUtil.mul(experienceSetting.getMoney(),order.getFlowPrice(),0);
//赠送会员经验值
memberService.updateMemberExperience(point.longValue(), true, order.getMemberId(), "会员下单,赠送经验值" + point + "");
}
}
/**
* 获取经验值设置
* @return 经验值设置
*/
private ExperienceSetting getExperienceSetting(){
Setting setting = settingService.get(SettingEnum.EXPERIENCE_SETTING.name());
return new Gson().fromJson(setting.getSettingValue(), ExperienceSetting.class);
}
}

View File

@@ -1,30 +1,37 @@
package cn.lili.event.impl;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.event.AfterSaleStatusChangeEvent;
import cn.lili.event.GoodsCommentCompleteEvent;
import cn.lili.event.MemberRegisterEvent;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.service.MemberService;
import cn.lili.modules.member.service.MemberWalletService;
import cn.lili.modules.order.order.entity.dos.AfterSale;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.OrderPromotionTypeEnum;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.order.trade.entity.enums.AfterSaleStatusEnum;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.PointSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 会员积分
*
* @author Chopper
* @author Bulbasaur
* @date 2020-07-03 11:20
*/
@Service
public class MemberPointExecute implements MemberRegisterEvent, GoodsCommentCompleteEvent {
public class MemberPointExecute implements MemberRegisterEvent, GoodsCommentCompleteEvent, OrderStatusChangeEvent, AfterSaleStatusChangeEvent {
//配置
@Autowired
@@ -32,22 +39,80 @@ public class MemberPointExecute implements MemberRegisterEvent, GoodsCommentComp
//会员
@Autowired
private MemberService memberService;
//订单
@Autowired
private OrderService orderService;
/**
* 会员注册赠送积分
* @param member 会员
*/
@Override
public void memberRegister(Member member) {
//获取签到积分赠送设置
Setting setting = settingService.get(SettingEnum.POINT_SETTING.name());
PointSetting pointSetting = new Gson().fromJson(setting.getSettingValue(), PointSetting.class);
//获取积分设置
PointSetting pointSetting=getPointSetting();
//赠送会员积分
memberService.updateMemberPoint(Long.valueOf(pointSetting.getRegister().longValue()), 1, member.getId(), "会员注册,赠送积分" + pointSetting.getRegister() + "");
memberService.updateMemberPoint(Long.valueOf(pointSetting.getRegister().longValue()), true, member.getId(), "会员注册,赠送积分" + pointSetting.getRegister() + "");
}
/**
* 会员评价赠送积分
* @param memberEvaluation 会员评价
*/
@Override
public void goodsComment(MemberEvaluation memberEvaluation) {
//获取签到积分赠送设置
Setting setting = settingService.get(SettingEnum.POINT_SETTING.name());
PointSetting pointSetting = new Gson().fromJson(setting.getSettingValue(), PointSetting.class);
//获取积分设置
PointSetting pointSetting=getPointSetting();
//赠送会员积分
memberService.updateMemberPoint(Long.valueOf(pointSetting.getComment().longValue()), 1, memberEvaluation.getMemberId(), "会员评价,赠送积分" + pointSetting.getComment() + "");
memberService.updateMemberPoint(Long.valueOf(pointSetting.getComment().longValue()), true, memberEvaluation.getMemberId(), "会员评价,赠送积分" + pointSetting.getComment() + "");
}
/**
* 非积分订单订单完成后赠送积分
* @param orderMessage 订单消息
*/
@Override
public void orderChange(OrderMessage orderMessage) {
if(orderMessage.getNewStatus().equals(OrderStatusEnum.COMPLETED)){
//根据订单编号获取订单数据,如果为积分订单则跳回
Order order = orderService.getBySn(orderMessage.getOrderSn());
if(order.getOrderPromotionType().equals(OrderPromotionTypeEnum.POINT.name())){
return;
}
//获取积分设置
PointSetting pointSetting=getPointSetting();
//计算赠送积分数量
Double point=CurrencyUtil.mul(pointSetting.getMoney(),order.getFlowPrice(),0);
//赠送会员积分
memberService.updateMemberPoint(point.longValue(), true, order.getMemberId(), "会员下单,赠送积分" + point + "");
}
}
/**
* 提交售后后扣除积分
* @param afterSale 售后
*/
@Override
public void afterSaleStatusChange(AfterSale afterSale) {
if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.COMPLETE.name())) {
//获取积分设置
PointSetting pointSetting=getPointSetting();
//计算扣除积分数量
Double point=CurrencyUtil.mul(pointSetting.getMoney(), afterSale.getActualRefundPrice(),0);
//扣除会员积分
memberService.updateMemberPoint(point.longValue(), false, afterSale.getMemberId(), "会员退款,扣除积分" + point + "");
}
}
/**
* 获取积分设置
* @return 积分设置
*/
private PointSetting getPointSetting(){
Setting setting = settingService.get(SettingEnum.POINT_SETTING.name());
return new Gson().fromJson(setting.getSettingValue(), PointSetting.class);
}
}

View File

@@ -11,12 +11,11 @@ import cn.lili.modules.message.service.NoticeMessageService;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.order.entity.dos.AfterSale;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.OrderTypeEnum;
import cn.lili.modules.order.order.entity.enums.OrderPromotionTypeEnum;
import cn.lili.modules.order.order.entity.vo.OrderDetailVO;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.order.trade.entity.enums.AfterSaleStatusEnum;
import cn.lili.modules.order.trade.entity.enums.AfterSaleTypeEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -60,7 +59,7 @@ public class NoticeMessageExecute implements TradeEvent, OrderStatusChangeEvent,
//如果订单状态不为空
if (orderDetailVO != null) {
Map<String, String> params = new HashMap<>();
switch (orderMessage.getNewStatus()){
switch (orderMessage.getNewStatus()) {
//如果订单新的状态为已取消 则发送取消订单站内信
case CANCELLED:
params.put(NoticeMessageParameterEnum.CANCEL_REASON.getType(), orderDetailVO.getOrder().getCancelReason());
@@ -83,7 +82,7 @@ public class NoticeMessageExecute implements TradeEvent, OrderStatusChangeEvent,
break;
//如果是拼团订单,发送拼团成功消息
case UNDELIVERED:
if(orderDetailVO.getOrder().getOrderType().equals(OrderTypeEnum.PINTUAN.name())){
if (OrderPromotionTypeEnum.PINTUAN.name().equals(orderDetailVO.getOrder().getOrderPromotionType())) {
//拼团成功消息
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.PINTUAN_SUCCESS);
}
@@ -149,11 +148,14 @@ public class NoticeMessageExecute implements TradeEvent, OrderStatusChangeEvent,
@Override
public void memberPointChange(MemberPointMessage memberPointMessage) {
if (memberPointMessage == null) {
return;
}
//组织站内信参数
NoticeMessageDTO noticeMessageDTO = new NoticeMessageDTO();
noticeMessageDTO.setMemberId(memberPointMessage.getMemberId());
Map<String, String> params = new HashMap<>();
if (memberPointMessage.getType().equals(1)) {
if (memberPointMessage.getType()) {
params.put("expenditure_points", "0");
params.put("income_points", memberPointMessage.getPoint().toString());
} else {

View File

@@ -0,0 +1,31 @@
package cn.lili.event.impl;
import cn.lili.event.TradeEvent;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.order.service.TradeService;
import cn.lili.modules.payment.kit.enums.PaymentMethodEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 订单状态处理类
*
* @author Chopper
* @date 2020-07-03 11:20
**/
@Service
public class OrderStatusHandlerExecute implements TradeEvent {
@Autowired
private TradeService tradeService;
@Override
public void orderCreate(TradeDTO tradeDTO) {
//如果订单需要支付金额为0则将订单步入到下一个流程
if (tradeDTO.getPriceDetailDTO().getFlowPrice() <= 0) {
tradeService.payTrade(tradeDTO.getSn(), PaymentMethodEnum.BANK_TRANSFER.name(), "-1");
}
}
}

View File

@@ -10,8 +10,6 @@ import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.payment.entity.RefundLog;
import cn.lili.modules.payment.kit.Payment;
import cn.lili.modules.payment.kit.enums.PaymentMethodEnum;
import cn.lili.modules.payment.service.PaymentService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -24,9 +22,6 @@ import org.springframework.stereotype.Service;
@Service
public class PaymentExecute implements OrderStatusChangeEvent {
//支付日志
@Autowired
private PaymentService paymentService;
//订单
@Autowired
private OrderService orderService;

View File

@@ -0,0 +1,41 @@
package cn.lili.event.impl;
import cn.lili.event.MemberRegisterEvent;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.promotion.entity.dos.CouponActivity;
import cn.lili.modules.promotion.entity.enums.CouponActivityTypeEnum;
import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum;
import cn.lili.modules.promotion.service.CouponActivityService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 注册赠券活动
*
* @author Bulbasaur
* @date: 2021/5/24 10:48 上午
*/
@Component
public class RegisteredCouponActivityExecute implements MemberRegisterEvent {
@Autowired
private CouponActivityService couponActivityService;
/**
* 获取进行中的注册赠券的优惠券活动
* 发送注册赠券
*
* @param member 会员
*/
@Override
public void memberRegister(Member member) {
List<CouponActivity> couponActivities = couponActivityService.list(new LambdaQueryWrapper<CouponActivity>()
.eq(CouponActivity::getCouponActivityType, CouponActivityTypeEnum.REGISTERED.name())
.eq(CouponActivity::getPromotionStatus, PromotionStatusEnum.START.name()));
couponActivityService.registered(couponActivities, member);
}
}

View File

@@ -12,6 +12,7 @@ import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
import cn.lili.modules.promotion.entity.enums.PromotionTypeEnum;
import cn.lili.modules.promotion.service.PromotionGoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
@@ -26,9 +27,12 @@ import java.util.List;
* @author Chopper
* @date 2020-07-03 11:20
*/
@Slf4j
@Service
public class StockUpdateExecute implements OrderStatusChangeEvent {
//出库失败消息
static String outOfStockMessage = "库存不足,出库失败";
//Redis
@Autowired
private StringRedisTemplate stringRedisTemplate;
@@ -52,7 +56,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
switch (orderMessage.getNewStatus()) {
case PAID: {
//获取订单详情
OrderDetailVO order = orderService.queryDetail(orderMessage.getOrderSn());
//库存key 和 扣减数量
List<String> keys = new ArrayList<>();
@@ -67,33 +71,41 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
Boolean skuResult = stringRedisTemplate.execute(quantityScript, keys, values.toArray());
//如果库存扣减都成功,则记录成交订单
if (Boolean.TRUE.equals(skuResult)) {
log.info("库存扣减成功,参数为{};{}", keys, values);
//库存确认之后对结构处理
orderService.afterOrderConfirm(orderMessage.getOrderSn());
//成功之后,同步库存
synchroDB(order);
} else {
log.info("库存扣件失败变更缓存key{} 变更缓存value{}", keys, values);
//失败之后取消订单
this.errorOrder(orderMessage.getOrderSn());
}
break;
}
case CANCELLED: {
//获取订单详情
OrderDetailVO order = orderService.queryDetail(orderMessage.getOrderSn());
if (order.getOrder().getPayStatus().equals(PayStatusEnum.PAID.name())) {
//判定是否已支付 并且 非库存不足导致库存回滚 则需要考虑订单库存返还业务
if (order.getOrder().getPayStatus().equals(PayStatusEnum.PAID.name()) && order.getOrder().getCancelReason().equals(outOfStockMessage)) {
//库存key 和 还原数量
List<String> keys = new ArrayList<>();
List<String> values = new ArrayList<>();
//返还商品库存,促销库存不与返还,不然前台展示层有展示逻辑错误
for (OrderItem orderItem : order.getOrderItems()) {
if (PromotionTypeEnum.haveStock(orderItem.getPromotionType())) {
PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(orderItem.getPromotionType());
Integer goodsPromotionOriginStock = promotionGoodsService.getPromotionGoodsStock(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId());
int goodsPromotionStock = goodsPromotionOriginStock + orderItem.getNum();
String promotionGoodsStockCacheKey = PromotionGoodsService.getPromotionGoodsStockCacheKey(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId());
stringRedisTemplate.opsForValue().set(promotionGoodsStockCacheKey, Integer.toString(goodsPromotionStock));
}
String stockCacheKey = GoodsSkuService.getStockCacheKey(orderItem.getSkuId());
Integer goodsOriginStock = goodsSkuService.getStock(orderItem.getSkuId());
int goodsStock = goodsOriginStock + orderItem.getNum();
stringRedisTemplate.opsForValue().set(stockCacheKey, Integer.toString(goodsStock));
keys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()));
int i = orderItem.getNum();
values.add(Integer.toString(i));
}
//批量脚本执行库存回退
Boolean skuResult = stringRedisTemplate.execute(quantityScript, keys, values.toArray());
//返还失败,则记录日志
if (Boolean.FALSE.equals(skuResult)) {
log.error("库存回退异常keys{},回复库存值为: {}", keys, values);
}
rollbackOrderStock(order);
}
break;
}
@@ -108,7 +120,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
* @param orderSn 失败入库订单信息
*/
private void errorOrder(String orderSn) {
orderService.systemCancel(orderSn, "库存不足,出库失败");
orderService.systemCancel(orderSn, outOfStockMessage);
}
@@ -132,8 +144,9 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
}
}
/**
* 写入需要更改促销库存的商品
* 同步库存和促销库存
*
* @param order 订单
*/
@@ -148,7 +161,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
//促销库存key 集合
List<String> promotionKey = new ArrayList<>();
// 循环订单
//循环订单
for (OrderItem orderItem : order.getOrderItems()) {
skuKeys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()));
GoodsSku goodsSku = new GoodsSku();
@@ -159,6 +172,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
if (PromotionTypeEnum.haveStock(orderItem.getPromotionType())) {
PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(orderItem.getPromotionType());
PromotionGoods pGoods = promotionGoodsService.getPromotionGoods(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId());
//记录需要更新的促销库存信息
promotionKey.add(
PromotionGoodsService.getPromotionGoodsStockCacheKey(
promotionTypeEnum,
@@ -170,6 +184,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
goodsSkus.add(goodsSku);
}
//批量获取商品库存
List skuStocks = cache.multiGet(skuKeys);
//循环写入商品库存
for (int i = 0; i < skuStocks.size(); i++) {
@@ -188,8 +203,41 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
}
promotionGoodsService.updateBatchById(promotionGoods);
}
//商品库存包含sku库存集合批量更新商品库存相关
goodsSkuService.updateGoodsStuck(goodsSkus);
log.info("订单确认,库存同步:商品信息--{};促销信息---{}", goodsSkus, promotionGoods);
}
/**
* 恢复商品库存
*
* @param order 订单
*/
private void rollbackOrderStock(OrderDetailVO order) {
//sku商品
List<GoodsSku> goodsSkus = new ArrayList<>();
//sku库存key 集合
List<String> skuKeys = new ArrayList<>();
//循环订单
for (OrderItem orderItem : order.getOrderItems()) {
skuKeys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()));
GoodsSku goodsSku = new GoodsSku();
goodsSku.setId(orderItem.getSkuId());
goodsSkus.add(goodsSku);
}
//批量获取商品库存
List skuStocks = cache.multiGet(skuKeys);
//循环写入商品SKU库存
for (int i = 0; i < skuStocks.size(); i++) {
goodsSkus.get(i).setQuantity(Integer.parseInt(skuStocks.get(i).toString()));
}
log.info("订单取消,库存还原:{}", goodsSkus);
//批量修改商品库存
goodsSkuService.updateBatchById(goodsSkus);
goodsSkuService.updateGoodsStuck(goodsSkus);
}
}

View File

@@ -0,0 +1,72 @@
package cn.lili.event.impl;
import cn.hutool.core.util.RandomUtil;
import cn.lili.common.utils.CommonUtil;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.OrderComplaintStatusEnum;
import cn.lili.modules.order.order.entity.enums.OrderItemAfterSaleStatusEnum;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderItemService;
import cn.lili.modules.order.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 虚拟商品
*
* @author Bulbasaur
* @date: 2021/5/29 9:17 上午
*/
@Component
public class VerificationOrderExecute implements OrderStatusChangeEvent {
@Autowired
private OrderService orderService;
@Autowired
private OrderItemService orderItemService;
@Override
public void orderChange(OrderMessage orderMessage) {
//订单状态为待核验,添加订单添加核验码
if (orderMessage.getNewStatus().equals(OrderStatusEnum.TAKE)) {
//获取订单信息
Order order = orderService.getBySn(orderMessage.getOrderSn());
//获取随机数,判定是否存在
String code = getCode(order.getStoreId());
//设置订单验证码
orderService.update(new LambdaUpdateWrapper<Order>()
.set(Order::getVerificationCode, code)
.eq(Order::getSn, orderMessage.getOrderSn()));
//修改虚拟订单货物可以进行售后、投诉
orderItemService.update(new LambdaUpdateWrapper<OrderItem>().eq(OrderItem::getOrderSn, orderMessage.getOrderSn())
.set(OrderItem::getAfterSaleStatus, OrderItemAfterSaleStatusEnum.NOT_APPLIED)
.set(OrderItem::getCommentStatus, OrderComplaintStatusEnum.NO_APPLY));
}
}
/**
* 获取随机数
* 判断当前店铺下是否使用验证码,如果已使用则重新获取
*
* @param storeId 店铺ID
* @return
*/
private String getCode(String storeId) {
//获取八位验证码
String code = Long.toString(RandomUtil.randomLong(10000000, 99999999));
LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<Order>()
.eq(Order::getVerificationCode, code)
.eq(Order::getStoreId, storeId);
if (orderService.getOne(lambdaQueryWrapper) == null) {
return code;
} else {
return this.getCode(storeId);
}
}
}

View File

@@ -112,7 +112,7 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
for (GoodsCompleteMessage goodsCompleteMessage : goodsCompleteMessageList) {
Goods goods = goodsService.getById(goodsCompleteMessage.getGoodsId());
if (goods != null) {
// 更新商品购买数量
//更新商品购买数量
if (goods.getBuyCount() == null) {
goods.setBuyCount(0);
}
@@ -126,7 +126,7 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
}
GoodsSku goodsSku = goodsSkuService.getById(goodsCompleteMessage.getSkuId());
if (goodsSku != null) {
// 更新商品购买数量
//更新商品购买数量
if (goodsSku.getBuyCount() == null) {
goodsSku.setBuyCount(0);
}

View File

@@ -1,18 +1,27 @@
package cn.lili.listener;
import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.SwitchEnum;
import cn.lili.common.rocketmq.tags.OtherTagsEnum;
import cn.lili.common.sms.SmsUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.vo.MemberSearchVO;
import cn.lili.modules.member.mapper.MemberMapper;
import cn.lili.modules.member.service.MemberService;
import cn.lili.modules.message.entity.dos.MemberMessage;
import cn.lili.modules.message.entity.dos.Message;
import cn.lili.modules.message.entity.dos.StoreMessage;
import cn.lili.modules.message.entity.dto.SmsReachDTO;
import cn.lili.modules.message.entity.enums.MessageSendClient;
import cn.lili.modules.message.entity.enums.MessageStatusEnum;
import cn.lili.modules.message.entity.enums.RangeEnum;
import cn.lili.modules.message.service.MemberMessageService;
import cn.lili.modules.message.service.StoreMessageService;
import cn.lili.modules.store.entity.dos.Store;
import cn.lili.modules.store.service.StoreService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
@@ -41,9 +50,15 @@ public class NoticeSendMessageListener implements RocketMQListener<MessageExt> {
//店铺消息
@Autowired
private StoreMessageService storeMessageService;
//会员消息
@Autowired
private MemberMessageService memberMessageService;
//店铺
@Autowired
private StoreService storeService;
//会员
@Autowired
private MemberService memberService;
@Override
public void onMessage(MessageExt messageExt) {
@@ -51,7 +66,6 @@ public class NoticeSendMessageListener implements RocketMQListener<MessageExt> {
case SMS:
String smsJsonStr = new String(messageExt.getBody());
SmsReachDTO smsReachDTO = JSONUtil.toBean(smsJsonStr, SmsReachDTO.class);
//发送全部会员
if (smsReachDTO.getSmsRange().equals(RangeEnum.ALL.name())) {
//获取所有会员的手机号
@@ -65,38 +79,118 @@ public class NoticeSendMessageListener implements RocketMQListener<MessageExt> {
//管理员发送站内信
case MESSAGE:
Message message = JSONUtil.toBean(new String(messageExt.getBody()), Message.class);
List<StoreMessage> list = new ArrayList<>();
//保存商家记录
if (message.getMessageRange().equals("ALL")) {
List<Store> storeList = storeService.list(new QueryWrapper<Store>().eq("store_disable", "OPEN"));
storeList.forEach(item -> {
StoreMessage storeMessage = new StoreMessage();
storeMessage.setMessageId(message.getId());
storeMessage.setStoreName(item.getStoreName());
storeMessage.setStoreId(item.getId());
storeMessage.setStatus(MessageStatusEnum.UN_READY.name());
storeMessage.setTitle(message.getTitle());
storeMessage.setContent(message.getContent());
list.add(storeMessage);
});
// 管理端发送给商家的站内信
if (message.getMessageClient().equals(MessageSendClient.STORE.name().toLowerCase())) {
saveStoreMessage(message);
} else {
int i = 0;
for (String str : message.getUserIds()) {
StoreMessage storeMessage = new StoreMessage();
storeMessage.setMessageId(message.getId());
storeMessage.setStoreId(str);
storeMessage.setStoreName(message.getUserNames()[i]);
storeMessage.setStatus(MessageStatusEnum.UN_READY.name());
storeMessage.setTitle(message.getTitle());
storeMessage.setContent(message.getContent());
list.add(storeMessage);
i++;
}
//管理员发送给会员的站内信
saveMemberMessage(message);
}
storeMessageService.save(list);
break;
default:
break;
}
}
/**
* 保存店铺消息
*
* @param message 消息
*/
private void saveStoreMessage(Message message) {
List<StoreMessage> list = new ArrayList<>();
//发送全部商家情况
if (message.getMessageRange().equals("ALL")) {
List<Store> storeList = storeService.list(new QueryWrapper<Store>().eq("store_disable", "OPEN"));
storeList.forEach(item -> {
StoreMessage storeMessage = new StoreMessage();
storeMessage.setMessageId(message.getId());
storeMessage.setStoreName(item.getStoreName());
storeMessage.setStoreId(item.getId());
storeMessage.setStatus(MessageStatusEnum.UN_READY.name());
storeMessage.setTitle(message.getTitle());
storeMessage.setContent(message.getContent());
list.add(storeMessage);
});
} else {
//发送给指定商家情况
int i = 0;
for (String str : message.getUserIds()) {
StoreMessage storeMessage = new StoreMessage();
storeMessage.setMessageId(message.getId());
storeMessage.setStoreId(str);
storeMessage.setStoreName(message.getUserNames()[i]);
storeMessage.setStatus(MessageStatusEnum.UN_READY.name());
storeMessage.setTitle(message.getTitle());
storeMessage.setContent(message.getContent());
list.add(storeMessage);
i++;
}
}
if (list.size() > 0) {
//执行保存
storeMessageService.save(list);
}
}
/**
* 保存会员消息
*
* @param message 消息
*/
private void saveMemberMessage(Message message) {
List<MemberMessage> list = new ArrayList<>();
//如果是给所有会员发送消息
if (message.getMessageRange().equals("ALL")) {
//查询所有会员总数,因为会员总数比较大 如果一次性查出来会占用数据库资源,所以要分页查询
MemberSearchVO memberSearchVO = new MemberSearchVO();
memberSearchVO.setDisabled(SwitchEnum.OPEN.name());
Integer memberNum = memberService.getMemberNum(memberSearchVO);
//构建分页查询参数
//100条查一次
Integer pageSize = 100;
Integer pageCount = 0;
pageCount = memberNum / pageSize;
pageCount = memberNum % pageSize > 0 ? pageCount + 1 : pageCount;
for (int i = 1; i <= pageCount; i++) {
PageVO pageVO = new PageVO();
pageVO.setPageSize(pageSize);
pageVO.setPageNumber(i);
IPage<Member> page = memberService.getMemberPage(memberSearchVO, pageVO);
//循环要保存的信息
page.getRecords().forEach(item -> {
MemberMessage memberMessage = new MemberMessage();
memberMessage.setContent(message.getContent());
memberMessage.setTitle(message.getTitle());
memberMessage.setMessageId(message.getId());
memberMessage.setMemberId(item.getId());
memberMessage.setMemberName(item.getUsername());
memberMessage.setStatus(MessageStatusEnum.UN_READY.name());
list.add(memberMessage);
});
}
} else {
//如果是给指定会员发送消息
int i = 0;
for (String str : message.getUserIds()) {
MemberMessage memberMessage = new MemberMessage();
memberMessage.setMessageId(message.getId());
memberMessage.setMemberId(str);
memberMessage.setMemberName(message.getUserNames()[i]);
memberMessage.setStatus(MessageStatusEnum.UN_READY.name());
memberMessage.setTitle(message.getTitle());
memberMessage.setContent(message.getContent());
list.add(memberMessage);
i++;
}
}
if (list.size() > 0) {
//执行保存
memberMessageService.save(list);
}
}
}

View File

@@ -44,6 +44,7 @@ public class OrderMessageListener implements RocketMQListener<MessageExt> {
case ORDER_CREATE:
String key = new String(messageExt.getBody());
TradeDTO tradeDTO = (TradeDTO) cache.get(key);
boolean result = true;
for (TradeEvent event : tradeEvent) {
try {
event.orderCreate(tradeDTO);
@@ -52,8 +53,14 @@ public class OrderMessageListener implements RocketMQListener<MessageExt> {
tradeDTO.getSn(),
event.getClass().getName(),
e);
result = false;
}
}
//如所有步骤顺利完成
if (Boolean.TRUE.equals(result)) {
//清除记录信息的trade cache key
cache.remove(key);
}
break;
//订单状态变更
case STATUS_CHANGE:

View File

@@ -1,15 +1,15 @@
package cn.lili.timetask.handler.impl.bill;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.lili.modules.store.entity.dto.StoreSettlementDay;
import cn.lili.modules.store.mapper.StoreDetailMapper;
import cn.lili.modules.store.service.BillService;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
@@ -25,7 +25,7 @@ public class BillExecute implements EveryDayExecute {
@Autowired
private BillService billService;
//店铺详情
@Autowired
@Resource
private StoreDetailMapper storeDetailMapper;
/**
@@ -36,20 +36,22 @@ public class BillExecute implements EveryDayExecute {
@Override
public void execute() {
//获取当前时间的前一
String day = "," + DateUtil.date().dayOfMonth() + ",";
//获取当前天
int day = DateUtil.date().dayOfMonth();
//获取待结算商家列表
List<StoreSettlementDay> storeList = storeDetailMapper.getSettlementStore(new QueryWrapper<StoreSettlementDay>().like("settlement_cycle", day));
List<StoreSettlementDay> storeList = storeDetailMapper.getSettlementStore(day);
//获取当前时间
DateTime endTime =DateUtil.date();
//批量商家结算
for (StoreSettlementDay storeSettlementDay : storeList) {
//生成结算单
billService.createBill(storeSettlementDay.getStoreId(), storeSettlementDay.getSettlementDay());
billService.createBill(storeSettlementDay.getStoreId(), storeSettlementDay.getSettlementDay(),endTime);
//修改店铺结算时间
storeDetailMapper.updateSettlementDay(storeSettlementDay.getStoreId(), DateUtil.date());
storeDetailMapper.updateSettlementDay(storeSettlementDay.getStoreId(), endTime);
}
}
}

View File

@@ -0,0 +1,25 @@
package cn.lili.timetask.handler.impl.broadcast;
import cn.lili.modules.broadcast.service.CommodityService;
import cn.lili.timetask.handler.EveryHourExecute;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 小程序直播状态获取
*
* @author Bulbasaur
* @date: 2021/5/20 2:52 下午
*/
@Component
public class BroadcastExecute implements EveryHourExecute {
@Autowired
private CommodityService commodityService;
@Override
public void execute() {
//同步直播商品状态
commodityService.getGoodsWareHouse();
}
}

View File

@@ -0,0 +1,38 @@
package cn.lili.timetask.handler.impl.coupon;
import cn.hutool.core.date.DateUtil;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum;
import cn.lili.modules.promotion.service.MemberCouponService;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 优惠券状态监测
*
* @author Bulbasaur
* @date: 2021/5/24 10:08 上午
*/
@Component
public class CouponExecute implements EveryDayExecute {
@Autowired
private MemberCouponService memberCouponService;
/**
* 检测优惠券的使用时间,超期未使用则失效
* 此方法用于领取*天后失效优惠券使用
*/
@Override
public void execute() {
LambdaUpdateWrapper<MemberCoupon> updateWrapper = new LambdaUpdateWrapper<MemberCoupon>()
.eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name())
.le(MemberCoupon::getEndTime, DateUtil.date())
.set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.EXPIRE.name());
this.memberCouponService.update(updateWrapper);
}
}

View File

@@ -39,7 +39,6 @@ public class GoodsExecute implements EveryDayExecute {
new QueryWrapper<MemberEvaluation>()
.between("create_time", DateUtil.yesterday(), new DateTime()));
System.out.println("评论数量" + list.size());
for (Map<String, Object> map : list) {
goodsMapper.addGoodsCommentNum(Integer.parseInt(map.get("num").toString()), map.get("goods_id").toString());
}

View File

@@ -43,11 +43,11 @@ public class CancelOrderTaskExecute implements EveryMinuteExecute {
Setting setting = settingService.get(SettingEnum.ORDER_SETTING.name());
OrderSetting orderSetting = JSONUtil.toBean(setting.getSettingValue(), OrderSetting.class);
if (orderSetting != null && orderSetting.getAutoCancel() != null) {
// 订单自动取消时间 = 当前时间 - 自动取消时间分钟数
//订单自动取消时间 = 当前时间 - 自动取消时间分钟数
DateTime cancelTime = DateUtil.offsetMinute(DateUtil.date(), -orderSetting.getAutoCancel());
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.UNPAID.name());
// 订单创建时间 <= 订单自动取消时间
//订单创建时间 <= 订单自动取消时间
queryWrapper.le(Order::getCreateTime, cancelTime);
List<Order> list = orderService.list(queryWrapper);
List<String> cancelSnList = list.stream().map(Order::getSn).collect(Collectors.toList());

View File

@@ -73,11 +73,11 @@ public class OrderEveryDayTaskExecute implements EveryDayExecute {
* @param orderSetting 订单设置
*/
private void completedOrder(OrderSetting orderSetting) {
// 订单自动收货时间 = 当前时间 - 自动收货时间天数
//订单自动收货时间 = 当前时间 - 自动收货时间天数
DateTime receiveTime = DateUtil.offsetDay(DateUtil.date(), -orderSetting.getAutoEvaluation());
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.DELIVERED.name());
// 订单发货时间 >= 订单自动收货时间
//订单发货时间 >= 订单自动收货时间
queryWrapper.ge(Order::getLogisticsTime, receiveTime);
List<Order> list = orderService.list(queryWrapper);
List<String> receiveSnList = list.stream().map(Order::getSn).collect(Collectors.toList());
@@ -98,9 +98,9 @@ public class OrderEveryDayTaskExecute implements EveryDayExecute {
* @param orderSetting 订单设置
*/
private void memberEvaluation(OrderSetting orderSetting) {
// 订单自动收货时间 = 当前时间 - 自动收货时间天数
//订单自动收货时间 = 当前时间 - 自动收货时间天数
DateTime receiveTime = DateUtil.offsetDay(DateUtil.date(), -orderSetting.getAutoReceive());
// 订单完成时间 <= 订单自动好评时间
//订单完成时间 <= 订单自动好评时间
List<OrderItem> orderItems = orderItemService.waitEvaluate(receiveTime);
for (OrderItem orderItem : orderItems) {

View File

@@ -3,15 +3,22 @@ package cn.lili.timetask.handler.impl.promotion;
import cn.lili.modules.order.cart.entity.vo.FullDiscountVO;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
import cn.lili.modules.promotion.entity.dos.Seckill;
import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum;
import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum;
import cn.lili.modules.promotion.entity.vos.CouponVO;
import cn.lili.modules.promotion.entity.vos.PintuanVO;
import cn.lili.modules.promotion.service.*;
import cn.lili.modules.search.service.EsGoodsIndexService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.SeckillSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
@@ -28,8 +35,8 @@ import java.util.List;
* @author Chopper
* @date 2021/3/18 3:23 下午
*/
@Slf4j
@Component
public class PromotionEverydayExecute implements EveryDayExecute {
//Mongo
@@ -54,88 +61,155 @@ public class PromotionEverydayExecute implements EveryDayExecute {
@Autowired
private PromotionGoodsService promotionGoodsService;
//系统设置
@Autowired
private SettingService settingService;
//秒杀活动
@Autowired
private SeckillService seckillService;
/**
* 将已过期的促销活动置为结束
*/
@Override
public void execute() {
//mongo查询条件
Query query = new Query();
// 结束条件 活动关闭/活动结束
//结束条件 活动关闭/活动结束
query.addCriteria(Criteria.where("promotionStatus").ne(PromotionStatusEnum.END.name())
.orOperator(Criteria.where("promotionStatus").ne(PromotionStatusEnum.CLOSE.name())));
//结束条件 活动结束时间大于当前时间
query.addCriteria(Criteria.where("endTime").lt(new Date()));
List<String> promotionIds = new ArrayList<>();
//结束满减活动
endFullDiscount(query);
//关闭满减活动
List<FullDiscountVO> fullDiscountVOS = mongoTemplate.find(query, FullDiscountVO.class);
if (!fullDiscountVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
for (FullDiscountVO vo : fullDiscountVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
esGoodsIndexService.deleteEsGoodsPromotionByPromotionId(promotionGoods.getSkuId(), vo.getId());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
fullDiscountService.update(this.getUpdatePromotionWrapper(ids));
promotionIds.addAll(ids);
}
//关闭拼团活动
List<PintuanVO> pintuanVOS = mongoTemplate.find(query, PintuanVO.class);
if (!pintuanVOS.isEmpty()) {
//准备修改活动的id
List<String> ids = new ArrayList<>();
for (PintuanVO vo : pintuanVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
esGoodsIndexService.deleteEsGoodsPromotionByPromotionId(promotionGoods.getSkuId(), vo.getId());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
pintuanService.update(this.getUpdatePromotionWrapper(ids));
promotionIds.addAll(ids);
}
endPintuan(query);
//关闭优惠券活动
List<CouponVO> couponVOS = mongoTemplate.find(query, CouponVO.class);
if (!couponVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
for (CouponVO vo : couponVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
esGoodsIndexService.deleteEsGoodsPromotionByPromotionId(promotionGoods.getSkuId(), vo.getId());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
couponService.update(this.getUpdatePromotionWrapper(ids));
LambdaUpdateWrapper<MemberCoupon> memberCouponLambdaUpdateWrapper = new LambdaUpdateWrapper<MemberCoupon>().in(MemberCoupon::getCouponId, ids).set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.EXPIRE.name());
memberCouponService.update(memberCouponLambdaUpdateWrapper);
promotionIds.addAll(ids);
}
//结束优惠券
endCoupon(query);
promotionGoodsService.update(this.getUpdatePromotionGoodsWrapper(promotionIds));
//定时创建活动
addSeckill();
}
/**
* 结束优惠券活动
*
* @param query
*/
private void endCoupon(Query query) {
try {
//关闭优惠券活动
List<CouponVO> couponVOS = mongoTemplate.find(query, CouponVO.class);
if (!couponVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
// //关闭的优惠券活动
for (CouponVO vo : couponVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
esGoodsIndexService.deleteEsGoodsPromotionByPromotionId(promotionGoods.getSkuId(), vo.getId());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
couponService.update(this.getUpdatePromotionWrapper(ids));
LambdaUpdateWrapper<MemberCoupon> memberCouponLambdaUpdateWrapper = new LambdaUpdateWrapper<MemberCoupon>().in(MemberCoupon::getCouponId, ids).set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.EXPIRE.name());
memberCouponService.update(memberCouponLambdaUpdateWrapper);
//将活动商品对照表进行结束处理
promotionGoodsService.update(this.getUpdatePromotionGoodsWrapper(ids));
}
} catch (Exception e) {
log.error("优惠券活动关闭错误", e);
}
}
/**
* 结束拼团活动
*
* @param query
*/
private void endPintuan(Query query) {
try {
//关闭拼团活动
List<PintuanVO> pintuanVOS = mongoTemplate.find(query, PintuanVO.class);
if (!pintuanVOS.isEmpty()) {
//准备修改活动的id
List<String> ids = new ArrayList<>();
for (PintuanVO vo : pintuanVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
esGoodsIndexService.deleteEsGoodsPromotionByPromotionId(promotionGoods.getSkuId(), vo.getId());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
pintuanService.update(this.getUpdatePromotionWrapper(ids));
//将活动商品对照表进行结束处理
promotionGoodsService.update(this.getUpdatePromotionGoodsWrapper(ids));
}
} catch (Exception e) {
log.error("拼团活动关闭错误", e);
}
}
/**
* 结束满减活动
*
* @param query
*/
private void endFullDiscount(Query query) {
try {
//关闭满减活动
List<FullDiscountVO> fullDiscountVOS = mongoTemplate.find(query, FullDiscountVO.class);
if (!fullDiscountVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
//循环活动 关闭活动
for (FullDiscountVO vo : fullDiscountVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
esGoodsIndexService.deleteEsGoodsPromotionByPromotionId(promotionGoods.getSkuId(), vo.getId());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
fullDiscountService.update(this.getUpdatePromotionWrapper(ids));
}
} catch (Exception e) {
log.error("满减活动关闭错误", e);
}
}
/**
* 添加秒杀活动
* 从系统设置中获取秒杀活动的配置
* 添加30天后的秒杀活动
*/
private void addSeckill() {
Setting setting = settingService.get(SettingEnum.SECKILL_SETTING.name());
SeckillSetting seckillSetting = new Gson().fromJson(setting.getSettingValue(), SeckillSetting.class);
Seckill seckill = new Seckill(30, seckillSetting.getHours(), seckillSetting.getSeckillRule());
seckillService.saveSeckill(seckill);
}
/**
* 获取促销修改查询条件 修改活动状态
* @param ids
* @return
*
* @param ids 促销活动ID
* @return 促销活动商品查询Wrapper
*/
private UpdateWrapper getUpdatePromotionWrapper(List<String> ids) {
UpdateWrapper updateWrapper = new UpdateWrapper<>();
@@ -143,10 +217,12 @@ public class PromotionEverydayExecute implements EveryDayExecute {
updateWrapper.set("promotion_status", PromotionStatusEnum.END.name());
return updateWrapper;
}
/**
* 获取商品的促销修改查询条件 修改商品状态
* @param ids
* @return
*
* @param ids 促销活动ID
* @return 促销活动商品修改Wrapper
*/
private UpdateWrapper getUpdatePromotionGoodsWrapper(List<String> ids) {
UpdateWrapper updateWrapper = new UpdateWrapper<>();

View File

@@ -186,7 +186,6 @@ class PageViewStatistics {
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
this.date = calendar.getTime();
System.out.println(DateUtil.toString(date,DateUtil.STANDARD_FORMAT));
}
}

View File

@@ -1,6 +1,7 @@
package cn.lili.common.delayqueue;
package cn.lili.trigger;
import cn.lili.common.utils.RedisUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.common.cache.Cache;
import cn.lili.common.utils.ThreadPoolUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -8,7 +9,6 @@ import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.util.Calendar;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -19,48 +19,35 @@ import java.util.concurrent.TimeUnit;
* @since 2020/11/7
**/
@Slf4j
public abstract class AbstractDelayQueueMachineFactory {
public abstract class AbstractDelayQueueListen {
@Autowired
private RedisUtil redisUtil;
private Cache cache;
/**
* 插入任务id
*
* @param jobId 任务id(队列内唯一)
* @param time 延时时间(单位 :)
* @return 是否插入成功
*/
public boolean addJobId(String jobId, Integer time) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, time);
long delaySeconds = instance.getTimeInMillis() / 1000;
boolean result = redisUtil.zadd(setDelayQueueName(), delaySeconds, jobId);
log.info("redis add delay, key {}, delay time {}", setDelayQueueName(), time);
return result;
}
/**
* 延时队列机器开始运作
*/
private void startDelayQueueMachine() {
log.info(String.format("延时队列机器{%s}开始运作", setDelayQueueName()));
log.info("延时队列机器{}开始运作", setDelayQueueName());
// 发生异常捕获并且继续不能让战斗停下来
//监听redis队列
while (true) {
try {
// 获取当前时间的时间戳
//获取当前时间的时间戳
long now = System.currentTimeMillis() / 1000;
// 获取当前时间前的任务列表
Set<DefaultTypedTuple> tuples = redisUtil.zrangeByScoreWithScores(setDelayQueueName(), 0, now);
// 如果不为空则遍历判断其是否满足取消要求
if (!CollectionUtils.isEmpty(tuples)) {
for (DefaultTypedTuple tuple : tuples) {
//获取当前时间前需要执行的任务列表
Set<DefaultTypedTuple> tuples = cache.zRangeByScore(setDelayQueueName(), 0, now);
//如果任务不为空
if (!CollectionUtils.isEmpty(tuples)) {
log.info("执行任务:{}", JSONUtil.toJsonStr(tuples));
for (DefaultTypedTuple tuple : tuples) {
String jobId = (String) tuple.getValue();
Long num = redisUtil.zremove(setDelayQueueName(), jobId);
// 如果移除成功, 则执行
//移除缓存如果移除成功则表示当前线程处理了延时任务则执行延时任务
Long num = cache.zRemove(setDelayQueueName(), jobId);
//如果移除成功, 则执行
if (num > 0) {
ThreadPoolUtil.execute(() -> invoke(jobId));
}
@@ -68,9 +55,9 @@ public abstract class AbstractDelayQueueMachineFactory {
}
} catch (Exception e) {
log.error(String.format("处理延时任务发生异常,异常原因为{%s}", e.getMessage()), e);
log.error("处理延时任务发生异常,异常原因为{}", e.getMessage(), e);
} finally {
// 间隔一秒钟搞一次
//间隔一秒钟搞一次
try {
TimeUnit.SECONDS.sleep(5L);
} catch (InterruptedException e) {
@@ -96,6 +83,9 @@ public abstract class AbstractDelayQueueMachineFactory {
public abstract String setDelayQueueName();
/**
* 监听队列
*/
@PostConstruct
public void init() {
new Thread(this::startDelayQueueMachine).start();

View File

@@ -2,9 +2,8 @@ package cn.lili.trigger;
import cn.hutool.json.JSONUtil;
import cn.lili.common.cache.Cache;
import cn.lili.common.trigger.interfaces.TimeTriggerExecutor;
import cn.lili.common.trigger.model.TimeTriggerMsg;
import cn.lili.common.trigger.util.TimeTriggerUtil;
import cn.lili.common.trigger.util.DelayQueueTools;
import cn.lili.common.utils.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
@@ -28,7 +27,7 @@ public class TimeTriggerConsumer implements RocketMQListener<TimeTriggerMsg> {
@Override
public void onMessage(TimeTriggerMsg timeTriggerMsg) {
try {
String key = TimeTriggerUtil.generateKey(timeTriggerMsg.getTriggerExecutor(), timeTriggerMsg.getTriggerTime(), timeTriggerMsg.getUniqueKey());
String key = DelayQueueTools.generateKey(timeTriggerMsg.getTriggerExecutor(), timeTriggerMsg.getTriggerTime(), timeTriggerMsg.getUniqueKey());
if (cache.get(key) == null) {
log.info("执行器执行被取消:{} | 任务标识:{}", timeTriggerMsg.getTriggerExecutor(), timeTriggerMsg.getUniqueKey());

View File

@@ -1,15 +1,16 @@
package cn.lili.common.trigger.interfaces;
package cn.lili.trigger;
/**
* 延时任务执行器接口
* @author Chopper
*
* @author Chopper
*/
public interface TimeTriggerExecutor {
/**
* 执行任务
*
* @param object 任务参数
*/
void execute(Object object);

View File

@@ -0,0 +1,36 @@
package cn.lili.trigger.executor;
import cn.hutool.json.JSONUtil;
import cn.lili.common.delayqueue.BroadcastMessage;
import cn.lili.common.trigger.model.TimeExecuteConstant;
import cn.lili.modules.broadcast.service.StudioService;
import cn.lili.trigger.TimeTriggerExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 直播间事件触发
*
* @author Bulbasaur
* @date: 2021/6/1 5:02 下午
*/
@Slf4j
@Component(TimeExecuteConstant.BROADCAST_EXECUTOR)
public class BroadcastTimeTriggerExecutor implements TimeTriggerExecutor {
@Autowired
private StudioService studioService;
@Override
public void execute(Object object) {
//直播间订单消息
BroadcastMessage broadcastMessage = JSONUtil.toBean(JSONUtil.parseObj(object), BroadcastMessage.class);
if (broadcastMessage != null && broadcastMessage.getStudioId() != null) {
log.info("直播间消费:{}", broadcastMessage);
//修改直播间状态
studioService.updateStudioStatus(broadcastMessage);
}
}
}

View File

@@ -1,13 +1,12 @@
package cn.lili.trigger.executor;
import cn.hutool.json.JSONUtil;
import cn.lili.common.delayqueue.PintuanOrderMessage;
import cn.lili.common.delayqueue.PromotionMessage;
import cn.lili.common.trigger.interfaces.TimeTrigger;
import cn.lili.common.trigger.interfaces.TimeTriggerExecutor;
import cn.lili.trigger.TimeTriggerExecutor;
import cn.lili.common.trigger.message.PintuanOrderMessage;
import cn.lili.common.trigger.message.PromotionMessage;
import cn.lili.common.trigger.model.TimeExecuteConstant;
import cn.lili.common.trigger.model.TimeTriggerMsg;
import cn.lili.common.utils.DateUtil;
import cn.lili.config.rocketmq.RocketmqCustomProperties;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum;
@@ -43,23 +42,25 @@ public class PromotionTimeTriggerExecutor implements TimeTriggerExecutor {
@Override
public void execute(Object object) {
PromotionMessage promotionMessage = JSONUtil.toBean(JSONUtil.parseObj(object), PromotionMessage.class);
// 促销延时信息
//促销延时信息
if (promotionMessage != null && promotionMessage.getPromotionId() != null) {
log.info("促销活动信息消费:{}", promotionMessage);
// 如果为促销活动开始,则需要发布促销活动结束的定时任务
//如果为促销活动开始,则需要发布促销活动结束的定时任务
if (PromotionStatusEnum.START.name().equals(promotionMessage.getPromotionStatus())) {
if (!promotionService.updatePromotionStatus(promotionMessage)) {
log.error("开始促销活动失败: {}", promotionMessage);
return;
}
// 促销活动开始后,设置促销活动结束的定时任务
//促销活动开始后,设置促销活动结束的定时任务
promotionMessage.setPromotionStatus(PromotionStatusEnum.END.name());
String uniqueKey = "{TIME_TRIGGER_" + promotionMessage.getPromotionType() + "}_" + promotionMessage.getPromotionId();
// 结束时间(延时一分钟)
//结束时间(延时一分钟)
long closeTime = promotionMessage.getEndTime().getTime() + 60000;
TimeTriggerMsg timeTriggerMsg = new TimeTriggerMsg(TimeExecuteConstant.PROMOTION_EXECUTOR, closeTime, promotionMessage, uniqueKey, rocketmqCustomProperties.getPromotionTopic());
timeTrigger.addDelay(timeTriggerMsg, DateUtil.getDelayTime(promotionMessage.getEndTime().getTime()));
//添加延时任务
timeTrigger.addDelay(timeTriggerMsg);
} else {
//不是开始,则修改活动状态
promotionService.updatePromotionStatus(promotionMessage);
}
return;
@@ -68,7 +69,7 @@ public class PromotionTimeTriggerExecutor implements TimeTriggerExecutor {
PintuanOrderMessage pintuanOrderMessage = JSONUtil.toBean(JSONUtil.parseObj(object), PintuanOrderMessage.class);
if (pintuanOrderMessage != null && pintuanOrderMessage.getPintuanId() != null) {
log.info("拼团订单信息消费:{}", pintuanOrderMessage);
// 拼团订单自动处理
//拼团订单自动处理
orderService.agglomeratePintuanOrder(pintuanOrderMessage.getPintuanId(), pintuanOrderMessage.getOrderSn());
}
}

View File

@@ -1,34 +1,34 @@
package cn.lili.common.trigger.delay;
package cn.lili.trigger.listen;
import cn.hutool.json.JSONUtil;
import cn.lili.common.delayqueue.AbstractDelayQueueMachineFactory;
import cn.lili.common.trigger.enums.DelayQueueEnums;
import cn.lili.common.trigger.interfaces.TimeTrigger;
import cn.lili.common.trigger.model.TimeTriggerMsg;
import cn.lili.trigger.AbstractDelayQueueListen;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 促销延迟队列
* PromotionTimeTriggerListen
*
* @author paulG
* @version v4.1
* @date 2020/11/17 7:19 下午
* @description
* @since 1
* @author Chopper
* @version v1.0
* 2021-06-11 10:47
*/
@Component
public class PromotionDelayQueue extends AbstractDelayQueueMachineFactory {
public class PromotionDelayQueueListen extends AbstractDelayQueueListen {
@Autowired
private TimeTrigger timeTrigger;
@Override
public void invoke(String jobId) {
timeTrigger.add(JSONUtil.toBean(jobId, TimeTriggerMsg.class));
timeTrigger.execute(JSONUtil.toBean(jobId, TimeTriggerMsg.class));
}
@Override
public String setDelayQueueName() {
return "promotion_delay";
return DelayQueueEnums.PROMOTION.name();
}
}

View File

@@ -124,7 +124,7 @@ spring:
props:
#是否打印逻辑SQL语句和实际SQL语句建议调试时打印在生产环境关闭
sql:
show: true
show: false
# 忽略鉴权url
ignored:

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--应用名称-->
<property name="APP_NAME" value="consumer"/>
<!--日志文件保存路径-->
<property name="LOG_FILE_PATH" value="lili-logs"/>
<contextName>${APP_NAME}</contextName>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--输出到elk的LOGSTASH-->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!-- 配置elk日志收集 配饰的是 LOGSTASH 的地址-->
<destination>192.168.0.116:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
</providers>
<!--自定义字段 区分项目-->
<customFields>{"appName":"${APP_NAME}"}</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="LOGSTASH"/>
</root>
</configuration>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>cn.lili</groupId>
<artifactId>lili-shop-parent</artifactId>
<version>1.0.1</version>
<version>4.2.0</version>
</parent>
<artifactId>framework</artifactId>
@@ -45,47 +45,16 @@
<de.codecentric>2.3.1</de.codecentric>
<userAgentUtils>1.21</userAgentUtils>
<interceptor-api>1.2</interceptor-api>
<poi-version>4.1.2</poi-version>
<poi-ooxml-version>4.1.2</poi-ooxml-version>
<logstash-logback-encoder>6.6</logstash-logback-encoder>
<zxing>3.4.1</zxing>
<slf4j-api>1.7.28</slf4j-api>
<xk-time>2.2.0</xk-time>
<commons-text>1.4</commons-text>
</properties>
<dependencies>
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>${interceptor-api}</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${de.codecentric}</version>
</dependency>
<!-- 开源多维码生成工具 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.28</version>
</dependency>
<!-- 开源多维码生成工具 -->
<dependency>
<groupId>com.github.xkzhangsan</groupId>
<artifactId>xk-time</artifactId>
<version>2.2.0</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-thymeleaf</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@@ -356,23 +325,11 @@
<artifactId>simple-http</artifactId>
<version>${simple-http-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.antlr/antlr4-runtime -->
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>${antlr4-runtime-version}</version>
</dependency>
<!-- http client -->
<!-- <dependency>-->
<!-- <groupId>org.apache.httpcomponents</groupId>-->
<!-- <artifactId>httpclient</artifactId>-->
<!-- <version>${httpclient-version}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.squareup.okhttp3</groupId>-->
<!-- <artifactId>okhttp</artifactId>-->
<!-- <version>${okhttp-version}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
@@ -385,6 +342,59 @@
<artifactId>UserAgentUtils</artifactId>
<version>${userAgentUtils}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi-version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi-ooxml-version}</version>
</dependency>
<!--集成logstash-->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>${logstash-logback-encoder}</version>
</dependency>
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>${interceptor-api}</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${de.codecentric}</version>
</dependency>
<!-- 开源多维码生成工具 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>${zxing}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>${zxing}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api}</version>
</dependency>
<!-- 开源多维码生成工具 -->
<dependency>
<groupId>com.github.xkzhangsan</groupId>
<artifactId>xk-time</artifactId>
<version>${xk-time}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${commons-text}</version>
</dependency>
</dependencies>

View File

@@ -29,7 +29,10 @@ public class MyMetaObjectHandler implements MetaObjectHandler {
this.setFieldValByName("deleteFlag", false, metaObject);
}
if (metaObject.hasGetter("id")) {
this.setFieldValByName("id", String.valueOf(SnowFlake.getId()), metaObject);
//如果已经配置id则不再写入
if (metaObject.getValue("id") == null) {
this.setFieldValByName("id", String.valueOf(SnowFlake.getId()), metaObject);
}
}
}

View File

@@ -9,13 +9,23 @@ import org.springframework.context.annotation.Configuration;
* @author Chopper
*/
@Configuration
@MapperScan({"cn.lili.modules.*.*.mapper","cn.lili.modules.*.mapper"})
@MapperScan({"cn.lili.modules.*.*.mapper", "cn.lili.modules.*.mapper"})
public class MybatisPlusConfig {
/**
* 分页插件,自动识别数据库类型
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
//阻断解析器,测试环境使用
// PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
//
// List<ISqlParser> sqlParserList = new ArrayList<>();
// //攻击 SQL 阻断解析器、加入解析链
// sqlParserList.add(new BlockAttackSqlParser());
// paginationInterceptor.setSqlParserList(sqlParserList);
// return paginationInterceptor;
}
}

View File

@@ -1,13 +1,12 @@
package cn.lili.common.aop.limiter;
import cn.lili.common.aop.limiter.annotation.LimitPoint;
import cn.lili.common.exception.ServiceException;
import com.google.common.collect.ImmutableList;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
@@ -17,10 +16,10 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.lang.reflect.Method;
/**
* 流量拦截
*
* @author Chopper
*/
@Aspect
@@ -41,46 +40,44 @@ public class LimitInterceptor {
this.limitScript = limitScript;
}
@Around("execution(public * *(..)) && @annotation(cn.lili.common.aop.limiter.annotation.LimitPoint)")
public Object interceptor(ProceedingJoinPoint pjp) {
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
LimitPoint limitPointAnnotation = method.getAnnotation(LimitPoint.class);
@Before("@annotation(limitPointAnnotation)")
public void interceptor(LimitPoint limitPointAnnotation) {
LimitType limitType = limitPointAnnotation.limitType();
String name = limitPointAnnotation.name();
String key;
int limitPeriod = limitPointAnnotation.period();
int limitCount = limitPointAnnotation.limit();
switch (limitType) {
case IP:
key = limitPointAnnotation.key() + getIpAddress();
break;
case CUSTOMER:
key = limitPointAnnotation.key();
break;
default:
key = StringUtils.upperCase(method.getName());
key = limitPointAnnotation.key() + getIpAddress();
}
ImmutableList<String> keys = ImmutableList.of(StringUtils.join(limitPointAnnotation.prefix(), key));
try {
Number count = redisTemplate.execute(limitScript, keys, limitCount, limitPeriod);
log.info("Access try count is {} for name={} and key = {}", count, name, key);
if (count != null && count.intValue() <= limitCount) {
return pjp.proceed();
} else {
throw new RuntimeException("访问过于频繁,请稍后再试");
}
} catch (Throwable e) {
if (e instanceof RuntimeException) {
throw new RuntimeException(e.getLocalizedMessage());
log.info("限制请求{}, 当前请求{},缓存key{}", limitCount, count.intValue(), key);
//如果缓存里没有值,或者他的值小于限制频率
if (count.intValue() >= limitCount) {
throw new ServiceException("访问过于频繁,请稍后再试");
}
}
//如果从redis中执行都值判定为空则这里跳过
catch (NullPointerException e) {
return;
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("服务器异常,请稍后再试");
}
}
//默认unknown常量值
private static final String UNKNOWN = "unknown";
//获取ip
public String getIpAddress() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ip = request.getHeader("x-forwarded-for");

View File

@@ -102,7 +102,7 @@ public class SystemLogAspect {
//请求参数
systemLogVO.setMapToParams(logParams);
//响应参数 此处数据太大了,所以先注释掉
// systemLogVO.setResponseBody(JSONUtil.toJsonStr(rvt));
// systemLogVO.setResponseBody(JSONUtil.toJsonStr(rvt));
//请求IP
systemLogVO.setIp(IpUtils.getIpAddress(request));
//IP地址

View File

@@ -232,4 +232,35 @@ public interface Cache<T> {
* @return
*/
Set<ZSetOperations.TypedTuple<Object>> reverseRangeWithScores(String sortedSetName, Integer start, Integer end);
/**
* 向Zset里添加成员
*
* @param key key值
* @param score 分数
* @param value 值
* @return 增加状态
*/
boolean zAdd(String key, long score, String value);
/**
* 获取 某key 下 某一分值区间的队列
*
* @param key 缓存key
* @param from 开始时间
* @param to 结束时间
* @return 数据
*/
Set<ZSetOperations.TypedTuple<Object>> zRangeByScore(String key, int from, long to);
/**
* 移除 Zset队列值
*
* @param key key值
* @param value 删除的集合
* @return 删除数量
*/
Long zRemove(String key, String... value);
}

View File

@@ -219,7 +219,7 @@ public enum CachePrefix {
STORE_ID_FULL_DISCOUNT,
/**
* 限时抢购活动缓存key前缀
* 秒杀活动活动缓存key前缀
*/
STORE_ID_SECKILL,

View File

@@ -1,6 +1,7 @@
package cn.lili.common.cache.impl;
import cn.lili.common.cache.Cache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
@@ -18,6 +19,7 @@ import java.util.function.Consumer;
*
* @author Chopepr
*/
@Slf4j
@Component
public class RedisCache implements Cache {
@@ -158,7 +160,7 @@ public class RedisCache implements Cache {
return null;
} catch (IOException e) {
e.printStackTrace();
log.error("scan错误",e);
throw new RuntimeException(e);
}
});
@@ -168,7 +170,7 @@ public class RedisCache implements Cache {
@Override
public Long cumulative(Object key, Object value) {
HyperLogLogOperations<Object, Object> operations = redisTemplate.opsForHyperLogLog();
// add 方法对应 PFADD 命令
//add 方法对应 PFADD 命令
return operations.add(key, value);
}
@@ -177,7 +179,7 @@ public class RedisCache implements Cache {
public Long counter(Object key) {
HyperLogLogOperations<Object, Object> operations = redisTemplate.opsForHyperLogLog();
// add 方法对应 PFADD 命令
//add 方法对应 PFADD 命令
return operations.size(key);
}
@@ -196,7 +198,7 @@ public class RedisCache implements Cache {
@Override
public Long mergeCounter(Object... key) {
HyperLogLogOperations<Object, Object> operations = redisTemplate.opsForHyperLogLog();
// 计数器合并累加
//计数器合并累加
return operations.union(key[0], key);
}
@@ -221,7 +223,7 @@ public class RedisCache implements Cache {
*/
@Override
public void incrementScore(String sortedSetName, String keyword) {
// x 的含义请见本方法的注释
//x 的含义请见本方法的注释
double x = 1.0;
this.redisTemplate.opsForZSet().incrementScore(sortedSetName, keyword, x);
}
@@ -240,4 +242,47 @@ public class RedisCache implements Cache {
public Set<ZSetOperations.TypedTuple<Object>> reverseRangeWithScores(String sortedSetName, Integer start, Integer end) {
return this.redisTemplate.opsForZSet().reverseRangeWithScores(sortedSetName, start, end);
}
/**
* 向Zset里添加成员
*
* @param key key值
* @param score 分数,通常用于排序
* @param value 值
* @return 增加状态
*/
@Override
public boolean zAdd(String key, long score, String value) {
Boolean result = redisTemplate.opsForZSet().add(key, value, score);
return result;
}
/**
* 获取 某key 下 某一分值区间的队列
*
* @param key 缓存key
* @param from 开始时间
* @param to 结束时间
* @return 数据
*/
@Override
public Set<ZSetOperations.TypedTuple<Object>> zRangeByScore(String key, int from, long to) {
Set<ZSetOperations.TypedTuple<Object>> set = redisTemplate.opsForZSet().rangeByScoreWithScores(key, from, to);
return set;
}
/**
* 移除 Zset队列值
*
* @param key key值
* @param value 删除的集合
* @return 删除数量
*/
@Override
public Long zRemove(String key, String... value) {
return redisTemplate.opsForZSet().remove(key, value);
}
}

View File

@@ -1,22 +0,0 @@
package cn.lili.common.delayqueue;
/**
* 延时任务工具类
*
* @author paulG
* @since 2021/5/7
**/
public class DelayQueueTools {
/**
* 组装延时任务唯一键
*
* @param type 延时任务类型
* @param id id
* @return 唯一键
*/
public static String wrapperUniqueKey(DelayQueueType type, String id) {
return "{TIME_TRIGGER_" + type.name() + "}_" + id;
}
}

View File

@@ -1,30 +0,0 @@
package cn.lili.common.delayqueue;
/**
* 延时任务类型
*
* @author paulG
* @since 2021/5/7
**/
public enum DelayQueueType {
/**
* 促销活动
*/
PROMOTION("促销活动"),
/**
* 拼团订单
*/
PINTUAN_ORDER("拼团订单");
private final String description;
DelayQueueType(String des) {
this.description = des;
}
public String description() {
return this.description;
}
}

View File

@@ -44,7 +44,7 @@ public abstract class BaseElasticsearchService {
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// 默认缓冲限制为100MB此处修改为30MB。
//默认缓冲限制为100MB此处修改为30MB。
builder.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024));
COMMON_OPTIONS = builder.build();
}
@@ -88,7 +88,7 @@ public abstract class BaseElasticsearchService {
protected void createIndexRequest(String index) {
try {
CreateIndexRequest request = new CreateIndexRequest(index);
// Settings for this index
//Settings for this index
request.settings(Settings.builder().put("index.number_of_shards", elasticsearchProperties.getIndex().getNumberOfShards()).put("index.number_of_replicas", elasticsearchProperties.getIndex().getNumberOfReplicas()));
//创建索引
@@ -98,7 +98,7 @@ public abstract class BaseElasticsearchService {
log.info(" Indicates whether the requisite number of shard copies were started for each shard in the index before timing out :{}", createIndexResponse.isShardsAcknowledged());
return;
} catch (Exception e) {
e.printStackTrace();
log.error("创建索引错误",e);
throw new ElasticsearchException("创建索引 {" + index + "} 失败:" + e.getMessage());
}
}
@@ -308,13 +308,13 @@ public abstract class BaseElasticsearchService {
PutMappingRequest request = new PutMappingRequest(index)
.source(source, XContentType.JSON);
// AcknowledgedResponse putMappingResponse = client.indices().putMapping(request,
// RequestOptions.DEFAULT);
// AcknowledgedResponse putMappingResponse = client.indices().putMapping(request,
// RequestOptions.DEFAULT);
//
// boolean acknowledged = putMappingResponse.isAcknowledged();
// if (acknowledged) {
// log.error("Succeed to put mapping");
// }
// boolean acknowledged = putMappingResponse.isAcknowledged();
// if (acknowledged) {
// log.error("Succeed to put mapping");
// }
CountDownLatch latch = new CountDownLatch(1);
AtomicReference response = new AtomicReference<AcknowledgedResponse>();
client.indices().putMappingAsync(
@@ -420,7 +420,7 @@ public abstract class BaseElasticsearchService {
try {
searchResponse = client.search(searchRequest, COMMON_OPTIONS);
} catch (IOException e) {
e.printStackTrace();
log.error("es 搜索错误",e);
}
return searchResponse;
}

View File

@@ -17,7 +17,7 @@ public enum ResultCode {
/**
* 失败返回码
*/
ERROR(400, "失败"),
ERROR(400, "服务器繁忙,请稍后重试"),
/**
* 失败返回码
@@ -34,6 +34,7 @@ public enum ResultCode {
*/
WECHAT_CONNECT_NOT_EXIST(1001, "微信联合登录未配置"),
VERIFICATION_EXIST(1002, "验证码服务异常"),
/**
* 分类
*/
@@ -50,134 +51,222 @@ public enum ResultCode {
/**
* 商品
*/
GOODS_ERROR(11001, "商品异常,请稍后重试"),
GOODS_NOT_EXIST(11001, "商品已下架"),
GOODS_NAME_ERROR(11002, "商品名称不正确名称应为2-50字符"),
GOODS_UNDER_ERROR(11003, "商品下架失败"),
GOODS_UPPER_ERROR(11004, "商品上架失败"),
GOODS_AUTH_ERROR(11005, "商品审核失败"),
POINT_GOODS_ERROR(11006, "积分商品业务异常,请稍后重试"),
GOODS_SKU_SN_ERROR(11007, "商品SKU编号不能为空"),
GOODS_SKU_PRICE_ERROR(11008, "商品SKU价格不能小于等于0"),
GOODS_SKU_COST_ERROR(11009, "商品SKU成本价不能小于等于0"),
GOODS_SKU_WEIGHT_ERROR(11010, "商品重量不能为负数"),
GOODS_SKU_QUANTITY_ERROR(11011, "商品库存数量不能为负数"),
GOODS_SKU_QUANTITY_NOT_ENOUGH(11011, "商品库存不足"),
/**
* 参数
*/
PARAMETER_SAVE_ERROR(12001, "参数添加失败"),
PARAMETER_UPDATE_ERROR(12002, "参数编辑失败"),
/**
* 规格
*/
SPEC_SAVE_ERROR(13001, "规格修改失败"),
SPEC_UPDATE_ERROR(13002, "规格修改失败"),
SPEC_DELETE_ERROR(13003, "此规格已绑定分类不允许删除"),
/**
* 品牌
*/
BRAND_SAVE_ERROR(14001, "品牌添加失败"),
BRAND_UPDATE_ERROR(14002, "品牌修改失败"),
BRAND_DISABLE_ERROR(14003, "品牌禁用失败"),
BRAND_DELETE_ERROR(14004, "品牌删除失败"),
/**
* 用户
*/
USER_EDIT_SUCCESS(20001, "用户修改成功"),
USER_NOT_EXIST(20002, "用户不存在"),
USER_NOT_LOGIN(20003, "用户未登录"),
USER_AUTH_EXPIRED(20004, "用户已退出,请重新登录"),
USER_AUTHORITY_ERROR(20005, "权限不足"),
USER_CONNECT_LOGIN_ERROR(20006, "未找到登录信息"),
USER_NAME_EXIST(20007, "该用户名已被注册"),
USER_PHONE_EXIST(20008, "该手机号已被注册"),
USER_PHONE_NOT_EXIST(20009, "手机号不存在"),
USER_PASSWORD_ERROR(20010, "密码不正确"),
USER_NOT_PHONE(20011, "非当前用户的手机号"),
USER_CONNECT_ERROR(20012, "联合第三方登录,授权信息错误"),
USER_RECEIPT_REPEAT_ERROR(20013, "会员发票信息重复"),
USER_RECEIPT_NOT_EXIST(20014, "会员发票信息不存在"),
USER_EDIT_ERROR(20015, "用户修改失败"),
USER_OLD_PASSWORD_ERROR(20016, "旧密码不正确"),
USER_COLLECTION_EXIST(2001, "无法重复收藏"),
USER_COLLECTION_EXIST(20017, "无法重复收藏"),
USER_GRADE_IS_DEFAULT(20018, "会员等级为默认会员等级"),
DELETE_EXIST(2001, "无法重复收藏"),
/**
* 权限
*/
PERMISSION_DEPARTMENT_ROLE_ERROR(21001, "角色已绑定部门,请逐个删除"),
PERMISSION_USER_ROLE_ERROR(21002, "角色已绑定管理员,请逐个删除"),
PERMISSION_MENU_ROLE_ERROR(21003, "菜单已绑定角色,请先删除或编辑角色"),
PERMISSION_DEPARTMENT_DELETE_ERROR(21004, "部门已经绑定管理员,请先删除或编辑管理员"),
PERMISSION_BEYOND_TEN(21005, "最多可以设置10个角色"),
/**
* 分销
*/
DISTRIBUTION_CLOSE(22000, "分销功能关闭"),
DISTRIBUTION_NOT_EXIST(22001, "分销员不存在"),
DISTRIBUTION_IS_APPLY(22002, "分销员已申请,无需重复提交"),
DISTRIBUTION_AUDIT_ERROR(22003, "审核分销员失败"),
DISTRIBUTION_RETREAT_ERROR(22004, "分销员清退失败"),
DISTRIBUTION_CASH_NOT_EXIST(22005, "分销员提现记录不存在"),
DISTRIBUTION_GOODS_DOUBLE(22006, "不能重复添加分销商品"),
/**
* 购物车
*/
CART_ERROR(30001, "读取结算页的购物车异常"),
CART_PINTUAN_NOT_EXIST_ERROR(30002, "拼团活动不存在错误"),
CART_PINTUAN_LIMIT_ERROR(30003, "购买数量超过拼团活动限制数量"),
SHIPPING_NOT_APPLY(30005, "购物商品不支持当前收货地址配送"),
/**
* 订单
*/
ORDER_ERROR(31001, "创建订单异常,请稍后重试"),
ORDER_NOT_EXIST(31002, "订单不存在"),
ORDER_DELIVERED_ERROR(31003, "订单状态错误,无法进行确认收货"),
ORDER_UPDATE_PRICE_ERROR(31004, "已支付的订单不能修改金额"),
ORDER_LOGISTICS_ERROR(31005, "物流错误"),
ORDER_DELIVER_ERROR(31006, "物流错误"),
ORDER_NOT_USER(31007, "非当前会员的订单"),
ORDER_TAKE_ERROR(31008, "当前订单无法核销"),
MEMBER_ADDRESS_NOT_EXIST(31009, "订单无收货地址,请先配置收货地址"),
ORDER_DELIVER_NUM_ERROR(31010, "没有待发货的订单"),
ORDER_NOT_SUPPORT_DISTRIBUTION(31011, "购物车中包含不支持配送的商品,请重新选择收货地址,或者重新选择商品"),
ORDER_CAN_NOT_CANCEL(31012, "当前订单状态不可取消"),
/**
* 支付
*/
PAY_UN_WANTED(32000, "当前订单不需要付款,返回订单列表等待系统订单出库即可"),
PAY_SUCCESS(32001, "支付成功"),
PAY_INCONSISTENT_ERROR(32002, "付款金额和应付金额不一致"),
PAY_DOUBLE_ERROR(32003, "订单已支付,不能再次进行支付"),
PAY_CASHIER_ERROR(32004, "收银台信息获取错误"),
PAY_ERROR(32005, "支付业务异常,请稍后重试"),
PAY_BAN(32006, "当前订单不需要付款,请返回订单列表重新操作"),
PAY_PARTIAL_ERROR(32007, "该订单已部分支付,请前往订单中心进行支付"),
PAY_NOT_SUPPORT(32008, "支付暂不支持"),
PAY_CLIENT_TYPE_ERROR(32009, "错误的客户端"),
PAY_POINT_ENOUGH(32010, "积分不足,不能兑换"),
PAY_NOT_EXIST_ORDER(32011, "支付订单不存在"),
CAN_NOT_RECHARGE_WALLET(32012, "不能使用余额进行充值"),
/**
* 售后
*/
AFTER_SALES_NOT_PAY_ERROR(33001, "当前订单未支付,不能申请售后"),
AFTER_SALES_CANCEL_ERROR(33002, "当前售后单无法取消"),
AFTER_SALES_BAN(33003, "订单状态不允许申请售后,请联系平台或商家"),
AFTER_SALES_DOUBLE_ERROR(33004, "售后已审核,无法重复操作"),
AFTER_SALES_LOGISTICS_ERROR(33005, "物流公司错误,请重新选择"),
AFTER_STATUS_ERROR(33006, "售后状态错误,请刷新页面"),
/**
* 投诉
*/
COMPLAINT_ORDER_ITEM_EMPTY_ERROR(33100, "订单不存在"),
COMPLAINT_SKU_EMPTY_ERROR(33101, "商品已下架,如需投诉请联系平台客服"),
COMPLAINT_ERROR(33102, "投诉异常,请稍后重试"),
/**
* 余额
*/
WALLET_NOT_EXIT_ERROR(34000, "钱包不存在,请联系管理员"),
WALLET_INSUFFICIENT(34001, "余额不足以支付订单,请充值!"),
WALLET_WITHDRAWAL_INSUFFICIENT(34002, "可提现金额不足!"),
WALLET_ERROR_INSUFFICIENT(34003, "零钱提现失败!"),
WALLET_REMARK_ERROR(34004, "请填写审核备注!"),
WALLET_APPLY_ERROR(34005, "提现申请异常!"),
/**
@@ -194,52 +283,79 @@ public enum ResultCode {
* 优惠券
*/
COUPON_EDIT_STATUS_SUCCESS(41001, "修改状态成功!"),
COUPON_CANCELLATION_SUCCESS(41002, "会员优惠券作废成功"),
COUPON_EXPIRED(41003, "优惠券已使用/已过期,不能使用"),
COUPON_EDIT_STATUS_ERROR(41004, "优惠券修改状态失败!"),
/**
* 拼团
*/
PINTUAN_MANUAL_OPEN_SUCCESS(42001, "手动开启拼团活动成功"),
PINTUAN_MANUAL_CLOSE_SUCCESS(42002, "手动关闭拼团活动成功"),
PINTUAN_ADD_SUCCESS(42003, "添加拼团活动成功"),
PINTUAN_EDIT_SUCCESS(42004, "修改拼团活动成功"),
PINTUAN_DELETE_SUCCESS(42005, "删除拼团活动成功"),
PINTUAN_MANUAL_OPEN_ERROR(42006, "手动开启拼团活动失败"),
PINTUAN_MANUAL_CLOSE_ERROR(42007, "手动关闭拼团活动失败"),
PINTUAN_ADD_ERROR(42008, "添加拼团活动失败"),
PINTUAN_EDIT_ERROR(42009, "修改拼团活动失败"),
PINTUAN_DELETE_ERROR(42010, "删除拼团活动失败"),
/**
* 满额活动
*/
FULL_DISCOUNT_EDIT_SUCCESS(43001, "修改满优惠活动成功"),
FULL_DISCOUNT_EDIT_DELETE(43002, "删除满优惠活动成功"),
/**
* 直播
*/
STODIO_GOODS_EXIST_ERROR(44001,"直播商品已存在"),
/**
* 店铺
*/
STORE_NOT_EXIST(50001, "此店铺不存在"),
STORE_NAME_EXIST_ERROR(50002, "店铺名称已存在!"),
STORE_APPLY_DOUBLE_ERROR(50003, "已有店铺,无需重复申请!"),
/**
* 结算单
*/
BILL_CHECK_ERROR(51001, "只有已出账结算单可以核对"),
BILL_COMPLETE_ERROR(51002, "只有已审核结算单可以支付"),
/**
* 文章
*/
ARTICLE_CATEGORY_NAME_EXIST(60001, "文章分类名称已存在"),
ARTICLE_CATEGORY_PARENT_NOT_EXIST(60002, "文章分类父分类不存在"),
ARTICLE_CATEGORY_BEYOND_TWO(60003, "最多为二级分类,操作失败"),
ARTICLE_CATEGORY_DELETE_ERROR(60004, "该文章分类下存在子分类,不能删除"),
ARTICLE_CATEGORY_HAS_ARTICLE(60005, "该文章分类下存在文章,不能删除"),
ARTICLE_CATEGORY_NO_DELETION(60007, "默认文章分类不能进行删除"),
ARTICLE_NO_DELETION(60008, "默认文章不能进行删除"),
@@ -247,8 +363,11 @@ public enum ResultCode {
* 页面
*/
PAGE_NOT_EXIST(61001, "页面不存在"),
PAGE_OPEN_DELETE_ERROR(61002, "当前页面为开启状态,无法删除"),
PAGE_DELETE_ERROR(61003, "当前页面为唯一页面,无法删除"),
PAGE_RELEASE_ERROR(61004, "页面已发布,无需重复提交"),
/**
@@ -265,39 +384,49 @@ public enum ResultCode {
* 站内信
*/
NOTICE_NOT_EXIST(80101, "当前消息模板不存在"),
NOTICE_ERROR(80102, "修改站内信异常,请稍后重试"),
/**
* OSS
*/
OSS_NOT_EXIST(80201, "OSS未配置"),
OSS_EXCEPTION(80202, "文件上传失败,请稍后重试"),
/**
* 验证码
*/
VERIFICATION_SEND_SUCCESS(80301, "短信验证码,发送成功"),
VERIFICATION_ERROR(80302, "验证失败"),
VERIFICATION_SMS_ERROR(80303, "短信验证码错误,请重新校验"),
VERIFICATION_SMS_EXPIRED_ERROR(80304, "验证码已失效,请重新校验"),
/**
* 配置错误
*/
ALIPAY_NOT_SETTING(80401, "支付宝支付未配置"),
ALIPAY_EXCEPTION(80402, "支付宝支付错误,请稍后重试"),
ALIPAY_PARAMS_EXCEPTION(80403, "支付宝参数异常"),
/**
* 微信相关异常
*/
WECHAT_CONNECT_NOT_SETTING(80500, "微信联合登陆信息未配置"),
WECHAT_PAYMENT_NOT_SETTING(80501, "微信支付信息未配置"),
WECHAT_QRCODE_ERROR(80502, "微信二维码生成异常"),
WECHAT_MP_MESSAGE_ERROR(80503, "微信小程序小消息订阅异常"),
APP_VERSION_EXIST(80600, "APP版本已存在")
;
APP_VERSION_EXIST(80600, "APP版本已存在");
private final Integer code;
private final String message;

View File

@@ -44,10 +44,21 @@ public class GlobalControllerExceptionHandler {
//如果是自定义异常,则获取异常,返回自定义错误消息
if (e instanceof ServiceException) {
ResultCode resultCode = ((ServiceException) e).getResultCode();
ServiceException serviceException = ((ServiceException) e);
ResultCode resultCode = serviceException.getResultCode();
Integer code = null;
String message = null;
if (resultCode != null) {
return ResultUtil.error(resultCode.code(), resultCode.message());
code = resultCode.code();
message = resultCode.message();
}
//如果有扩展消息,则输出异常中,跟随补充异常
if (!serviceException.getMsg().equals(ServiceException.DEFAULT_MESSAGE)) {
message += ":" + serviceException.getMsg();
}
return ResultUtil.error(code, message);
}
//默认错误消息
@@ -67,24 +78,24 @@ public class GlobalControllerExceptionHandler {
return ResultUtil.error(ResultCode.ERROR);
}
// /**
// * 通用的接口映射异常处理方
// */
// @Override
// protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
// if (ex instanceof MethodArgumentNotValidException) {
// MethodArgumentNotValidException exception = (MethodArgumentNotValidException) ex;
// return new ResponseEntity<>(new ResultUtil<>().setErrorMsg(exception.getBindingResult().getAllErrors().get(0).getDefaultMessage()), status);
// }
// if (ex instanceof MethodArgumentTypeMismatchException) {
// MethodArgumentTypeMismatchException exception = (MethodArgumentTypeMismatchException) ex;
// logger.error("参数转换失败,方法:" + exception.getParameter().getMethod().getName() + ",参数:" + exception.getName()
// + ",信息:" + exception.getLocalizedMessage());
// return new ResponseEntity<>(new ResultUtil<>().setErrorMsg("参数转换失败"), status);
// }
// ex.printStackTrace();
// return new ResponseEntity<>(new ResultUtil<>().setErrorMsg("未知异常,请联系管理员"), status);
// }
// /**
// * 通用的接口映射异常处理方
// */
// @Override
// protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
// if (ex instanceof MethodArgumentNotValidException) {
// MethodArgumentNotValidException exception = (MethodArgumentNotValidException) ex;
// return new ResponseEntity<>(new ResultUtil<>().setErrorMsg(exception.getBindingResult().getAllErrors().get(0).getDefaultMessage()), status);
// }
// if (ex instanceof MethodArgumentTypeMismatchException) {
// MethodArgumentTypeMismatchException exception = (MethodArgumentTypeMismatchException) ex;
// logger.error("参数转换失败,方法:" + exception.getParameter().getMethod().getName() + ",参数:" + exception.getName()
// + ",信息:" + exception.getLocalizedMessage());
// return new ResponseEntity<>(new ResultUtil<>().setErrorMsg("参数转换失败"), status);
// }
// ex.printStackTrace();
// return new ResponseEntity<>(new ResultUtil<>().setErrorMsg("未知异常,请联系管理员"), status);
// }
/**
* bean校验未通过异常

View File

@@ -4,13 +4,19 @@ import cn.lili.common.enums.ResultCode;
import lombok.Data;
/**
* 全局业务异常类
*
* @author Chopper
*/
@Data
public class ServiceException extends RuntimeException {
private String msg;
public static String DEFAULT_MESSAGE = "网络错误,请稍后重试!";
//异常消息
private String msg = DEFAULT_MESSAGE;
//错误码
private ResultCode resultCode;
public ServiceException(String msg) {
@@ -19,8 +25,7 @@ public class ServiceException extends RuntimeException {
}
public ServiceException() {
super("网络错误,请稍后重试!");
this.msg = "网络错误,请稍后重试!";
super();
}
public ServiceException(ResultCode resultCode) {

View File

@@ -0,0 +1,39 @@
package cn.lili.common.security.filter;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 防止XSS攻击过滤器
*
* @author Chopper
* @version v1.0
* 2021-06-04 10:37
*/
@WebFilter
@Component
public class XssFilter implements Filter {
FilterConfig filterConfig = null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//对请求进行拦截,防xss处理
chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
}
@Override
public void destroy() {
this.filterConfig = null;
}
}

View File

@@ -0,0 +1,136 @@
package cn.lili.common.security.filter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.regex.Pattern;
/**
* 防止Xss
*
* @author Chopper
* @version v1.0
* 2021-06-04 10:39
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
/**
* 对数组参数进行特殊字符过滤
*/
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values == null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = cleanXSS(values[i]);
}
return encodedValues;
}
/**
* 对参数中特殊字符进行过滤
*/
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (value == null) {
return null;
}
return cleanXSS(value);
}
/**
* 获取attribute,特殊字符过滤
*/
@Override
public Object getAttribute(String name) {
Object value = super.getAttribute(name);
if (value != null && value instanceof String) {
cleanXSS((String) value);
}
return value;
}
/**
* 对请求头部进行特殊字符过滤
*/
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
if (value == null) {
return null;
}
return cleanXSS(value);
}
/**
* 转义字符,使用该方法存在一定的弊端
*
* @param value
* @return
*/
private String cleanXSS2(String value) {
//移除特殊标签
value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
value = value.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;");
value = value.replaceAll("'", "&#39;");
value = value.replaceAll("eval\\((.*)\\)", "");
value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
value = value.replaceAll("script", "");
return value;
}
private String cleanXSS(String value) {
if (value != null) {
//推荐使用ESAPI库来避免脚本攻击,value = ESAPI.encoder().canonicalize(value);
// //避免空字符串
// value = value.replaceAll(" ", "");
//避免script 标签
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
//避免src形式的表达式
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
//删除单个的 </script> 标签
scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
//删除单个的<script ...> 标签
scriptPattern = Pattern.compile("<script(.*?)>",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
//避免 eval(...) 形式表达式
scriptPattern = Pattern.compile("eval\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
//避免 e­xpression(...) 表达式
scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
//避免 javascript: 表达式
scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
//避免 vbscript:表达式
scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
//避免 onload= 表达式
scriptPattern = Pattern.compile("onload(.*?)=",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
}
return value;
}
}

View File

@@ -10,6 +10,8 @@ import cn.lili.common.sms.AliSmsUtil;
import cn.lili.common.sms.SmsUtil;
import cn.lili.common.utils.CommonUtil;
import cn.lili.common.verification.enums.VerificationEnums;
import cn.lili.config.properties.SmsTemplateSetting;
import cn.lili.config.properties.SystemSetting;
import cn.lili.modules.connect.util.Base64Utils;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.service.MemberService;
@@ -51,6 +53,12 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
@Autowired
private MemberService memberService;
@Autowired
private SmsTemplateSetting smsTemplateSetting;
@Autowired
private SystemSetting systemSetting;
@Override
public void sendSmsCode(String mobile, VerificationEnums verificationEnums, String uuid) {
//获取短信配置
@@ -65,7 +73,7 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
//准备发送短信参数
Map<String, String> params = new HashMap<>();
// 验证码内容
//验证码内容
params.put("code", code);
//模版 默认为登录验证
@@ -75,17 +83,17 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
switch (verificationEnums) {
//登录
case LOGIN: {
templateCode = "SMS_205755300";
templateCode = smsTemplateSetting.getLOGIN();
break;
}
//注册
case REGISTER: {
templateCode = "SMS_205755298";
templateCode = smsTemplateSetting.getREGISTER();
break;
}
//找回密码
case FIND_USER: {
templateCode = "SMS_205755301";
templateCode = smsTemplateSetting.getFIND_USER();
break;
}
//修改密码
@@ -96,18 +104,30 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
}
//更新为用户最新手机号
mobile = member.getMobile();
templateCode = "SMS_205755297";
templateCode = smsTemplateSetting.getUPDATE_PASSWORD();
break;
}
//设置支付密码
case WALLET_PASSWORD: {
Member member = memberService.getById(UserContext.getCurrentUser().getId());
//更新为用户最新手机号
mobile = member.getMobile();
templateCode = smsTemplateSetting.getWALLET_PASSWORD();
break;
}
//如果不是有效的验证码手段,则此处不进行短信操作
default:
return;
}
//如果是测试模式 默认验证码 6个1
if (systemSetting.getIsTestModel()) {
code = "111111";
} else {
//发送短信
this.sendSmsCode(smsSetting.getSignName(), mobile, params, templateCode);
}
//缓存中写入要验证的信息
cache.put(cacheKey(verificationEnums, mobile, uuid), code, 300L);
//发送短信
this.sendSmsCode(smsSetting.getSignName(), mobile, params, templateCode);
}
@Override
@@ -135,7 +155,7 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
try {
SendSmsResponse response = client.sendSms(sendSmsRequest);
} catch (Exception e) {
e.printStackTrace();
log.error("发送短信错误",e);
}
}
@@ -162,7 +182,7 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
signNameList.add(sign.subList((i * 100), endPoint));
}
// //发送短信
// //发送短信
for (int i = 0; i < mobileList.size(); i++) {
SendBatchSmsRequest sendBatchSmsRequest = new SendBatchSmsRequest()
.setPhoneNumberJson(JSONUtil.toJsonStr(mobileList.get(i)))
@@ -171,7 +191,7 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
try {
client.sendBatchSms(sendBatchSmsRequest);
} catch (Exception e) {
e.printStackTrace();
log.error("批量发送短信错误",e);
}
}
@@ -182,8 +202,6 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
public void addSmsSign(SmsSign smsSign) throws Exception {
//设置参数添加短信签名
com.aliyun.dysmsapi20170525.Client client = this.createClient();
System.out.println(smsSign.getBusinessLicense().substring(smsSign.getBusinessLicense().lastIndexOf(".") + 1));
System.out.println(smsSign.getLicense().substring(smsSign.getLicense().lastIndexOf(".")));
//营业执照
AddSmsSignRequest.AddSmsSignRequestSignFileList signFileList0 = new AddSmsSignRequest.AddSmsSignRequestSignFileList()
.setFileContents(Base64Utils.encode(smsSign.getBusinessLicense()))
@@ -338,15 +356,15 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
SmsSetting smsSetting = new Gson().fromJson(setting.getSettingValue(), SmsSetting.class);
Config config = new Config();
// 您的AccessKey ID
//您的AccessKey ID
config.accessKeyId = smsSetting.getAccessKeyId();
// 您的AccessKey Secret
//您的AccessKey Secret
config.accessKeySecret = smsSetting.getAccessSecret();
// 访问的域名
//访问的域名
config.endpoint = "dysmsapi.aliyuncs.com";
return new com.aliyun.dysmsapi20170525.Client(config);
} catch (Exception e) {
e.printStackTrace();
log.error("短信初始化错误",e);
}
return null;
}

View File

@@ -121,15 +121,15 @@ public class TokenUtil {
* @return
*/
private String createToken(String username, Object claim, Long expirationTime) {
// JWT 生成
//JWT 生成
return Jwts.builder()
// jwt 私有声明
//jwt 私有声明
.claim(SecurityEnum.USER_CONTEXT.getValue(), new Gson().toJson(claim))
// JWT的主体
//JWT的主体
.setSubject(username)
// 失效时间 当前时间+过期分钟
//失效时间 当前时间+过期分钟
.setExpiration(new Date(System.currentTimeMillis() + expirationTime * 60 * 1000))
// 签名算法和密钥
//签名算法和密钥
.signWith(SecretKeyUtil.generalKey())
.compact();
}

View File

@@ -43,7 +43,7 @@ public class ManagerTokenGenerate extends AbstractTokenGenerate {
@Override
public Token createToken(String username, Boolean longTerm) {
// 生成token
//生成token
AdminUser adminUser = adminUserService.findByUsername(username);
AuthUser user = new AuthUser(adminUser.getUsername(), adminUser.getId(), UserEnums.MANAGER, adminUser.getNickName(), adminUser.getIsSuper());
@@ -84,7 +84,7 @@ public class ManagerTokenGenerate extends AbstractTokenGenerate {
//for循环路径集合
for (String path : paths) {
//如果是超级权限 则计入超级权限
if (menu.getIsSupper()) {
if (menu.getIsSupper() != null && menu.getIsSupper()) {
//如果已有超级权限,则这里就不做权限的累加
if (!superPermissions.contains(path)) {
superPermissions.add(path);

View File

@@ -54,7 +54,7 @@ public class MemberTokenGenerate extends AbstractTokenGenerate {
memberService.updateById(member);
AuthUser authUser = new AuthUser(member.getUsername(), member.getId(),member.getNickName(), UserEnums.MEMBER);
// 登陆成功生成token
//登陆成功生成token
return tokenUtil.createToken(username, authUser, longTerm, UserEnums.MEMBER);
}

View File

@@ -33,7 +33,7 @@ public class StoreTokenGenerate extends AbstractTokenGenerate {
@Override
public Token createToken(String username, Boolean longTerm) {
// 生成token
//生成token
Member member = memberService.findByUsername(username);
if (!member.getHaveStore()) {
throw new ServiceException("该会员未开通店铺");

View File

@@ -0,0 +1,44 @@
package cn.lili.common.trigger.delay;
import cn.lili.common.cache.Cache;
import cn.lili.common.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 延时队列工厂
*
* @author paulG
* @since 2020/11/7
**/
@Slf4j
public abstract class AbstractDelayQueueMachineFactory {
@Autowired
private Cache cache;
/**
* 插入任务id
*
* @param jobId 任务id(队列内唯一)
* @param triggerTime 执行时间 时间戳(毫秒)
* @return 是否插入成功
*/
public boolean addJob(String jobId, Long triggerTime) {
//redis 中排序时间
long delaySeconds = triggerTime / 1000;
//增加延时任务 参数依次为队列名称、执行时间、任务id
boolean result = cache.zAdd(setDelayQueueName(), delaySeconds, jobId);
log.info("增加延时任务, 缓存key {}, 执行时间 {},任务id {}", setDelayQueueName(), DateUtil.toString(triggerTime), jobId);
return result;
}
/**
* 要实现延时队列的名字
*/
public abstract String setDelayQueueName();
}

View File

@@ -0,0 +1,24 @@
package cn.lili.common.trigger.delay.queue;
import cn.lili.common.trigger.delay.AbstractDelayQueueMachineFactory;
import cn.lili.common.trigger.enums.DelayQueueEnums;
import org.springframework.stereotype.Component;
/**
* 促销延迟队列
*
* @author paulG
* @version v4.1
* @date 2020/11/17 7:19 下午
* @description
* @since 1
*/
@Component
public class PromotionDelayQueue extends AbstractDelayQueueMachineFactory {
@Override
public String setDelayQueueName() {
return DelayQueueEnums.PROMOTION.name();
}
}

View File

@@ -0,0 +1,19 @@
package cn.lili.common.trigger.enums;
/**
* 队列枚举
*/
public enum DelayQueueEnums {
/**
* 促销活动
*/
PROMOTION("促销活动");
private String description;
DelayQueueEnums(String description) {
this.description = description;
}
}

View File

@@ -0,0 +1,31 @@
package cn.lili.common.trigger.enums;
/**
* 延时任务类型
*
* @author paulG
* @since 2021/5/7
*/
public enum DelayTypeEnums {
/**
* 促销活动
*/
PROMOTION("促销活动"),
/**
* 拼团订单
*/
PINTUAN_ORDER("拼团订单"),
/**
* 直播
*/
BROADCAST("直播");
private String description;
DelayTypeEnums(String description) {
this.description = description;
}
}

View File

@@ -9,35 +9,20 @@ import cn.lili.common.trigger.model.TimeTriggerMsg;
*/
public interface TimeTrigger {
/**
* 添加延时任务
*
* @param executorName 执行器beanId
* @param param 执行参数
* @param triggerTime 执行时间 时间戳 秒为单位
* @param uniqueKey 如果是一个 需要有 修改/取消 延时任务功能的延时任务,<br/>
* 请填写此参数,作为后续删除,修改做为唯一凭证 <br/>
* 建议参数为COUPON_{ACTIVITY_ID} 例如 coupon_123<br/>
* 业务内全局唯一
* @param topic rocketmq topic
*/
void add(String executorName, Object param, Long triggerTime, String uniqueKey, String topic);
/**
* 添加延时任务
*
* @param timeTriggerMsg 延时任务信息
*/
void add(TimeTriggerMsg timeTriggerMsg);
void addDelay(TimeTriggerMsg timeTriggerMsg);
/**
* 添加延时任务
* 执行延时任务
*
* @param timeTriggerMsg 延时任务信息
* @param delayTime 延时时间(秒)
*/
void addDelay(TimeTriggerMsg timeTriggerMsg, int delayTime);
void execute(TimeTriggerMsg timeTriggerMsg);
/**
* 修改延时任务

View File

@@ -1,12 +1,12 @@
package cn.lili.common.trigger;
package cn.lili.common.trigger.interfaces.impl;
import cn.hutool.json.JSONUtil;
import cn.lili.common.cache.Cache;
import cn.lili.common.rocketmq.RocketmqSendCallbackBuilder;
import cn.lili.common.trigger.delay.PromotionDelayQueue;
import cn.lili.common.trigger.delay.queue.PromotionDelayQueue;
import cn.lili.common.trigger.interfaces.TimeTrigger;
import cn.lili.common.trigger.model.TimeTriggerMsg;
import cn.lili.common.trigger.util.TimeTriggerUtil;
import cn.lili.common.trigger.util.DelayQueueTools;
import cn.lili.common.utils.DateUtil;
import cn.lili.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
@@ -17,6 +17,8 @@ import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
/**
* 延时任务实现
*
* @author paulG
* @since 2020/11/5
**/
@@ -32,8 +34,49 @@ public class RocketmqTimerTrigger implements TimeTrigger {
@Override
public void add(String executorName, Object param, Long triggerTime, String uniqueKey, String topic) {
public void addDelay(TimeTriggerMsg timeTriggerMsg) {
//执行器唯一key
String uniqueKey = timeTriggerMsg.getUniqueKey();
if (StringUtils.isEmpty(uniqueKey)) {
uniqueKey = StringUtils.getRandStr(10);
}
//执行任务key
String generateKey = DelayQueueTools.generateKey(timeTriggerMsg.getTriggerExecutor(), timeTriggerMsg.getTriggerTime(), uniqueKey);
this.cache.put(generateKey, 1);
//设置延时任务
if (Boolean.TRUE.equals(promotionDelayQueue.addJob(JSONUtil.toJsonStr(timeTriggerMsg), timeTriggerMsg.getTriggerTime()))) {
log.info("延时任务标识: {}", generateKey);
log.info("定时执行在【" + DateUtil.toString(timeTriggerMsg.getTriggerTime(), "yyyy-MM-dd HH:mm:ss") + "】,消费【" + timeTriggerMsg.getParam().toString() + "");
} else {
log.error("延时任务添加失败:{}", timeTriggerMsg);
}
}
@Override
public void execute(TimeTriggerMsg timeTriggerMsg) {
this.addExecute(timeTriggerMsg.getTriggerExecutor(),
timeTriggerMsg.getParam(),
timeTriggerMsg.getTriggerTime(),
timeTriggerMsg.getUniqueKey(),
timeTriggerMsg.getTopic()
);
}
/**
* 将任务添加到mqmq异步队列执行
* <p>
* 本系统中redis相当于延时任务吊起机制而mq才是实际的业务消费执行任务的存在
*
* @param executorName 执行器beanId
* @param param 执行参数
* @param triggerTime 执行时间 时间戳 秒为单位
* @param uniqueKey 如果是一个 需要有 修改/取消 延时任务功能的延时任务<br/>
* 请填写此参数作为后续删除修改做为唯一凭证 <br/>
* 建议参数为COUPON_{ACTIVITY_ID} 例如 coupon_123<br/>
* 业务内全局唯一
* @param topic rocketmq topic
*/
private void addExecute(String executorName, Object param, Long triggerTime, String uniqueKey, String topic) {
TimeTriggerMsg timeTriggerMsg = new TimeTriggerMsg(executorName, triggerTime, param, uniqueKey, topic);
Message<TimeTriggerMsg> message = MessageBuilder.withPayload(timeTriggerMsg).build();
@@ -41,39 +84,16 @@ public class RocketmqTimerTrigger implements TimeTrigger {
this.rocketMQTemplate.asyncSend(topic, message, RocketmqSendCallbackBuilder.commonCallback());
}
@Override
public void add(TimeTriggerMsg timeTriggerMsg) {
this.add(timeTriggerMsg.getTriggerExecutor(), timeTriggerMsg.getParam(), timeTriggerMsg.getTriggerTime(), timeTriggerMsg.getUniqueKey(), timeTriggerMsg.getTopic());
}
@Override
public void addDelay(TimeTriggerMsg timeTriggerMsg, int delayTime) {
String uniqueKey = timeTriggerMsg.getUniqueKey();
if (StringUtils.isEmpty(uniqueKey)) {
uniqueKey = StringUtils.getRandStr(10);
}
//执行任务key
String generateKey = TimeTriggerUtil.generateKey(timeTriggerMsg.getTriggerExecutor(), timeTriggerMsg.getTriggerTime(), uniqueKey);
this.cache.put(generateKey, 1);
//设置延时任务
if (Boolean.TRUE.equals(promotionDelayQueue.addJobId(JSONUtil.toJsonStr(timeTriggerMsg), delayTime))) {
log.info("add Redis key {}", generateKey);
log.info("定时执行在【" + DateUtil.toString(timeTriggerMsg.getTriggerTime(), "yyyy-MM-dd HH:mm:ss") + "】,消费【" + timeTriggerMsg.getParam().toString() + "");
} else {
log.error("延时任务添加失败:{}", timeTriggerMsg);
}
}
@Override
public void edit(String executorName, Object param, Long oldTriggerTime, Long triggerTime, String uniqueKey, int delayTime, String topic) {
this.delete(executorName, oldTriggerTime, uniqueKey, topic);
this.addDelay(new TimeTriggerMsg(executorName, triggerTime, param, uniqueKey, topic), delayTime);
this.addDelay(new TimeTriggerMsg(executorName, triggerTime, param, uniqueKey, topic));
}
@Override
public void delete(String executorName, Long triggerTime, String uniqueKey, String topic) {
String generateKey = TimeTriggerUtil.generateKey(executorName, triggerTime, uniqueKey);
log.info("delete redis key {} -----------------------", generateKey);
String generateKey = DelayQueueTools.generateKey(executorName, triggerTime, uniqueKey);
log.info("删除延时任务{}", generateKey);
this.cache.remove(generateKey);
}
}

View File

@@ -0,0 +1,34 @@
package cn.lili.common.delayqueue;
import cn.hutool.core.date.DateTime;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* 直播消息实体
*
* @author Bulbasaur
* @date: 2021/6/1 4:48 下午
*/
@Data
@NoArgsConstructor
public class BroadcastMessage {
/**
* 直播间ID
*/
private String studioId;
/**
* 状态
*/
private String status;
public BroadcastMessage(String studioId, String status) {
this.studioId = studioId;
this.status = status;
}
}

View File

@@ -1,4 +1,4 @@
package cn.lili.common.delayqueue;
package cn.lili.common.trigger.message;
import lombok.AllArgsConstructor;
import lombok.Data;

View File

@@ -1,4 +1,4 @@
package cn.lili.common.delayqueue;
package cn.lili.common.trigger.message;
import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;

View File

@@ -1,6 +1,8 @@
package cn.lili.common.trigger.model;
/**
* 延时任务执行器常量
*
* @author paulG
* @since 2020/8/20
**/
@@ -12,13 +14,8 @@ public abstract class TimeExecuteConstant {
public static final String PROMOTION_EXECUTOR = "promotionTimeTriggerExecutor";
/**
* 拼团延迟加载执行器
* 直播间延迟加载执行器
*/
public static final String PINTUAN_EXECUTOR = "pintuanTimeTriggerExecutor";
/**
* 拼团延迟加载执行器
*/
public static final String FULL_DISCOUNT_EXECUTOR = "fullDiscountTimeTriggerExecutor";
public static final String BROADCAST_EXECUTOR = "broadcastTimeTriggerExecutor";
}

View File

@@ -1,17 +1,32 @@
package cn.lili.common.trigger.util;
import cn.lili.common.trigger.enums.DelayTypeEnums;
/**
* 延时任务mq实现内容提供加密算法以及任务前缀参数
* 延时任务工具类
*
* @author Chopper
*/
public class TimeTriggerUtil {
* @author paulG
* @since 2021/5/7
**/
public class DelayQueueTools {
/**
* 前缀
*/
private static final String PREFIX = "{rocketmq_trigger}_";
/**
* 组装延时任务唯一键
*
* @param type 延时任务类型
* @param id id
* @return 唯一键
*/
public static String wrapperUniqueKey(DelayTypeEnums type, String id) {
return "{TIME_TRIGGER_" + type.name() + "}_" + id;
}
/**
* 生成延时任务标识key
*
@@ -24,5 +39,4 @@ public class TimeTriggerUtil {
return PREFIX + (executorName + triggerTime + uniqueKey).hashCode();
}
}

View File

@@ -1,5 +1,6 @@
package cn.lili.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import java.util.Base64;
@@ -12,6 +13,7 @@ import java.io.*;
*
* @author Chopper
*/
@Slf4j
public class Base64DecodeMultipartFile implements MultipartFile {
private final byte[] imgContent;
@@ -64,7 +66,7 @@ public class Base64DecodeMultipartFile implements MultipartFile {
stream = new FileOutputStream(dest);
stream.write(imgContent);
} catch (IOException e) {
e.printStackTrace();
log.error("transferTo错误",e);
}finally {
stream.close();
}
@@ -92,14 +94,14 @@ public class Base64DecodeMultipartFile implements MultipartFile {
byte[] bytes = Base64.getDecoder().decode(base64);
stream = new ByteArrayInputStream(bytes);
} catch (Exception e) {
e.printStackTrace();
log.error("base64ToInputStream错误",e);
}
return stream;
}
public static String inputStreamToStream(InputStream in) {
byte[] data = null;
// 读取图片字节数组
//读取图片字节数组
try {
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[100];
@@ -109,13 +111,13 @@ public class Base64DecodeMultipartFile implements MultipartFile {
}
data = swapStream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
log.error("转码错误",e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
log.error("inputStreamToStream错误",e);
}
}
}

View File

@@ -1,5 +1,7 @@
package cn.lili.common.utils;
import cn.hutool.json.JSONUtil;
import cn.lili.modules.payment.kit.dto.PayParam;
import org.springframework.beans.BeanUtils;
import java.lang.reflect.Field;
@@ -56,4 +58,75 @@ public class BeanUtil {
return null;
}
}
/**
* 将对象转换为key value
* A=a&B=b&C=c 格式
*/
public static String formatKeyValuePair(Object object) {
//准备接受的字符串
StringBuilder stringBuffer = new StringBuilder();
//获取对象字段
String[] fieldNames = BeanUtil.getFiledName(object);
//遍历所有属性
for (int j = 0; j < fieldNames.length; j++) {
//不是第一个并且不是最后一个,拼接&
if (j != 0) {
stringBuffer.append("&");
}
//获取属性的名字
String key = fieldNames[j];
//获取值
Object value = BeanUtil.getFieldValueByName(key, object);
stringBuffer.append(key).append("=").append(value.toString());
}
return stringBuffer.toString();
}
/**
* key value键值对 转换为 对象
* A=a&B=b&C=c 格式 转换为对象
*/
public static <T> T formatKeyValuePair(String str, T t) {
//填写对参数键值对
String[] params = str.split("&");
//获取对象字段
String[] fieldNames = BeanUtil.getFiledName(t);
try {
//循环每个参数
for (String param : params) {
String[] keyValues = param.split("=");
for (int i = 0; i < fieldNames.length; i++) {
if (fieldNames[i].equals(keyValues[0])) {
Field f = t.getClass().getDeclaredField(fieldNames[i]);
f.setAccessible(true);
//长度为2 才转换,否则不转
if (keyValues.length == 2) {
f.set(t, keyValues[1]);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
public static void main(String[] args) throws IllegalAccessException {
PayParam payParam = new PayParam();
payParam.setClientType("client");
payParam.setOrderType("");
payParam.setSn("sn");
String val = formatKeyValuePair(payParam);
System.out.println(val);
PayParam param = formatKeyValuePair(val, new PayParam());
System.out.println(JSONUtil.toJsonStr(param));
}
}

View File

@@ -14,9 +14,9 @@ import java.util.regex.Pattern;
public class CheckMobileUtil {
// \b 是单词边界(连着的两个(字母字符 与 非字母字符) 之间的逻辑上的间隔),
// 字符串在编译时会被转码一次,所以是 "\\b"
// \B 是单词内部逻辑间隔(连着的两个字母字符之间的逻辑上的间隔)
//\b 是单词边界(连着的两个(字母字符 与 非字母字符) 之间的逻辑上的间隔),
//字符串在编译时会被转码一次,所以是 "\\b"
//\B 是单词内部逻辑间隔(连着的两个字母字符之间的逻辑上的间隔)
static String phoneReg = "\\b(ip(hone|od)|android|opera m(ob|in)i"
+ "|windows (phone|ce)|blackberry"
+ "|s(ymbian|eries60|amsung)|p(laybook|alm|rofile/midp"
@@ -41,7 +41,7 @@ public class CheckMobileUtil {
if (null == userAgent) {
userAgent = "";
}
// 匹配
//匹配
Matcher matcherPhone = phonePat.matcher(userAgent);
Matcher matcherTable = tablePat.matcher(userAgent);
if (matcherPhone.find() || matcherTable.find()) {

View File

@@ -1,5 +1,7 @@
package cn.lili.common.utils;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -11,24 +13,9 @@ import javax.servlet.http.HttpServletResponse;
* @version v1.0
* 2020-12-14 09:32
*/
@Slf4j
public class CookieUtil {
/**
* 新增cookie
*
* @param key key值
* @param value 对应值
* @param response 响应
*/
public static void addCookie(String key, String value, HttpServletResponse response) {
try {
Cookie c = new Cookie(key, value);
c.setPath("/");
response.addCookie(c);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 新增cookie
@@ -45,7 +32,7 @@ public class CookieUtil {
c.setPath("/");
response.addCookie(c);
} catch (Exception e) {
e.printStackTrace();
log.error("新增cookie错误",e);
}
}
@@ -61,7 +48,7 @@ public class CookieUtil {
c.setMaxAge(0);
response.addCookie(c);
} catch (Exception e) {
e.printStackTrace();
log.error("删除cookie错误",e);
}
}
@@ -83,7 +70,7 @@ public class CookieUtil {
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("获取cookie错误",e);
}
return null;
}

View File

@@ -56,6 +56,24 @@ public final class CurrencyUtil {
return b1.multiply(b2).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的乘法运算。
*
* @param v1 被乘数
* @param v2 乘数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的积
*/
public static Double mul(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时, 精确到小数点以后10位以后的数字四舍五入。
*

View File

@@ -87,6 +87,9 @@ public class DateUtil {
* @return
*/
public static Date endOfDate(Date date) {
if (date == null) {
date = new Date();
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 23);
@@ -148,18 +151,18 @@ public class DateUtil {
* @return
*/
public static Long[] getLastMonth() {
// 取得系统当前时间
//取得系统当前时间
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;
// 取得系统当前时间所在月第一天时间对象
//取得系统当前时间所在月第一天时间对象
cal.set(Calendar.DAY_OF_MONTH, 1);
// 日期减一,取得上月最后一天时间对象
//日期减一,取得上月最后一天时间对象
cal.add(Calendar.DAY_OF_MONTH, -1);
// 输出上月最后一天日期
//输出上月最后一天日期
int day = cal.get(Calendar.DAY_OF_MONTH);
String months = "";
@@ -194,12 +197,23 @@ public class DateUtil {
/**
* 把日期转换成字符串型
*
* @param date 日期
* @param date 日期
* @return
*/
public static String toString(Date date) {
return toString(date,STANDARD_FORMAT);
return toString(date, STANDARD_FORMAT);
}
/**
* 把日期转换成字符串型
*
* @param Long 日期
* @return
*/
public static String toString(Long date) {
return toString(date, STANDARD_FORMAT);
}
/**
* 把日期转换成字符串型
*
@@ -346,7 +360,7 @@ public class DateUtil {
*/
public static Integer getDelayTime(Long startTime) {
int time = Math.toIntExact((startTime - System.currentTimeMillis()) / 1000);
// 如果时间为负数则改为一秒后执行
//如果时间为负数则改为一秒后执行
if (time <= 0) {
time = 1;
}

View File

@@ -43,14 +43,14 @@ public class HibernateProxyTypeAdapter extends TypeAdapter<HibernateProxy> {
out.nullValue();
return;
}
// Retrieve the original (not proxy) class
//Retrieve the original (not proxy) class
Class<?> baseType = Hibernate.getClass(value);
// Get the TypeAdapter of the original class, to delegate the serialization
//Get the TypeAdapter of the original class, to delegate the serialization
TypeAdapter delegate = context.getAdapter(TypeToken.get(baseType));
// Get a filled instance of the original class
//Get a filled instance of the original class
Object unproxiedValue = ((HibernateProxy) value).getHibernateLazyInitializer()
.getImplementation();
// Serialize the value
//Serialize the value
delegate.write(out, unproxiedValue);
}
}

View File

@@ -1,9 +1,12 @@
package cn.lili.common.utils;
import org.apache.http.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
@@ -21,7 +24,6 @@ import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLException;
@@ -30,31 +32,30 @@ import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
public class HttpClientUtils {
// org.apache.http.impl.client.CloseableHttpClient
//org.apache.http.impl.client.CloseableHttpClient
private static CloseableHttpClient httpClient = null;
// 这里就直接默认固定了,因为以下三个参数在新建的method中仍然可以重新配置并被覆盖.
static final int connectionRequestTimeout = 30000;// ms毫秒,从池中获取链接超时时间
static final int connectTimeout = 60000;// ms毫秒,建立链接超时时间
static final int socketTimeout = 60000;// ms毫秒,读取超时时间
//这里就直接默认固定了,因为以下三个参数在新建的method中仍然可以重新配置并被覆盖.
static final int connectionRequestTimeout = 30000;//ms毫秒,从池中获取链接超时时间
static final int connectTimeout = 60000;//ms毫秒,建立链接超时时间
static final int socketTimeout = 60000;//ms毫秒,读取超时时间
// 总配置,主要涉及是以下两个参数,如果要作调整没有用到properties会比较后麻烦,但鉴于一经粘贴,随处可用的特点,就不再做依赖性配置化处理了.
// 而且这个参数同一家公司基本不会变动.
static final int maxTotal = 500;// 最大总并发,很重要的参数
static final int maxPerRoute = 100;// 每路并发,很重要的参数
//总配置,主要涉及是以下两个参数,如果要作调整没有用到properties会比较后麻烦,但鉴于一经粘贴,随处可用的特点,就不再做依赖性配置化处理了.
//而且这个参数同一家公司基本不会变动.
static final int maxTotal = 500;//最大总并发,很重要的参数
static final int maxPerRoute = 100;//每路并发,很重要的参数
// 正常情况这里应该配成MAP或LIST
// 细化配置参数,用来对每路参数做精细化处理,可以管控各ip的流量,比如默认配置请求baidu:80端口最大100个并发链接,
static final String detailHostName = "http://www.baidu.com";// 每个细化配置之ip(不重要,在特殊场景很有用)
// 每个细化配置之port(不重要,在特殊场景很有用)
//正常情况这里应该配成MAP或LIST
//细化配置参数,用来对每路参数做精细化处理,可以管控各ip的流量,比如默认配置请求baidu:80端口最大100个并发链接,
static final String detailHostName = "http://www.baidu.com";//每个细化配置之ip(不重要,在特殊场景很有用)
//每个细化配置之port(不重要,在特殊场景很有用)
static final int detailPort = 80;
// 每个细化配置之最大并发数(不重要,在特殊场景很有用)
//每个细化配置之最大并发数(不重要,在特殊场景很有用)
static final int detailMaxPerRoute = 100;
private synchronized static CloseableHttpClient getHttpClient() {
@@ -71,51 +72,51 @@ public class HttpClientUtils {
private static CloseableHttpClient init() {
CloseableHttpClient newHotpoint;
// 设置连接池
//设置连接池
ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", plainsf).register("https", sslsf).build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
// 将最大连接数增加
//将最大连接数增加
cm.setMaxTotal(maxTotal);
// 将每个路由基础的连接增加
//将每个路由基础的连接增加
cm.setDefaultMaxPerRoute(maxPerRoute);
// 细化配置开始,其实这里用Map或List的for循环来配置每个链接,在特殊场景很有用.
// 将每个路由基础的连接做特殊化配置,一般用不着
//细化配置开始,其实这里用Map或List的for循环来配置每个链接,在特殊场景很有用.
//将每个路由基础的连接做特殊化配置,一般用不着
HttpHost httpHost = new HttpHost(detailHostName, detailPort);
// 将目标主机的最大连接数增加
//将目标主机的最大连接数增加
cm.setMaxPerRoute(new HttpRoute(httpHost), detailMaxPerRoute);
// 细化配置结束
//细化配置结束
// 请求重试处理
//请求重试处理
HttpRequestRetryHandler httpRequestRetryHandler = (exception, executionCount, context) -> {
if (executionCount >= 2) {// 如果已经重试了2次就放弃
if (executionCount >= 2) {//如果已经重试了2次就放弃
return false;
}
if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试
if (exception instanceof NoHttpResponseException) {//如果服务器丢掉了连接,那么就重试
return true;
}
if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常
if (exception instanceof SSLHandshakeException) {//不要重试SSL握手异常
return false;
}
if (exception instanceof InterruptedIOException) {// 超时
if (exception instanceof InterruptedIOException) {//超时
return false;
}
if (exception instanceof UnknownHostException) {// 目标服务器不可达
if (exception instanceof UnknownHostException) {//目标服务器不可达
return false;
}
if (exception instanceof SSLException) {// SSL握手异常
if (exception instanceof SSLException) {//SSL握手异常
return false;
}
HttpClientContext clientContext = HttpClientContext.adapt(context);
HttpRequest request = clientContext.getRequest();
// 如果请求是幂等的,就再次尝试
//如果请求是幂等的,就再次尝试
return !(request instanceof HttpEntityEnclosingRequest);
};
// 配置请求的超时设置
//配置请求的超时设置
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeout).setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).build();
newHotpoint = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(requestConfig).setRetryHandler(httpRequestRetryHandler).build();
return newHotpoint;
@@ -123,13 +124,13 @@ public class HttpClientUtils {
public static String doGet(String url, Map<String, String> param) {
// httpClient
//httpClient
CloseableHttpClient httpClient = getHttpClient();
String resultString = "";
CloseableHttpResponse response = null;
try {
// 创建uri
//创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
@@ -138,19 +139,17 @@ public class HttpClientUtils {
}
URI uri = builder.build();
// 创建http GET请求
//创建http GET请求
HttpGet httpGet = new HttpGet(uri);
// 执行请求
//执行请求
response = httpClient.execute(httpGet);
// 判断返回状态是否为200
//判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
} else {
System.out.println(response.getStatusLine().getStatusCode());
}
} catch (Exception e) {
e.printStackTrace();
log.error("get请求错误",e);
} finally {
try {
if (response != null) {
@@ -158,71 +157,9 @@ public class HttpClientUtils {
}
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
log.error("Get错误",e);
}
}
return resultString;
}
public static String doPost(String url, Map<String, String> param) {
// 创建HttpClient对象
CloseableHttpClient httpClient = getHttpClient();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (param != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (String key : param.keySet()) {
paramList.add(new BasicNameValuePair(key, param.get(key)));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8");
httpPost.setEntity(entity);
}
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doPostJson(String url, String json) {
// 创建HttpClient对象
CloseableHttpClient httpClient = getHttpClient();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
}

Some files were not shown because too many files have changed in this diff Show More