关于秒杀:抢购业务的技术方案

总体架构计划网络拦挡: DNS优化, SLB负载平衡,网关封IP限速 业务拦挡: ID限速, 验证码, 只排汇后面N个申请,前面的全回绝; Redis拦挡: 库存不超发,保障限购 接口拦挡: 尽量减少业务查看,判断黑名单 MQ+MYSQL: 异步解决落库状况; Redis List计划 + Incrby计划从缓存读取出流动信息判断流动开始工夫和完结工夫redis内无库存就间接返回无库存,流动完结读取 UID+流动ID的 参加次数 达到限度就返回限度应用Incrby 写入 UID+流动ID的 参加次数,判断返回的次数是否超过限购次数,超过则返回限度写入DB(或者用MQ推送给DB削峰落库)第四点尽管redis是单线程的,然而客户端是多个的,所以第四点的读取和第五点的应用,两个不能同时具备原子性, 必须以 incrby后果为准; 比方一人限购一个,就算某用户第二个申请进来了,把 UID+流动ID 的值 incrby 为2 ,那么这个人返回的也是 “一人只能够购买一个”,对于业务无损; 如果呈现Redis解体或者Mysql解体等异常情况,期待服务复原后, 能够间接从DB外面的购买记录和库存信息简略同步到redis外面,无需开发人员进行过多操作 Redis List计划反对库存编号模型,如果所有的SKU自身无编号意义或者发货才确定库存,能够应用 Incrby管制库存 + Incrby 管制集体限购数量

May 30, 2022 · 1 min · jiezi

关于秒杀:解密秒杀系统架构不是所有的系统都能做秒杀

