「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。
之前我们已经做完了用户篇以及简单实现了完整的下单流程,接下来就是一些具体业务的实现,现阶段的表结构如下:
- rel_role_permiss:角色——权限关联中间表
- rel_user_role:用户——角色关联中间表
- sys_permissions:权限表
- sys_role:角色表
- sys_user:用户表 这五张表是用来做shiro认证和授权的,具体流程在之前的文章:
# springboot整合shiro——前后端分离模式(上篇)
# springboot整合shiro——前后端分离模式(下篇)
# springboot整合shiro——前后端分离模式(浅析登录流程)
- t_goods:秒杀商品表
- t_seckill_goods:秒杀商品表的简化版,t_goods表更新时会同步更新,但是只有必要的几个字段用于在秒杀的时候减库存用
- t_overdue_record:用户逾期记录,记录用户的逾期时间,金额等等信息
- t_goods_rule:商品规则表,用于配置秒杀活动的准入规则,跟逾期记录相关,会限制有逾期记录或者失信人员等条件无法参与此次活动
- t_order_record:订单记录
- t_apply_record:申请记录表,用户在查看商品详情时会先进行一次判断,根据商品规则表和用户逾期记录表判断用户是否有资格参与此次秒杀,无论成功与否都会留下一次申请记录
首先是完成一些简单的curd,这里以商品的controller为例:
@RestController
@RequestMapping("/goods")
@Tag(name = "t-goods-controller", description = "商品接口")
public class TGoodsController {
@Autowired
TGoodsServiceImpl tGoodsService;
@PostMapping("/insert")
@Operation(summary = "商品新增")
public Map insert(@RequestBody @Valid TGoods entity, BindingResult bindingResult) {
if (bindingResult.hasErrors())
throw new RuntimeException(bindingResult.getFieldError().getDefaultMessage());
return tGoodsService.insertGoods(entity);
}
@PostMapping("/delete")
@Operation(summary = "商品删除")
public String delete(@RequestBody String dataId) {
return tGoodsService.deleteGoods((String) JSONObject.parseObject(dataId).get("dataId"));
}
@PostMapping("/list")
@Operation(summary = "分页+条件查询商品列表,参数:"pageNum":0,\n" +
""pageSize":10,\n" + ""keyWord":"要查的关键字,没有就为空查询全部"")
public Map list(@RequestBody Map params) {
return tGoodsService.selectlist(params);
}
@PostMapping("/update")
@Operation(summary = "更新操作")
public String update(@RequestBody TGoods entity) {
return tGoodsService.updateOne(entity);
}
@PostMapping("/detail")
@Operation(summary = "根据dataid查询对应商品信息")
public TGoods detail(@RequestBody String dataId) {
return tGoodsService.detail((String)JSONObject.parseObject(dataId).get("dataId"));
}
}
其余的controller也时大同小异,具体代码都同步更新在GitHub仓库->github.com/yt-King/sec…
稍微有些不同的就是用户在点击秒杀商品详情的时候会调用detail方法:
public TGoods detail(String dataId) {
QueryWrapper<TGoods> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("data_id",dataId);
TGoods tGoods = tGoodsMapper.selectOne(queryWrapper);
if(null==tGoods)
throw new RuntimeException("商品不存在");
//查询准入规则,从头里或请求里拿到token得到用户信息
String token = TokenUtil.getRequestToken(request);
//根据token获取用户信息
if(null==token)
throw new RuntimeException("token为空,请重新登录");
SysUser sysUser = (SysUser) redisTemplate.opsForValue().get(token);
//查询准入规则
TGoodsRule tGoodsRule = tGoodsRuleService.detail(dataId);
//新增申请记录
TApplyRecord tApplyRecord = new TApplyRecord();
tApplyRecord.setUserId(sysUser.getUserId());
tApplyRecord.setUserName(sysUser.getName());
tApplyRecord.setGoodsId(tGoods.getDataId());
tApplyRecord.setGoodsName(tGoods.getGoodsName());
tApplyRecord.setApplyTime(new Date());
//根据用户查询是否有参与活动的资格
try {
sysUserService.checkUserQualify(sysUser,tGoodsRule);
}catch (Exception e){
//结果不通过
tApplyRecord.setApplyResult(1);
tApplyRecordService.insertRecord(tApplyRecord);
throw e;
}
//结果通过
tApplyRecord.setApplyResult(0);
tApplyRecordService.insertRecord(tApplyRecord);
return tGoods;
}
入参是商品的id,先根据头拿到token,具体如何获取在整合shiro篇有讲到,然后根据token拿到存在redis里的用户数据,在根据商品的id去查询对应的准入规则,然后根据商品id和用户id查询用户是否有参与此次活动的资格,方法如下:
public void checkUserQualify(SysUser sysUser, TGoodsRule tGoodsRule){
if(Integer.parseInt(sysUser.getAge())<tGoodsRule.getLimitAge())
//年龄不符合
throw new RuntimeException("抱歉您不符合本次活动要求,无法参与");
if(1==(Integer.parseInt(sysUser.getStatus())&tGoodsRule.getLimitIsUnemployment()))
//失业限制,进行与运算,两者都是1才说明不符合要求
throw new RuntimeException("抱歉您不符合本次活动要求,无法参与");
if(tOverdueRecordMapper.checkUserQualify(sysUser.getTel(), tGoodsRule)>=tGoodsRule.getLimitOverdueFrequency())
//逾期次数超过规定次数
throw new RuntimeException("抱歉您不符合本次活动要求,无法参与");
// System.out.println("tOverdueRecordMapper.checkUserQualify(sysUser.getTel(),tGoodsRule) = " + tOverdueRecordMapper.checkUserQualify(sysUser.getTel(), tGoodsRule));
}
不通过的情况下抛出异常后在detail捕获一下填入结果不通过的记录信息然后把申请记录写进数据库再把异常抛出。 最后根据自己的需求通过shiro授权用注释的方法在接口上授权即可。