SpringBoot 签到奖励实现方案的示例代码
前言
最近在做社交业务,用户进入APP后有签到功能,签到成功后获取相应的奖励:
项目状况:前期尝试业务阶段;
特点:
- 快速实现(不需要做太重,满足初期推广运营即可)
 - 快速投入市场去运营
 
用户签到:
- 用户在每次启动时查询签到记录(规则:连续7日签到从0开始,签到过程中有断签从0开始)
 - 如果今日未签到则提示用户可以进行签到
 - 用户签到获取相应的奖励
 
提到签到,脑海中首先浮现特点:
- 需要记录每位用户每天的签到情况
 - 查询时根据规则进行签到记录情况
 
需求&流程设计&技术实现方案
需求原型图
查询签到记录
进行签到
技术实现方案
- SpringBoot
 - MySQL
 
数据库表结构
签到记录最新表
CREATETABLE`zh_sign_in`( `id`bigint(20)NOTNULLAUTO_INCREMENT, `bu_no`varchar(32)DEFAULTNULLCOMMENT'业务编码', `customer_id`varchar(32)DEFAULTNULLCOMMENT'签到用户编码', `sign_in_date`datetimeDEFAULTNULLCOMMENT'签到日期(单位精确到日)', `reward_money`int(11)DEFAULTNULLCOMMENT'本次签到奖励金币个数', `continuite_day`int(2)DEFAULT'1'COMMENT'连续签到天数(A:7天内如果有断签从0开始B:7天签满从0开始)', `create_time`datetimeDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间', `update_time`datetimeDEFAULTCURRENT_TIMESTAMPCOMMENT'更新时间', `param1`int(2)DEFAULTNULLCOMMENT'预留字段1', `param2`int(4)DEFAULTNULLCOMMENT'预留字段2', `param3`int(11)DEFAULTNULLCOMMENT'预留字段3', `param4`varchar(20)DEFAULTNULLCOMMENT'预留字段4', `param5`varchar(32)DEFAULTNULLCOMMENT'预留字段5', `param6`varchar(64)DEFAULTNULLCOMMENT'预留字段6', PRIMARYKEY(`id`)USINGBTREE, UNIQUEKEY`uk_zh_sign_in_buno`(`bu_no`), UNIQUEKEY`uk_zh_sign_in_cid_signindate`(`customer_id`,`sign_in_date`)USINGBTREE )ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='用户签到表';
签到记录历史表
CREATETABLE`zh_sign_in_hist`( `id`bigint(20)NOTNULLAUTO_INCREMENT, `bu_no`varchar(32)DEFAULTNULLCOMMENT'业务编码', `customer_id`varchar(32)DEFAULTNULLCOMMENT'签到用户编码', `sign_in_date`datetimeNULLDEFAULTNULLCOMMENT'签到日期(单位精确到日)', `reward_money`int(11)DEFAULTNULLCOMMENT'本次签到奖励金币个数', `continuite_day`int(2)DEFAULT'1'COMMENT'连续签到天数(A:7天内如果有断签从0开始B:7天签满从0开始)', `create_time`datetimeDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间', `update_time`datetimeDEFAULTCURRENT_TIMESTAMPCOMMENT'更新时间', `param1`int(2)DEFAULTNULLCOMMENT'预留字段1', `param2`int(4)DEFAULTNULLCOMMENT'预留字段2', `param3`int(11)DEFAULTNULLCOMMENT'预留字段3', `param4`varchar(20)DEFAULTNULLCOMMENT'预留字段4', `param5`varchar(32)DEFAULTNULLCOMMENT'预留字段5', `param6`varchar(64)DEFAULTNULLCOMMENT'预留字段6', PRIMARYKEY(`id`)USINGBTREE, UNIQUEKEY`uk_zh_sign_in_hist_cid_signindate`(`customer_id`,`sign_in_date`)USINGBTREE, KEY`key_zh_sign_in_hist_buno`(`bu_no`)USINGBTREE )ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='用户签到历史表';
代码实现
完整代码(GitHub,欢迎大家Star,Fork,Watch)
https://github.com/dangnianchuntian/springboot
主要代码展示
Controller
/*
*Copyright(c)2020.zhanghan_java@163.comAllRightsReserved.
*项目名称:SpringBoot实战:签到奖励实现方案
*类名称:SignInController.java
*创建人:张晗
*联系方式:zhanghan_java@163.com
*开源地址:https://github.com/dangnianchuntian/springboot
*博客地址:https://zhanghan.blog.csdn.net
*/
packagecom.zhanghan.zhsignin.controller;
importcom.zhanghan.zhsignin.controller.request.PostSignInRequest;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.validation.annotation.Validated;
importorg.springframework.web.bind.annotation.RequestBody;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RequestMethod;
importorg.springframework.web.bind.annotation.RestController;
importcom.zhanghan.zhsignin.controller.request.ListSignInDetailRequest;
importcom.zhanghan.zhsignin.service.SignInService;
@RestController
publicclassSignInController{
@Autowired
privateSignInServicesignInService;
/**
*查询签到记录
*/
@RequestMapping(value="/list/sign/in/detail",method=RequestMethod.POST)
publicObjectlistSignInDetail(@RequestBody@ValidatedListSignInDetailRequestlistSignInDetailRequest){
returnsignInService.listSignInDetail(listSignInDetailRequest);
}
/**
*用户进行签到
*/
@RequestMapping(value="/post/sign/in",method=RequestMethod.POST)
publicObjectpostSignIn(@RequestBody@ValidatedPostSignInRequestpostSignInRequest){
returnsignInService.postSignIn(postSignInRequest);
}
}
service
/*
*Copyright(c)2020.zhanghan_java@163.comAllRightsReserved.
*项目名称:SpringBoot实战:签到奖励实现方案
*类名称:SignInServiceImpl.java
*创建人:张晗
*联系方式:zhanghan_java@163.com
*开源地址:https://github.com/dangnianchuntian/springboot
*博客地址:https://zhanghan.blog.csdn.net
*/
packagecom.zhanghan.zhsignin.service.impl;
importcn.hutool.core.util.IdUtil;
importcom.zhanghan.zhsignin.config.SignInRewardMoneyListConfig;
importcom.zhanghan.zhsignin.constant.SignInConstant;
importcom.zhanghan.zhsignin.controller.request.ListSignInDetailRequest;
importcom.zhanghan.zhsignin.controller.request.PostSignInRequest;
importcom.zhanghan.zhsignin.controller.response.ListSignInDetailResponse;
importcom.zhanghan.zhsignin.mybatis.entity.XZhSignInEntity;
importcom.zhanghan.zhsignin.mybatis.entity.XZhSignInHistEntity;
importcom.zhanghan.zhsignin.mybatis.mapper.XZhSignInHistMapper;
importcom.zhanghan.zhsignin.mybatis.mapper.XZhSignInMapper;
importcom.zhanghan.zhsignin.service.SignInService;
importcom.zhanghan.zhsignin.util.DateUtils;
importcom.zhanghan.zhsignin.util.wrapper.WrapMapper;
importorg.springframework.beans.BeanUtils;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.factory.annotation.Value;
importorg.springframework.stereotype.Service;
importorg.springframework.util.CollectionUtils;
importjava.util.Date;
importjava.util.List;
importjava.util.stream.Collectors;
importstaticcom.zhanghan.zhsignin.constant.SignInConstant.*;
@Service
publicclassSignInServiceImplimplementsSignInService{
@Autowired
privateXZhSignInMapperxZhSignInMapper;
@Autowired
privateXZhSignInHistMapperxZhSignInHistMapper;
//校验连续天数是否为7
@Value("#{T(java.lang.Integer).parseInt('${zh.sign.in.continuite.day.threshold:7}')}")
publicIntegercontinuiteDayThreshold;
//签到奖励金币集合配置
@Autowired
publicSignInRewardMoneyListConfigsignInRewardMoneyListConfig;
/**
*查询用户签到记录
*/
@Override
publicObjectlistSignInDetail(ListSignInDetailRequestlistSignInDetailRequest){
//若配置文件中未配置签到奖励则不展示签到记录
ListsignInRewardMoneyListConfigList=signInRewardMoneyListConfig.getList();
if(CollectionUtils.isEmpty(signInRewardMoneyListConfigList)){
returnWrapMapper.ok(newListSignInDetailResponse(false));
}
StringcustomerId=listSignInDetailRequest.getCustomerId();
XZhSignInEntityxZhSignInEntity=xZhSignInMapper.findByCustomerId(customerId);
ListsignInDetailList=signInRewardMoneyListConfigList.stream().map(aa->newListSignInDetailResponse.SignInDetail(0,aa)).collect(Collectors.toList());
//该用户之前未签到过
if(null==xZhSignInEntity){
returnWrapMapper.ok(newListSignInDetailResponse(TODAY_NOT_SIGN_IN,SignInConstant.CONTINUITE_DAY_ZERO,signInDetailList));
}
longsignInDateTime=xZhSignInEntity.getSignInDate().getTime();
//最近一次签到是否为昨日之前
if(signInDateTime=continuiteDayThreshold){
returnWrapMapper.ok(newListSignInDetailResponse(TODAY_NOT_SIGN_IN,SignInConstant.CONTINUITE_DAY_ZERO,signInDetailList));
}
//最近一次签到是昨日且之前连续未超7日
todaySignStatus=TODAY_NOT_SIGN_IN;
}
//查询用户签到历史记录
ListxZhSignInHistEntitieList=xZhSignInHistMapper.listByCustomerIdAndLimit(customerId,continuiteDay);
for(XZhSignInHistEntityxZhSignInHistEntity:xZhSignInHistEntitieList){
ListSignInDetailResponse.SignInDetailsignInDetail=newListSignInDetailResponse.SignInDetail(TODAY_YES_SIGN_IN,xZhSignInHistEntity.getRewardMoney());
signInDetailList.remove(xZhSignInHistEntity.getContinuiteDay()-1);
signInDetailList.add(xZhSignInHistEntity.getContinuiteDay()-1,signInDetail);
}
returnWrapMapper.ok(newListSignInDetailResponse(todaySignStatus,continuiteDay,signInDetailList));
}
/**
*进行签到
*/
@Override
publicObjectpostSignIn(PostSignInRequestpostSignInRequest){
//若配置文件中未配置签到奖励则不展示签到记录
ListsignInRewardMoneyListConfigList=signInRewardMoneyListConfig.getList();
if(CollectionUtils.isEmpty(signInRewardMoneyListConfigList)){
returnWrapMapper.ok();
}
//获取session用户对象
StringcustomerId=postSignInRequest.getCustomerId();
//根据customerId查询用户签到记录
XZhSignInEntityxZhSignInEntityByCustomerId=xZhSignInMapper.findByCustomerId(customerId);
//签到记录是否为空
if(null==xZhSignInEntityByCustomerId){
XZhSignInEntityxZhSignInEntity=newXZhSignInEntity();
xZhSignInEntity.setBuNo(IdUtil.simpleUUID());
xZhSignInEntity.setCustomerId(customerId);
xZhSignInEntity.setContinuiteDay(CONTINUITE_DAY_ONE);
xZhSignInEntity.setRewardMoney(signInRewardMoneyListConfigList.get(0));
xZhSignInEntity.setSignInDate(DateUtils.getTodayDate());
insertSigninAndHist(xZhSignInEntity);
returnWrapMapper.ok();
}
longsignInDateTime=xZhSignInEntityByCustomerId.getSignInDate().getTime();
if(signInDateTime==DateUtils.getTodayDateTime()){
returnWrapMapper.error("今天已经签到");
}
//获取连续签到天数
IntegercontinuiteDay=continuiteDay(xZhSignInEntityByCustomerId.getContinuiteDay(),signInDateTime);
xZhSignInEntityByCustomerId.setSignInDate(DateUtils.getTodayDate());
xZhSignInEntityByCustomerId.setContinuiteDay(continuiteDay);
xZhSignInEntityByCustomerId.setRewardMoney(signInRewardMoneyListConfigList.get(continuiteDay-1));
xZhSignInEntityByCustomerId.setUpdateTime(newDate());
xZhSignInEntityByCustomerId.setBuNo(IdUtil.simpleUUID());
updateSignInAndInsertHist(xZhSignInEntityByCustomerId);
returnWrapMapper.ok();
}
privateIntegercontinuiteDay(IntegercontinuiteDay,LongsignInDateTime){
if(signInDateTime=continuiteDayThreshold){
returnCONTINUITE_DAY_ONE;
}
returncontinuiteDay+1;
}
privatevoidinsertSigninAndHist(XZhSignInEntityxZhSignInEntity){
xZhSignInMapper.insertSelective(xZhSignInEntity);
XZhSignInHistEntityxZhSignInHistEntity=newXZhSignInHistEntity();
BeanUtils.copyProperties(xZhSignInEntity,xZhSignInHistEntity);
xZhSignInHistEntity.setId(null);
xZhSignInHistMapper.insertSelective(xZhSignInHistEntity);
}
privatevoidupdateSignInAndInsertHist(XZhSignInEntityxZhSignInEntity){
xZhSignInMapper.updateByPrimaryKeySelective(xZhSignInEntity);
XZhSignInHistEntityxZhSignInHistEntity=newXZhSignInHistEntity();
BeanUtils.copyProperties(xZhSignInEntity,xZhSignInHistEntity);
xZhSignInHistEntity.setId(null);
xZhSignInHistMapper.insertSelective(xZhSignInHistEntity);
}
}      
测试
模拟用户进行签到
进行请求
查看数据库结果
模拟用户查询签到记录
进行请求
总结
- 亮点:实现业务连续签到,断签以及奖励的业务
 - 注意点:基于数据库查询做的,在进行签到接口需要用redis锁防止并发操作
 - 后续会持续分享更多业务中的亮点
 
到此这篇关于SpringBoot签到奖励实现方案的示例代码的文章就介绍到这了,更多相关SpringBoot签到奖励内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。