摘要:教你如何设计一个秒杀零碎架构:从电商零碎架构到秒杀零碎、从高并发“黑科技”与致胜奇招到服务器硬件优化,全方位平面把握秒杀零碎架构!!本文分享自华为云社区《实际出真知:全网最强秒杀零碎架构解密,不是所有的秒杀都是秒杀!!》,作者: 冰 河。 电商零碎架构在电商畛域,存在着典型的秒杀业务场景,那何谓秒杀场景呢。简略的来说就是一件商品的购买人数远远大于这件商品的库存,而且这件商品在很短的工夫内就会被抢购一空。 比方每年的618、双11大促,小米新品促销等业务场景,就是典型的秒杀业务场景。 咱们能够将电商零碎的架构简化成下图所示。 由图所示,咱们能够简略的将电商零碎的核心层分为:负载平衡层、应用层和长久层。接下来,咱们就预估下每一层的并发量。 • 如果负载平衡层应用的是高性能的Nginx,则咱们能够预估Nginx最大的并发度为:10W+,这里是以万为单位。• 假如应用层咱们应用的是Tomcat,而Tomcat的最大并发度能够预估为800左右,这里是以百为单位。• 假如长久层的缓存应用的是Redis,数据库应用的是MySQL,MySQL的最大并发度能够预估为1000左右,以千为单位。Redis的最大并发度能够预估为5W左右,以万为单位。 所以,负载平衡层、应用层和长久层各自的并发度是不同的,那么,为了晋升零碎的总体并发度和缓存,咱们通常能够采取哪些计划呢? (1)零碎扩容 零碎扩容包含垂直扩容和程度扩容,减少设施和机器配置,绝大多数的场景无效。 (2)缓存 本地缓存或者集中式缓存,缩小网络IO,基于内存读取数据。大部分场景无效。 (3)读写拆散 采纳读写拆散,分而治之,减少机器的并行处理能力。 秒杀零碎的特点对于秒杀零碎来说,咱们能够从业务和技术两个角度来论述其本身存在的一些特点。 秒杀零碎的业务特点这里,咱们能够应用12306网站来举例,每年春运时,12306网站的访问量是十分大的,然而网站平时的访问量却是比拟平缓的,也就是说,每年春运季节,12306网站的访问量会呈现刹时突增的景象。 再比方,小米秒杀零碎,在上午10点开售商品,10点前的访问量比拟平缓,10点时同样会呈现并发量刹时突增的景象。 所以,秒杀零碎的流量和并发量咱们能够应用下图来示意。 由图能够看出,秒杀零碎的并发量存在刹时凸峰的特点,也叫做流量突刺景象。 咱们能够将秒杀零碎的特点总结如下。 (1)限时、限量、限价 在规定的工夫内进行;秒杀流动中商品的数量无限;商品的价格会远远低于原来的价格,也就是说,在秒杀流动中,商品会以远远低于原来的价格发售。 例如,秒杀流动的工夫仅限于某天上午10点到10点半,商品数量只有10万件,售完为止,而且商品的价格非常低,例如:1元购等业务场景。 限时、限量和限价能够独自存在,也能够组合存在。 (2)流动预热 须要提前配置流动;流动还未开始时,用户能够查看流动的相干信息;秒杀流动开始前,对流动进行鼎力宣传。 (3)持续时间短 购买的人数数量宏大;商品会迅速售完。 在零碎流量出现上,就会呈现一个突刺景象,此时的并发访问量是十分高的,大部分秒杀场景下,商品会在极短的工夫内售完。 秒杀零碎的技术特点咱们能够将秒杀零碎的技术特点总结如下。 (1)刹时并发量十分高 大量用户会在同一时间抢购商品;霎时并发峰值十分高。 (2)读多写少 零碎中商品页的访问量微小;商品的可购买数量非常少;库存的查问拜访数量远远大于商品的购买数量。 在商品页中往往会退出一些限流措施,例如晚期的秒杀零碎商品页会退出验证码来平滑前端对系统的拜访流量,近期的秒杀零碎商品详情页会在用户关上页面时,提醒用户登录零碎。这都是对系统的拜访进行限流的一些措施。 (3)流程简略 秒杀零碎的业务流程个别比较简单;总体上来说,秒杀零碎的业务流程能够概括为:下单减库存。 秒杀三阶段通常,从秒杀开始到完结,往往会经验三个阶段: • 筹备阶段:这个阶段也叫作零碎预热阶段,此时会提前预热秒杀零碎的业务数据,往往这个时候,用户会一直刷新秒杀页面,来查看秒杀流动是否曾经开始。在肯定水平上,通过用户一直刷新页面的操作,能够将一些数据存储到Redis中进行预热。• 秒杀阶段:这个阶段次要是秒杀流动的过程,会产生刹时的高并发流量,对系统资源会造成微小的冲击,所以,在秒杀阶段肯定要做好零碎防护。• 结算阶段: 实现秒杀后的数据处理工作,比方数据的一致性问题解决,异常情况解决,商品的回仓解决等。 针对这种短时间内大流量的零碎来说,就不太适宜应用零碎扩容了,因为即便零碎扩容了,也就是在很短的工夫内会应用到扩容后的零碎,大部分工夫内,零碎无需扩容即可失常拜访。 那么,咱们能够采取哪些计划来晋升零碎的秒杀性能呢? 秒杀零碎计划针对秒杀零碎的特点,咱们能够采取如下的措施来晋升零碎的性能。 (1)异步解耦 将整体流程进行拆解,外围流程通过队列形式进行管制。 (2)限流防刷 管制网站整体流量,进步申请的门槛,防止系统资源耗尽。 (3)资源管制 将整体流程中的资源调度进行管制,取长补短。 因为应用层可能承载的并发量比缓存的并发量少很多。所以,在高并发零碎中,咱们能够间接应用OpenResty由负载平衡层拜访缓存,防止了调用应用层的性能损耗。大家能够到https://openresty.org/cn/来理解无关OpenResty更多的常识。同时,因为秒杀零碎中,商品数量比拟少,咱们也能够应用动静渲染技术,CDN技术来减速网站的拜访性能。 如果在秒杀流动开始时,并发量太高时,咱们能够将用户的申请放入队列中进行解决,并为用户弹出排队页面。 注:图片来自魅族 秒杀零碎时序图网上很多的秒杀零碎和对秒杀零碎的解决方案,并不是真正的秒杀零碎,他们采纳的只是同步解决申请的计划,一旦并发量真的上来了,他们所谓的秒杀零碎的性能会急剧下降。咱们先来看一下秒杀零碎在同步下单时的时序图。 同步下单流程 1.用户发动秒杀申请在同步下单流程中,首先,用户发动秒杀申请。商城服务须要顺次执行如下流程来解决秒杀申请的业务。 (1)辨认验证码是否正确 商城服务判断用户发动秒杀申请时提交的验证码是否正确。 (2)判断流动是否曾经完结 验证以后秒杀流动是否曾经完结。 (3)验证拜访申请是否处于黑名单 在电商畛域中,存在着很多的歹意竞争,也就是说,其余商家可能会通过不正当伎俩来歹意申请秒杀零碎,占用零碎大量的带宽和其余系统资源。此时,就须要应用风控系统等实现黑名单机制。为了简略,也能够应用拦截器统计拜访频次实现黑名单机制。 (4)验证实在库存是否足够 ...

