深圳网站建设服务哪个便宜啊网站后台构建

张小明 2026/1/15 5:40:40
深圳网站建设服务哪个便宜啊,网站后台构建,网站建设介绍会发言稿,自己注册一家公司需要多少钱day10接口 1 查询发放中的优惠券接口说明查询发放中的优惠券请求方式GET请求路径/coupons/list请求参数无返回值[ { id: 110, // 优惠券id name: 年中大促, // 优惠券名称 specific: true, // 优惠券是…day10接口1 查询发放中的优惠券接口说明查询发放中的优惠券请求方式GET请求路径/coupons/list请求参数无返回值[ { id: 110, // 优惠券id name: 年中大促, // 优惠券名称 specific: true, // 优惠券是否限定了课程范围 discountType: , // 折扣类型 thresholdAmount: 0 // 折扣门槛 discountValue: 0, // 折扣值 maxDiscountAmount: 0, // 最大折扣金额 termDays: 0, // 有效天数 termEndTime: , // 过期时间 available: true, // 是否可领取 received: true, // 是否已领取 } ]CouponController.java/** * 查询发放中的优惠券列表 * return */ApiOperation(查询发放中的优惠券列表)GetMapping(list)publicListCouponVOqueryIssuingCoupons(){returncouponService.queryIssuingCoupons();}ICouponService.javaListCouponVOqueryIssuingCoupons();CouponServiceImpl.javaOverridepublicListCouponVOqueryIssuingCoupons(){//1.查询属于手动领取以及发放中的优惠券ListCouponlistlambdaQuery().eq(Coupon::getStatus,CouponStatus.ISSUING).eq(Coupon::getObtainWay,PUBLIC).list();if(CollUtils.isEmpty(list)){returnCollUtils.emptyList();}ListLongidslist.stream().map(Coupon::getId).collect(Collectors.toList());// 2.查询用户领取的并符合条件的优惠券ListUserCouponequserCouponService.lambdaQuery().eq(UserCoupon::getUserId,UserContext.getUser()).in(UserCoupon::getCouponId,ids).list();//2.1当前用户已经领取的数量MapLong,Longmapeq.stream().collect(Collectors.groupingBy(UserCoupon::getCouponId,Collectors.counting()));//2.2当前用户对优惠券已经领取但是没使用的数量MapLong,Longunusedeq.stream().filter(uc-uc.getStatus().equals(UserCouponStatus.UNUSED)).collect(Collectors.groupingBy(UserCoupon::getCouponId,Collectors.counting()));//3.封装优惠券信息并返回ArrayListCouponVOcouponVOSnewArrayList();for(Couponcoupon:list){CouponVOcouponVOBeanUtils.copyBean(coupon,CouponVO.class);//3.是否可以领取被领取数量未达到总发放数量当前用户领取数量小于每人最多领取数量couponVO.setAvailable(coupon.getIssueNum()coupon.getTotalNum()map.getOrDefault(coupon.getId(),0L)coupon.getUserLimit());//4.是否可以使用(未使用的)couponVO.setReceived(unused.getOrDefault(coupon.getId(),0L)0);couponVOS.add(couponVO);}returncouponVOS;}2 手动领取优惠券UserCouponController.java/** * 领取优惠券(方式为手动领取的优惠券) * * param couponId * return */PostMapping({couponId}/receive)ApiOperation(领取优惠券)publicvoidreceiveCoupon(PathVariableLongcouponId){userCouponService.receiveCoupon(couponId);}IUserCouponService.javavoidreceiveCoupon(LongcouponId);UserCouponServiceImpl.javaOverrideTransactionalpublicvoidreceiveCoupon(LongcouponId){CouponcouponcouponMapper.selectById(couponId);if(couponnull){thrownewBizIllegalException(优惠券不存在);}LocalDateTimenowLocalDateTime.now();if(now.isBefore(coupon.getIssueBeginTime())||now.isAfter(coupon.getIssueEndTime())){thrownewBizIllegalException(优惠券不在领取时间范围内);}LonguserIdUserContext.getUser();LongresultredisLuaService.tryReceiveCoupon(couponId,userId,coupon.getUserLimit());if(resultnull){thrownewBizIllegalException(系统繁忙);}if(result-1){thrownewBizIllegalException(超过个人领取上限);}if(result0){thrownewBizIllegalException(库存不足);}try{saveUserCouponWithTx(coupon,userId,now);}catch(Exceptione){redisLuaService.rollbackCoupon(couponId,userId);throwe;}}TransactionalpublicvoidsaveUserCouponWithTx(Couponcoupon,LonguserId,LocalDateTimenow){// 1. 校验每人限领数量兜底IntegercountlambdaQuery().eq(UserCoupon::getUserId,userId).eq(UserCoupon::getCouponId,coupon.getId()).count();if(count!nullcountcoupon.getUserLimit()){thrownewBizIllegalException(该用户领取数量超出限制);}// 2. 乐观更新优惠券发放数量最终防线introwscouponMapper.incrIssueNumWithLimit(coupon.getId());if(rows0){thrownewBizIllegalException(优惠券库存不足);}// 3. 新增用户优惠券addCoupon(coupon.getId(),coupon,now,userId);}privatevoidaddCoupon(LongcouponId,Couponcoupon,LocalDateTimenow,LonguserId){UserCouponuserCouponnewUserCoupon();LocalDateTimetermBeginTimecoupon.getTermBeginTime();LocalDateTimetermEndTimecoupon.getTermEndTime();if(termBeginTimenull){termBeginTimenow;termEndTimetermBeginTime.plusDays(coupon.getTermDays());}userCoupon.setUserId(userId);userCoupon.setCouponId(couponId);userCoupon.setTermBeginTime(termBeginTime);userCoupon.setTermEndTime(termEndTime);userCoupon.setStatus(UserCouponStatus.UNUSED);this.save(userCoupon);}Lua脚本-- KEYS[1] coupon:stock:{couponId}-- KEYS[2] coupon:user:{couponId}-- ARGV[1] userId-- ARGV[2] userLimit-- 1. 查询用户已领取数量localcounttonumber(redis.call(HGET,KEYS[2],ARGV[1])or0)locallimittonumber(ARGV[2])ifcountlimitthenreturn-1-- 超过个人限领end-- 2. 校验库存localstocktonumber(redis.call(GET,KEYS[1]))ifnotstockorstock0thenreturn0-- 库存不足end-- 3. 扣库存redis.call(DECR,KEYS[1])-- 4. 用户领取数量 1redis.call(HINCRBY,KEYS[2],ARGV[1],1)-- 5. 成功return1LUA配置类packagecom.tianji.promotion.config;importcom.tianji.promotion.constants.PromotionConstants;importlombok.RequiredArgsConstructor;importorg.springframework.core.io.ClassPathResource;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.data.redis.core.script.DefaultRedisScript;importorg.springframework.stereotype.Service;importjava.util.Arrays;importjava.util.List;/** * Redis Lua 执行统一封装 * * 职责 * 1. 负责 Lua 脚本加载 * 2. 统一管理 Redis Key 拼装 * 3. 对业务层屏蔽 Lua 细节 * author ABC */ServiceRequiredArgsConstructorpublicclassRedisLuaService{privatefinalStringRedisTemplateredisTemplate;privatestaticfinalDefaultRedisScriptLongRECEIVE_COUPON_SCRIPT;static{RECEIVE_COUPON_SCRIPTnewDefaultRedisScript();RECEIVE_COUPON_SCRIPT.setLocation(newClassPathResource(redis/lua/receive_coupon.lua));RECEIVE_COUPON_SCRIPT.setResultType(Long.class);}publicLongtryReceiveCoupon(LongcouponId,LonguserId,IntegeruserLimit){StringstockKeyPromotionConstants.COUPON_STOCK_KEYcouponId;StringuserCountKeyPromotionConstants.COUPON_USER_COUNT_KEYcouponId;returnredisTemplate.execute(RECEIVE_COUPON_SCRIPT,List.of(stockKey,userCountKey),userId.toString(),userLimit.toString());}/** * DB 失败回滚 */publicvoidrollbackCoupon(LongcouponId,LonguserId){StringstockKeyPromotionConstants.COUPON_STOCK_KEYcouponId;StringuserCountKeyPromotionConstants.COUPON_USER_COUNT_KEYcouponId;redisTemplate.opsForValue().increment(stockKey);redisTemplate.opsForHash().increment(userCountKey,userId.toString(),-1);}}Redis常量Keypackagecom.tianji.promotion.constants;/** * 优惠券常量类 * * author ax */publicinterfacePromotionConstants{/** * 优惠券的兑换码生成序列号key */StringCOUPON_CODE_SERIAL_KEYcoupon:code:serial:;/** * 优惠券的兑换码兑换序列号key */StringCOUPON_CODE_MAP_KEYcoupon:code:serial:;/** * 优惠券库存 * coupon:stock:{couponId} - int */StringCOUPON_STOCK_KEYcoupon:stock:;/** * 用户已领取数量 * coupon:user:{couponId} - Hash(userId - count) */StringCOUPON_USER_COUNT_KEYcoupon:user:;}CouponMapper.javaUpdate(update coupon set issue_num issue_num 1 where id #{couponId} and issue_num total_num)intincrIssueNumWithLimit(LongcouponId);3 兑换码兑换优惠券UserCouponController.java/** * 兑换码兑换优惠券(方式为兑换码兑换的优惠券) * * return */PostMapping({code}/exchange)ApiOperation(兑换码兑换优惠券)publicvoidexchangeCoupon(PathVariableStringcode){userCouponService.exchangeCoupon(code);}IUserCouponService.javavoidexchangeCoupon(Stringcode);UserCouponServiceImpl.javaOverrideTransactionalpublicvoidexchangeCoupon(Stringcode){//校验兑换码是否被兑换过是否存在longlCodeUtil.parseCode(code);//是否已经兑换过 setbit替换getbitbooleanisExchangeexchangeCodeService.updateExchangeMark(l,true);try{if(isExchange){thrownewBizIllegalException(该兑换码已经兑换过);}ExchangeCodebyIdexchangeCodeService.getById(l);if(byIdnull){thrownewBizIllegalException(该兑换码不存在);}LocalDateTimenowLocalDateTime.now();if(now.isAfter(byId.getExpiredTime())){thrownewBizIllegalException(该兑换码已过期);}//查询优惠券CouponcouponcouponMapper.selectById(byId.getExchangeTargetId());LonguserIdUserContext.getUser();//领取优惠券saveUserCouponWithTx(coupon,userId,now);//更新兑换码状态exchangeCodeService.lambdaUpdate().eq(ExchangeCode::getId,l).set(ExchangeCode::getUserId,userId).set(ExchangeCode::getStatus,ExchangeCodeStatus.USED).update();}catch(Exceptione){exchangeCodeService.updateExchangeMark(l,false);throwe;}}IExchangeCodeServicebooleanupdateExchangeMark(longl,booleanb);ExchangeCodeServiceImplOverridepublicbooleanupdateExchangeMark(longl,booleanb){BooleanisstringRedisTemplate.opsForValue().setBit(COUPON_CODE_MAP_KEY,l,b);returnis!nullis;}CouponMapper.javaUpdate(update coupon set issue_num issue_num 1 where id #{couponId} and issue_num total_num)intincrIssueNumWithLimit(LongcouponId);一种解决方案我们可以借助AspectJ来实现。1引入AspectJ依赖!--aspecj--dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactId/dependency2暴露代理对象在启动类上添加注解暴露代理对象3使用代理对象最后改造领取优惠券的代码获取代理对象来调用事务方法
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

邮编域名做网站四川建设机械网站首页

查看全文:https://www.longkui.site/program/java/java-jeesite-jeecgboot-smartadmin-ruoyi/7161/ 在Java后端开发中,选择合适的快速开发框架对于项目的开发效率和质量至关重要。本文将围绕技术特点、优劣势、适用场景、最佳实践及实际案例,…

张小明 2026/1/15 0:07:42 网站建设

...东莞网站公司盘锦企业网站建设

Stable Diffusion WebUI Forge全平台快速部署终极指南 【免费下载链接】stable-diffusion-webui-forge 项目地址: https://gitcode.com/GitHub_Trending/st/stable-diffusion-webui-forge 你是否曾在不同操作系统间挣扎于AI绘画工具的安装配置?Stable Diffu…

张小明 2026/1/7 17:33:27 网站建设

雄安智能网站建设方案php用户管理系统

GPT-SoVITS语音克隆安全性探讨:隐私保护如何实现? 在智能语音助手、虚拟主播和个性化有声内容日益普及的今天,用户对“像人”的语音合成需求不断攀升。而真正让人眼前一亮的,并不是那些千篇一律的标准播音腔,而是能精准…

张小明 2026/1/7 19:49:42 网站建设

电脑上如何做网站宣传会员制网站建设教程

Midscene.js企业级部署:从零构建自动化测试生态体系 【免费下载链接】midscene Let AI be your browser operator. 项目地址: https://gitcode.com/GitHub_Trending/mid/midscene 🎯 还在为多环境自动化测试发愁吗? 随着企业数字化进程…

张小明 2026/1/7 20:48:11 网站建设

做网站买什么空间高并发系统架构

使用ComfyUI进行风格迁移:跨艺术流派生成实验 在数字艺术创作的前沿,一个看似简单的问题却长期困扰着创作者:如何让AI真正“理解”梵高的笔触、莫奈的光影,而不是仅仅贴上一个模糊的“印象派”标签?传统文本到图像模型…

张小明 2026/1/7 15:56:26 网站建设

有效的网站推广方式深圳专业专业网站建设公司

桌面版脑图完整使用教程:跨平台思维导图解决方案 【免费下载链接】DesktopNaotu 桌面版脑图 (百度脑图离线版,思维导图) 跨平台支持 Windows/Linux/Mac OS. (A cross-platform multilingual Mind Map Tool) 项目地址: https://gitcode.com/gh_mirrors/…

张小明 2026/1/7 22:55:06 网站建设