September 27, 2021 · 2 min · jiezi

秒杀系统技术解剖

我们知道秒杀类的活动对整个运营贡献是最大的,它的特点是瞬间流量俱增、请求数量远大于库存,导致保证下单扣库存准确性难度大,那我们前端、后端怎么做才能保证呢?下面是我的一些思考。 先来说说整体的设计理念,秒杀类的活动光靠水平扩展扩增机器只能是个备选方案,它的成本和收益不对等。那我们就应该尽量利用有效的资源最大化处理业务,可从限流、异步处理、内存缓存角度考虑。 接下来说说具体的落地方案。秒杀类的活动前端一般会展示商品描述、秒杀价格、已售比例、时间提示,这些内容基本上是不变的,那我们可以通过内容分发CDN机制来将页面静态化,减少动态元素。前端还需要减少用户提交次数,用户提交之后按钮置灰,禁止重复提交,但是别忘记了还有刷子这个灰色产业链,所以后端还需要做一些限制。 在后端的服务控制层针对同一访问UID,限制请求频率。或者先把请教都写到消息队列中缓存一下,逻辑层订阅消息减库存,减库存成功的请求返回秒杀成功,失败的返回秒杀结束。甚至,我们可以利用缓存来应对读写请求,首先把库存信息同步到Redis缓存中,所以的减库存操作都Redis中进行,然后同步到数据库中。实际上,这些还远远不够,我们还需要考虑以下场景。 场景一是同一个账号,一次性发出多个请求。我们可以利用Redis内容缓存来判断用户是否已参加过了活动,写入一个标志位,结合乐观锁特性约束只允许一个请求写成功,成功写入的也就是没有记录的才能继续参加。 场景二是多个账号,一次性发送多个请求。针对这种场景,我们通过检测指定机器IP请求频率可以解决,如果发现某个请求IP请求频率过高,可以给它弹出一个验证码或者直接禁止它的请求。 场景三是多个账号,不同IP发送不同的请求。这种场景下的请求,和真实用户行为基本相同,想做分辨很难,需要通过账号数据进行数据挖掘后打标,结合是否经常抢票、退票等等标识为风控用户。 其实秒杀类的活动最大的挑战是如何保证高并发下的数据安全和防刷,这是一个矛与盾的博弈。总结一下今天的文章重点,针对秒杀系统,尽量将请求拦截在系统上游,越上游越好,另外读多写少的多使用缓存。好,今天的分享就到这里,欢迎分享给你的朋友。 文章来源:www.liangsonghua.me 作者介绍:京东资深工程师-梁松华,在稳定性保障、敏捷开发、JAVA高级、微服务架构方面有深入的理解

August 19, 2019 · 1 min · jiezi

支撑马蜂窝会员体系全面升级背后的架构设计

流量红利正逐渐走向终结,这已经不再是什么秘密。后互联网时代,如何维系住用户群,提升用户在平台上的体验是整个行业都需要考虑的事情。正是出于这一原因,现在全行业都在关注会员体系的搭建,这也是马蜂窝 2019 年重点投入的方向之一。  面对这个全行业都在发力的会员市场,要对「马蜂窝特色」的会员体系进行有力的支撑,无疑对会员体系的架构设计提出更高的要求。 马蜂窝会员体系建设从 2018 年 9 月份开始启动,经过前期对会员身份和会员权益的摸索,伴随业务的快速发展,到 2019 年上半年,为了让更多用户体验到马蜂窝高质量的会员服务,公司推出了更灵活、维度更多、权益更丰富的会员模式。在这样的背景下,初期较为粗旷的底层技术也需要及时做出调整,对核心架构和服务进行升级。 一、会员身份策略改造早期的会员身份模块由会员产品、用户属性和时间属性共同构成: 可以看到早期的会员产品比较单一,因此将产品信息设计成一级结构。这种设计的好处是逻辑简单,可以快速实现,但不易扩展,一旦新增会员类别以及不同卡种之间出现复杂关系时,不论是对项目或者对代码本身而言,维护成本都将成倍增长。 从 2019 年年初开始,马蜂窝会员体系进行了全面升级,主要体现在以下几个方面: 更完善的获客渠道,增加了在小程序端的服务展示;更丰富的会员类别,新增了非常多卡种,在最初的年度金卡和体验金卡基础上,增加了季度金卡、 7 日卡、「蜂享卡」,未来还计划推出月度金卡、学生卡等;更低的获取门槛,早期的会员身份只能通过在 App 中购买获得,为了让更多用户享受到品质更高的服务,增加了通过完成用户激励任务、供应商合作、产品搭售、线下实体卡等会员获取方式。这也意味着,同一时间段内用户的会员身份将变得愈发复杂,早期单一的会员身份策略和模型设计已经不能满足需求。重新设计会员身份的时候,我们明确了未来无论业务线如何划分会员身份,底层结构都要能够较好地支持,因此决定把会员模块身份抽离出来。会员体系升级后,产品信息调整为以 SKU 作为最小粒度重新划分,同时增加了用户信息中的来源以及获取渠道信息: 二、会员中心架构设计和优化在明确了新的会员身份策略后,我们对整个会员体系进行了梳理,将现阶段的会员中心架构设计如下: 合上面的架构图来看,目前马蜂窝会员中心系统主要划分为数据存储、核心服务、接口层、应用层四大部分: 数据储存:主要基于 MySQL 和 Redis,以及马蜂窝统一日志系统 MES核心服务:这是当前马蜂窝会员体系中最重要的一层。核心服务又可以分为三大块:(1)「四驾马车」:会员身份、权益、增值服务接入、会员积分,驱动着整个会员体系的运转; (2)交易营销:辅助四驾马车快速往前跑; (3)支撑模块:与会员体系对接的公司级别支撑模块,包括风控、监控、日志、消息总线、商家结算对账等 接口层:会员体系对外暴露的接口,包括了会员身份、权益领取、蜂蜜消费等接口应用层:主要是面向 C 端的应用,包括会员频道页、蜂蜜中心、用户权益中心、任务中心等下面重点围绕「核心服务」层展开介绍。 2.1「四驾马车」2.1.1 会员身份目前,市面上很多常见的会员产品都是采用普通的续费模式,比如一些视频平台的年度会员、季度会员。这种模式的特点是只进行时间的区分,在会员身份后生效后享受的权益完全相同,通过续费使权益时效得到相应延长。 但是马蜂窝由于业务的特殊性,会员体系需要设计得更为立体。如果只采用单纯的续费模式,会影响高忠诚度用户的使用体验。 首先,在同一类别的会员身份下,时长不同的产品对应的权益也不同。以金卡会员为例,季度金卡、年度金卡这种同类别下的会员身份,可以通过续费升级,但它们彼拥有的权益不完全相同,比如年度金卡 96 折抵额上限为 500 元,季度金卡只有 100 元。另外,同一用户在同一时间内,只要满足条件,就可同时拥有不同类别的卡种,比如金卡和蜂享卡。为了满足上述需求,我们决定引入用户身份的叠加以及续费模型。通过增加会员 SKU 叠加、续费关系表,使用户在一个时间段内不仅可以同时拥有多种身份,还可以续费已有卡种。 上图是会员身份的时间轴示意。横轴代表时间,纵轴代表不同的卡种。我们通过最终 SKU 时间轴便可以确认用户当前的会员身份。 我们将用户已有的每个 SKU 时间轴拉平,当用户在某个时间点发出购买新卡种的请求时,查看当前生效的时间轴中是否已有用户正在购买的 SPU,如果没有则叠加,如已有则需要再判断 SKU 之间的配置策略,决定是叠加还是续费;然后继续计算出正在购买的 SKU 生效时间轴;接下来根据配置好的规则,对比当前购买生效时间轴和已有 SKU 时间轴的身份关系,决定用户是否可以完成此次购买,如: 前置身份:指必须已经购买某个 SKU,才可以购买当前 SKU冲突身份:指如果已经购买某个 SKU,就不可以购买当前 SKU为了满足不同的业务需求,这里的叠加、续费关系都是可以通过运营来配置的。整个流程大致示意如下: ...

July 26, 2019 · 1 min · jiezi

php和redis设计秒杀活动

1 说明前段时间面试的时候,一直被问到如何设计一个秒杀活动,但是无奈没有此方面的实际经验,所以只好凭着自己的理解和一些资料去设计这么一个程序主要利用到了redis的string和set,string主要是利用它的k-v结构去对库存进行处理,也可以用list的数据结构来处理商品的库存,set则用来确保用户进行重复的提交其中我们最主要解决的问题是-防止并发产生超抢/超卖 2 流程设计 3 代码3.1 服务端代码class MiaoSha{ const MSG_REPEAT_USER = '请勿重复参与'; const MSG_EMPTY_STOCK = '库存不足'; const MSG_KEY_NOT_EXIST = 'key不存在'; const IP_POOL = 'ip_pool'; const USER_POOL = 'user_pool'; /** @var Redis */ public $redis; public $key; public function __construct($key = '') { $this->checkKey($key); $this->redis = new Redis(); //todo 连接池 $this->redis->connect('127.0.0.1'); } public function checkKey($key = '') { if(!$key) { throw new Exception(self::MSG_KEY_NOT_EXIST); } else { $this->key = $key; } } public function setStock($value = 0) { if($this->redis->exists($this->key) == 0) { $this->redis->set($this->key,$value); } } public function checkIp($ip = 0) { $sKey = $this->key . self::IP_POOL; if(!$ip || $this->redis->sIsMember($sKey,$ip)) { throw new Exception(self::MSG_REPEAT_USER); } } public function checkUser($user = 0) { $sKey = $this->key . self::USER_POOL; if(!$user || $this->redis->sIsMember($sKey,$user)) { throw new Exception(self::MSG_REPEAT_USER); } } public function checkStock($user = 0, $ip = 0) { $num = $this->redis->decr($this->key); if($num < 0 ) { throw new Exception(self::MSG_EMPTY_STOCK); } else { $this->redis->sAdd($this->key . self::USER_POOL, $user); $this->redis->sAdd($this->key . self::IP_POOL, $ip); //todo add to mysql echo 'success' . PHP_EOL; error_log('success' . $user . PHP_EOL,3,'/var/www/html/demo/log/debug.log'); } } /** * @note:此种做法不能防止并发 * @func checkStockFail * @param int $user * @param int $ip * @throws Exception */ public function checkStockFail($user = 0,$ip = 0) { $num = $this->redis->get($this->key); if($num > 0 ){ $this->redis->sAdd($this->key . self::USER_POOL, $user); $this->redis->sAdd($this->key . self::IP_POOL, $ip); //todo add to mysql echo 'success' . PHP_EOL; error_log('success' . $user . PHP_EOL,3,'/var/www/html/demo/log/debug.log'); $num--; $this->redis->set($this->key,$num); } else { throw new Exception(self::MSG_EMPTY_STOCK); } }}3.2 客户端测试代码function test(){ try{ $key = 'cup_'; $handler = new MiaoSha($key); $handler->setStock(10); $user = rand(1,10000); $ip = $user; $handler->checkIp($ip); $handler->checkUser($user); $handler->checkStock($user,$ip); } catch (\Exception $e) { echo $e->getMessage() . PHP_EOL; error_log('fail' . $e->getMessage() .PHP_EOL,3,'/var/www/html/demo/log/debug.log'); }}function test2(){ try{ $key = 'cup_'; $handler = new MiaoSha($key); $handler->setStock(10); $user = rand(1,10000); $ip = $user; $handler->checkIp($ip); $handler->checkUser($user); $handler->checkStockFail($user,$ip); //不能防止并发的 } catch (\Exception $e) { echo $e->getMessage() . PHP_EOL; error_log('fail' . $e->getMessage() .PHP_EOL,3,'/var/www/html/demo/log/debug.log'); }}4 测试测试环境说明 ...

July 16, 2019 · 2 min · jiezi

Java秒杀系统实战系列整体业务流程介绍与数据库设计

摘要: 本篇博文是“Java秒杀系统实战系列文章”的第三篇,本篇博文将主要介绍秒杀系统的整体业务流程,并根据相应的业务流程进行数据库设计,最终采用Mybatis逆向工程生成相应的实体类Entity、操作Sql的接口Mapper以及写动态Sql的配置文件Mapper.xml。 内容: 对于该秒杀系统的整体业务流程,相信机灵的小伙伴在看完第二篇博文的时候,就已经知道个大概了!因为在提供的源码数据库下载的链接中,Debug已经跟各位小伙伴介绍了该秒杀系统整体的业务流程,而且还以视频形式给各位小伙伴进行了展示!该源码数据库的下载链接如下:https://gitee.com/steadyjack/...  在本篇博文中Debug将继续花一点篇幅介绍介绍! 一图以概之,如下图所示为该秒杀系统整体的业务流程: 从该业务流程图中,可以看出,后端接口在接收前端的秒杀请求时,其核心处理逻辑为: (1)首先判断当前用户是否已经抢购过该商品了,如果否,则代表用户没有抢购过该商品,可以进入下一步的处理逻辑 (2)判断该商品可抢的剩余数量,即库存是否充足(即是否大于0),如果是,则进入下一步的处理逻辑 (3)扣减库存,并更新数据库的中对应抢购记录的库存(一般是减一操作),判断更新库存的数据库操作是否成功了,如果是,则创建用户秒杀成功的订单,并异步发送短信或者邮件通知信息通知用户 (4)以上的操作逻辑如果有任何一步是不满足条件的,则直接结束整个秒杀的流程,即秒杀失败! 如下图所示为后端处理“秒杀请求”时的核心处理逻辑: 综合这两个业务流程,下面进入“秒杀系统”的数据库设计环节,其中,主要包含以下几个表:商品信息表item、待秒杀信息表item_kill、秒杀成功记录表item_kill_success以及用户信息表user;当然,在实际的大型网站中,其所包含的数据库表远远不止于此!本系统暂且浓缩出其中核心的几张表! 如下图所示为该“秒杀系统”的数据库设计模型: 紧接着,是采用Mybatis的逆向工程生成这几个数据库表对应的实体类Entity、操作Sql的接口Mapper以及写动态Sql的配置文件Mapper.xml。如下图所示: 下面,贴出其中一个实体类以及相对应的Mapper接口和Mapper.xml代码,其他的,各位小伙伴可以点击链接:https://gitee.com/steadyjack/... 前往下载查看!首先是实体类ItemKill的源代码: import com.fasterxml.jackson.annotation.JsonFormat;import lombok.Data;import java.util.Date;@Datapublic class ItemKill { private Integer id; private Integer itemId; private Integer total; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date startTime; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date endTime; private Byte isActive; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date createTime; private String itemName; //采用服务器时间控制是否可以进行抢购 private Integer canKill;}然后是ItemKillMapper接口的源代码: ...

July 16, 2019 · 2 min · jiezi

Java秒杀系统实战系列构建SpringBoot多模块项目

摘要:本篇博文是“Java秒杀系统实战系列文章”的第二篇,主要分享介绍如何采用IDEA,基于SpringBoot+SpringMVC+Mybatis+分布式中间件构建一个多模块的项目,即“秒杀系统”!。 内容:传统的基于IDEA构建SpringBoot的项目,是直接借助Spring Initializr插件进行构建,但是这种方式在大部分情况下,只能充当“单模块”的项目,并不能很好的做到“分工明确、职责清晰”的分层原则! 故而为了能更好的管理项目代码以及尽量做到“模块如名”,快速定位给定的类文件或者其他文件的位置,下面我们将基于IDEA、借助Maven构建多模块的项目,其中,其构建的思路如下图所示: ![图片上传中...] 详细的构建过程在本文就不赘述了!文末有提供源码的地址以及构建过程的视频教程!下面重点介绍一下跟“Java秒杀系统”相关的构建步骤。 (1)如下图所示为最终构建成功的项目的整体目录结构: 从该目录结构中可以看出,该项目为一个“聚合型项目”,其中,model模块依赖api模块,server模块依赖model模块,层层依赖!最终在server模块实现“大汇总”,即server模块为整个项目的核心关键所在,像什么“配置文件”、“入口启动类”啥的都在这个模块中! 而且,各个模块的职责是不一样的,分工也很明确,就像model模块,一般人看了就知道这里放的东西应该是跟mybatis或者跟数据库mysql相关的类文件与配置文件等等。 构建好相应的模块之后,就需要往相应的模块添加依赖,即只需要在pom.xml中加入相应的依赖即可,在这里就不贴出来了!(2)在这里主要贴一下server模块入口启动类MainApplication的代码,如下所示: @SpringBootApplication@ImportResource(value = {"classpath:spring/spring-jdbc.xml"})@MapperScan(basePackages = "com.debug.kill.model.mapper")@EnableSchedulingpublic class MainApplication extends SpringBootServletInitializer{ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(MainApplication.class); } public static void main(String[] args) { SpringApplication.run(MainApplication.class,args); }}其中,该启动类将加载配置文件spring-jdbc.xml(数据库链接信息的配置文件)! 构建完成之后,可以将整个项目采用外置的Tomcat跑起来,运行过程中,观察控制台Console的输出信息,如果没有报错信息,则代表整个项目的搭建是没有问题的!如果出现了问题,建议自己先研究一番并尝试去解决掉!如果仍旧不能解决,可以加文末提供的联系方式进行解决! (4)除此之外,为了让整个项目在前后端分离开发的情况下,前后端的接口交互更加规范(比如响应信息的规范等等),在这里我们采用了通用的一个状态码枚举类StatusCode 跟 一个通用的响应结果类BaseResponse,用于后端在返回响应信息给到前端时进行统一封装。 状态码枚举类StatusCode的源代码如下所示: public enum StatusCode { Success(0,"成功"), Fail(-1,"失败"), InvalidParams(201,"非法的参数!"), UserNotLogin(202,"用户没登录"), ; private Integer code; //状态码code private String msg; //状态码描述信息msg StatusCode(Integer code, String msg) { this.code = code; this.msg = msg; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; }}响应结果类BaseResponse的源代码如下所示: ...

July 16, 2019 · 2 min · jiezi