Java生鲜电商平台-RBAC系统权限的设计与架构
Java生鲜电商平台-RBAC系统权限的设计与架构
说明:根据上面的需求描述以及对需求的分析,我们得知通常的一个中小型系统对于权限系统所需实现的功能以及非功能性的需求,在下面我们将根据需求从技术角度上分析实现的策略以及基于目前两种比较流行的权限设计思想来讨论关于权限系统的实现。
1.1. 技术策略
l 身份认证
在B/S的系统中,为识别用户身份,通常使用的技术策略为将用户的身份记录在Session中,也就是当用户登录时即获取用户的身份信息,并将其记录到Session里,当需要进行身份认证的时候通过从Session中获取用户的身份信息来实现用户的身份认证。
l 资源权限校验
资源权限校验取决于系统的授权模型,这块将在之后进行详细的阐述。
l 数据权限校验
数据权限校验取决于系统的授权模型,这块将在之后进行详细的阐述。
l 授权模型
授权模型作为权限系统的核心,从本质上决定了权限系统的易用性,这个易用性包括权限的授予和权限的校验,并同时也决定了权限的继承,权限的排斥和包含等方面的实现。
在经历了这么多年的发展,授权模型在目前中小型应用系统接受的比较多的主要有RBAC模型和ACL模型,将在之后展开专门的篇幅进行讲解。
l 权限校验的体现
权限校验的体现在中小型系统中体现出来的通常只是对于系统菜单、按钮显示的控制和对于拥有权限的数据的访问上。
它们共同依赖于资源权限校验和数据权限校验,对于系统菜单、按钮的显示上的控制在B/S中通常采用的技术策略为在生成菜单、按钮的Html时做权限级的判断,当操作主体不具备权限时则不生成该菜单、按钮的Html,从技术角度分析为方便使用者,避免使用者调用权限校验接口,通常的做法为提供菜单、按钮的标签,通过此标签生成的菜单和按钮即为经过权限过滤的。
l 高性能
为提高权限系统在授权以及校验权限时的性能,通常的做法为采用缓存技术以及加强权限系统的管理建设,加强权限系统的管理建设有助于建立一个最为适合需求的权限结构,同时做到了简化系统权限授予。
l 安全性
安全性方面来讲在B/S系统中通常有两个方面需要控制:
n 通过非法途径访问系统文件
在Java的Web应用中通常采用的技术策略为将需要受保护的文件放入WEB-INF文件夹中,大家都知道在WEB-INF下的文件除了在服务器上能直接访问外,通过普通的URL是无法访问到的。
其次的做法为做Filter,即对需要受保护的资源做访问的Filter,如操作者不具备权限则直接报出错误。
n 通过非法途径访问系统操作
通常采用的技术策略为对每个直接暴露对外的需要受权限保护的对象做操作级别的权限控制,简单来说在Web系统中通常采用MVC框架来实现,通常Command层是直接对外的,为防止用户通过URL或其他方式访问Command,从技术上我们需要考虑对现有系统的尽量少的侵入性,所以通常采用的做法是在Command之上做Before Interceptor或Proxy,在此Interceptor或Proxy中做权限的校验,以确认操作者具有相应的权限。
经过上面的描述,我们已经基本了解到满足权限系统需求的技术实现策略,从中我们也可以看出权限系统中最为重要的为授权模型,由于权限系统的通用性,在业界也是推出了不少的授权模型,在这里我们已目前比较通用的两种授权模型来具体讲解权限系统的完整实现。
1.2. 基于RBAC的实现
1.2.1. RBAC介绍
RBAC模型作为目前最为广泛接受的权限模型,在此也将对其模型进行简要的介绍,RBAC模型成功的经典应用案例当属Unix系统了。
NIST(The National Institute of Standards and Technology,美国国家标准与技术研究院)标准RBAC模型由4个部件模型组成,这4个部件模型分别是基本模型RBAC0(Core RBAC)、角色分级模型RBAC1(Hierarchal RBAC)、角色限制模型RBAC2(Constraint RBAC)和统一模型RBAC3(Combines RBAC)[1]。RBAC0模型如图1所示。
图表 1 RBAC 0模型
l RBAC0定义了能构成一个RBAC控制系统的最小的元素集合
在RBAC之中,包含用户users(USERS)、角色roles(ROLES)、目标objects(OBS)、操作operations(OPS)、许可权permissions(PRMS)五个基本数据元素,权限被赋予角色,而不是用户,当一个角色被指定给一个用户时,此用户就拥有了该角色所包含的权限。会话sessions是用户与激活的角色集合之间的映射。RBAC0与传统访问控制的差别在于增加一层间接性带来了灵活性,RBAC1、RBAC2、RBAC3都是先后在RBAC0上的扩展。
l RBAC1引入角色间的继承关系
角色间的继承关系可分为一般继承关系和受限继承关系。一般继承关系仅要求角色继承关系是一个绝对偏序关系,允许角色间的多继承。而受限继承关系则进一步要求角色继承关系是一个树结构。
l RBAC2模型中添加了责任分离关系
RBAC2的约束规定了权限被赋予角色时,或角色被赋予用户时,以及当用户在某一时刻激活一个角色时所应遵循的强制性规则。责任分离包括静态责任分离和动态责任分离。约束与用户-角色-权限关系一起决定了RBAC2模型中用户的访问许可。
l RBAC3包含了RBAC1和RBAC2
既提供了角色间的继承关系,又提供了责任分离关系。
1.2.2. 实现方案
通过上面章节对RBAC的介绍,从RBAC模型中我们可以看出它已经实现了一个使用起来很方便的授权模型,并同时也就权限的继承,权限的排斥和包含提出了解决的模型。
那么现在的关键是我们需要来看看基于RBAC到底是怎么实现权限系统的需求的呢?在这里我们针对在技术策略中未描述的授权模型和权限校验部分做实现方案的讲解。
l 授权模型
授权模型遵循RBAC进行搭建,即建立如上图表一的模型。
针对授权模型中的几个关键部分我们进行描述:
n 授权
按照RBAC的模型,在授权时分为配置资源以及资源的操作、授予角色对资源的操作权限、分配角色给用户这几个步骤来完成。
从这几个步骤我们进行分析:
u 配置资源以及资源的操作
实现这步非常的简单,直接维护资源以及资源操作两个对象的持久即可实现。
u 授予角色对资源的操作权限
实现这步同样非常的简单,维护角色与资源的关联模型即可。
u 分配角色给用户
实现这步同样非常的简单,维护角色与用户的关联模型即可。
n 权限的继承
权限的继承在RBAC的模型中通过增加角色的自关联来实现,即角色可拥有子角色,子角色继承父角色的权限。
按照此模型可以看出在授权时维护权限的继承也是非常的简单,维护角色的自关联模型即可。
n 权限的排斥和包含
权限的排斥和包含这块我没有具体看RBAC的规范,通常的做法是通过在资源的操作权限模型中增加自关联模型以定义哪些资源的操作权限是排斥和包含的,在授权时可以看到同样需要维护的只是资源权限的自关联模型。
l 资源权限校验
根据上面的授权模型,在做资源权限校验的时候需要经过以下步骤:
n 判断用户所在的角色是否拥有对资源进行操作的权限
获取用户所拥有的角色,遍历其角色,以各角色建立Session,并通过类似的role.doPrivilege(Resource,Operation)的方式来判断该角色是否具备权限,如具备则直接返回,如不具备则直到遍历结束。
n 递规用户所在角色的父角色判断是否拥有对资源进行操作的权限
当遍历完用户本身的角色得到用户不具备对资源进行该操作的权限时,则开始递规其所在角色的父角色来判断是否拥有对资源进行操作的权限,过程同上,如确定某角色具备,则返回,如不具备直到递规结束。
l 数据权限校验
在RBAC模型中没有明确定义数据权限的实现策略,鉴于此首先要讲解下基于RBAC模型的数据授权模型的建立,基于RBAC模型,将数据映射为RBAC中的资源,对数据的操作则映射为资源的操作,同样的是将此资源以及资源的操作构成的权限授予给角色,将用户分配给角色完成数据权限的授权过程。
但根据数据权限校验的需求,数据的权限也是需要继承的,而且数据权限的授予对象需要是多种,这样的话就对上面根据RBAC映射形成的数据权限的授权模型造成了冲击,需要重构上面的授权模型来满足需求。
为实现数据权限的继承,需要将RBAC模型中的资源重构为允许自关联的模型,为实现数据权限能够授予给多种对象,需要将本来资源操作权限授予给角色的模型演变为数据操作权限授予给角色、组织机构或具体人员,根据RBAC模型,同样的建立一个中间对象,此对象和数据操作权限所授予的对象做1对多的关联,在经过这样的重构之后数据权限的授权模型就形成了,也满足了数据权限的继承和授予给多种对象的需求。
图表 2 基于RBAC演变的数据权限模型
上面的图中少画了数据的自关联。
根据上面的数据权限模型,来看看数据权限的校验是怎么样去实现呢?
在做数据权限校验的时候我们需要实现的为两种方式,一种是获取操作主体具有数据操作权限的全部数据,另外一种为分页获取操作主体具有数据操作权限的数据。
就这两种方式分别来进行阐述:
n 获取操作主体具有数据操作权限的全部数据
从数据库中获取所有数据,遍历取出的数据从数据权限模型中获取相应的拥有数据操作权限的权限拥有者,如果该数据未配置数据操作权限的控制,那么就无需对该数据进行权限级的判断,如配置了,则需判断当前用户是否在该数据操作权限所对应的拥有者中,如用户不在,则需递规获取该数据的父数据的操作权限的拥有者,到用户拥有权限或递规结束时终止。
n 分页获取操作主体具有数据操作权限的数据
分页的做法和上面差不多,只是在获取了所有的数据后在内存中做分页返回。
1.2.3. 优缺点分析
从上面的基于RBAC的实现方案中可以看出基于RBAC模型的优点在于:
l 易用和高效的授权方式
用户在进行授权时只需对角色进行授权,之后将相应的角色分配给用户即可。
l 简便和高效的授权模型维护
在技术角度来讲,进行授权模型的维护上因为基本只需要维护关联模型而显得简单而高效。
缺点在于:
l 复杂的权限校验
在进行权限校验时需要不断的遍历和递规,造成了性能的影响。
l 对于数据权限的不够支持
没有明确的数据权限模型,可以看到在经过重构的数据权限模型其实已经和RBAC模型有一定的
出入,而且在数据权限的校验上实现起来是非常的低效。
最终根据说明,设计如下系统架构图:

一、设计规则定义
1. 数据库表明定义规则:t_ 模块名_表名
二、权限管理系统系统设计
1. 用户管理(t_sys_userInfo)
|
数据项 |
字段名称 |
数据定义 |
必输项 |
检查规则 |
|
userId |
用户ID |
Varchar(20) |
系统产生(UUID) |
单表唯一 |
|
userName |
用户名称 |
Varchar(8) |
手工输入 |
不可为空 |
|
userAccount |
用户帐户 |
Varchar(20) |
手工输入 |
全系统唯一 |
|
userMobile |
移动电话 |
Varchar(11) |
可以为空 |
|
|
isAdmin |
管理员标志 |
DECIMAL(1,0) |
系统产生 |
1、超级管理员2、企业管理员3用户 |
|
lockFlag |
帐号锁定标志 |
DECIMAL(1,0) |
系统产生 |
是否锁定 1、锁住 0、未锁住 锁定后的用户不能登录系统 |
|
departId |
所属部门ID |
Varchar(20) |
手动选择 |
来源t_sys_org表(orgId) |
|
departName |
部门名称 |
Varchar(30) |
系统产生 |
|
|
orgId |
企业ID |
Varchar(20) |
系统产生 |
来源t_sys_org表(orgId) |
|
orgName |
企业名称 |
Varchar(30) |
系统产生 |
来源t_sys_org表(orgName) |
|
createBy |
创建人ID |
Varchar(20) |
系统产生 |
|
|
createName |
创建人名称 |
Varchar(30) |
系统产生 |
|
|
createTime |
创建时间 |
DATETIME |
系统产生 |
|
|
updateBy |
更新人ID |
Varchar(20) |
系统产生 |
|
|
updateName |
更新人名称 |
Varchar(30) |
系统产生 |
|
|
lastUpdateTime |
更新时间 |
DATETIME |
系统产生 |
|
CREATE TABLE `t_sys_userInfo` (
`userId` VARCHAR(20) NOT NULL COMMENT '用户主键',
`userName` VARCHAR(20) NOT NULL,
`orgId` VARCHAR(20) NOT NULL COMMENT '所属机构ID',
`orgName` VARCHAR(50) NOT NULL COMMENT '所属机构名称',
`orgPath` VARCHAR(120) NOT NULL COMMENT '所属机构路径',
`userAccount` VARCHAR(16) NOT NULL COMMENT '登录帐号',
`userPwd` VARCHAR(16) NOT NULL COMMENT '登录密码',
`userMobile` VARCHAR(11) NULL DEFAULT NULL COMMENT '移动电话',
`isAdmin` DECIMAL(1,0) NOT NULL DEFAULT '3' COMMENT '1、超级管理员2、企业管理员3用户',
`lockFlag` DECIMAL(1,0) NOT NULL COMMENT '是否锁住 1、锁住 0、未锁住',
`departId` VARCHAR(20) NOT NULL COMMENT '所属部门',
`createBy` VARCHAR(20) NOT NULL,
`createName` VARCHAR(50) NOT NULL COMMENT '创建人',
`createTime` DATETIME NOT NULL COMMENT '创建时间',
`lastUpdateBy` VARCHAR(32) NOT NULL COMMENT '最后修改人ID',
`updateName` VARCHAR(50) NOT NULL COMMENT '最后修改人',
`lastUpdateTime` DATETIME NOT NULL COMMENT '最后修改时间',
PRIMARY KEY (`userId`)
)
COMMENT='用户信息表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
2. 资源管理(t_sys_resInfo)
|
数据项 |
字段名称 |
数据定义 |
必输项 |
检查规则 |
|
resId |
用户ID |
Varchar(20) |
系统产生(UUID) |
单表唯一 |
|
resName |
用户名称 |
Varchar(20) |
手工输入 |
不可为空 |
|
parentId |
用户帐户 |
Varchar(20) |
手工输入 |
来源t_sys_resInfo表(resId) |
|
parentName |
移动电话 |
Varchar(20) |
可以为空 |
来源t_sys_resInfo表(resName) |
|
resType |
资源类型 |
DECIMAL(1,0) |
手动选择 |
1、目录2、菜单 3.操作权限 检查规则: 1、目录下面,不能添加操作权限 2、菜单下面不能添加目录 3、以此类推 |
|
resState |
资源状态 |
DECIMAL(1,0) |
手动选择 |
0,不可用 1可用 |
|
resSort |
资源排序字段 |
DECIMAL(1,0) |
系统产生 |
来源t_sys_org表(orgId) |
|
resUrl |
资源访问地址 |
Varchar(30) |
手动输入 |
后期自动产生 |
|
leafCount |
子级菜单数量 |
DECIMAL(1,0) |
系统产生 |
|
|
resPath |
企业名称 |
Varchar(30) |
系统产生 |
来源t_sys_org表(orgName) |
|
iconCls |
创建人ID |
Varchar(32) |
系统产生 |
CREATE TABLE `t_sys_resInfo` (
`resId` VARCHAR(32) NOT NULL COMMENT '主键ID',
`resName` VARCHAR(128) NOT NULL COMMENT '资源名称',
`parentId` VARCHAR(32) NOT NULL COMMENT '资源父节点',
`parentName` VARCHAR(128) NOT NULL COMMENT '资源父节点名称',
`resType` DECIMAL(1,0) NULL DEFAULT '1' COMMENT '1、功能菜单 2、功能点 3、按钮',
`resState` DECIMAL(1,0) NULL DEFAULT '1' COMMENT '记录资源的状态(可用,不可用):0表示不可用,1表示可用',
`resSort` DECIMAL(8,0) NULL DEFAULT '0' COMMENT '资源排序 ',
`resUrl` VARCHAR(512) NULL DEFAULT '' COMMENT '资源URL地址',
`leafCount` DECIMAL(1,0) NULL DEFAULT '0' COMMENT '子节点数量',
`resPath` VARCHAR(2048) NULL DEFAULT '' COMMENT '记录资源节点的路径:当前菜单的上级菜单,上级菜单的父级菜单',
`iconCls` VARCHAR(20) NULL DEFAULT '' COMMENT '资源图标',
PRIMARY KEY (`resId`)
)
COMMENT='系统资源'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
3. 组织机构表(t_sys_org)
CREATE TABLE `t_sys_org` (
`orgId` VARCHAR(20) NOT NULL COMMENT '组织主键',
`orgName` VARCHAR(50) NOT NULL COMMENT '组织名称',
`orgShortName` VARCHAR(30) NULL DEFAULT NULL COMMENT '组织简称',
`parentId` VARCHAR(32) NOT NULL COMMENT '组织父节点ID',
`parentName` VARCHAR(50) NOT NULL COMMENT '父节点编码',
`orgType` DECIMAL(1,0) NOT NULL DEFAULT '1' COMMENT '组织的类型 1、企业 2、部门 3、分公司,4,支行',
`orgStatus` DECIMAL(1,0) NOT NULL DEFAULT '1' COMMENT '记录组织的状态是否启用:0,停用/1,启用',
`orgHisStatus` DECIMAL(1,0) NOT NULL DEFAULT '1' COMMENT '0,停用/1,启用',
`orgLinkMan` VARCHAR(50) NULL DEFAULT NULL COMMENT '机构的法人代表名称',
`orgTelephone` VARCHAR(20) NULL DEFAULT NULL COMMENT '机构的联系电话',
`orgFax` VARCHAR(20) NULL DEFAULT NULL COMMENT '机构的传真',
`orgEmail` VARCHAR(100) NULL DEFAULT NULL COMMENT '机构的电子邮箱',
`orgAddress` VARCHAR(200) NULL DEFAULT NULL COMMENT '组织地址',
`orgWebsite` VARCHAR(200) NULL DEFAULT NULL COMMENT '组织的网站',
`leafCount` DECIMAL(1,0) NULL DEFAULT NULL COMMENT '子企业数量',
`orgSort` DECIMAL(10,0) NULL DEFAULT NULL COMMENT '组织排序',
`resIconStyle` VARCHAR(20) NULL DEFAULT '' COMMENT '资源图标',
`orgPath` VARCHAR(2048) NULL DEFAULT NULL COMMENT '记录组织的节点路径',
`createBy` VARCHAR(20) NULL DEFAULT NULL COMMENT '创建人ID',
`createName` VARCHAR(50) NULL DEFAULT NULL COMMENT '创建人',
`createTime` DATETIME NULL DEFAULT NULL COMMENT '创建时间',
`lastUpdateBy` VARCHAR(20) NULL DEFAULT NULL COMMENT '最后修改人ID',
`updateName` VARCHAR(50) NULL DEFAULT NULL COMMENT '最后修改人',
`lastUpdateTime` DATETIME NULL DEFAULT NULL COMMENT '最后修改时间',
PRIMARY KEY (`orgId`)
)
COMMENT='组织架构信息'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
4. 组织角色表(t_sys_role)
CREATE TABLE `t_sys_role` (
`roleId` VARCHAR(20) NOT NULL COMMENT '角色表主键ID',
`orgId` VARCHAR(20) NULL DEFAULT NULL COMMENT '所属组织',
`orgPath` VARCHAR(20) NULL DEFAULT NULL COMMENT '组织路径',
`orgName` VARCHAR(50) NOT NULL COMMENT '组织名称',
`roleName` VARCHAR(50) NOT NULL COMMENT '角色名称',
`roleDesc` VARCHAR(100) NULL DEFAULT NULL COMMENT '角色描述',
`createBy` VARCHAR(20) NOT NULL COMMENT '创建人ID',
`createName` VARCHAR(50) NOT NULL COMMENT '创建人',
`createTime` DATETIME NOT NULL COMMENT '创建时间',
`lastUpdateBy` VARCHAR(20) NULL DEFAULT NULL COMMENT '最后修改人ID',
`updateName` VARCHAR(50) NULL DEFAULT NULL COMMENT '最后修改人',
`lastUpdateTime` DATETIME NULL DEFAULT NULL COMMENT '最后修改时间',
PRIMARY KEY (`roleId`)
)
COMMENT='角色信息表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
5. 用户角色表(t_sys_userRole)
CREATE TABLE `t_sys_userRole` (
`userRoleId` VARCHAR(20) NOT NULL COMMENT '主键ID',
`roleId` VARCHAR(20) NULL DEFAULT NULL COMMENT '角色表主键ID',
`userId` VARCHAR(20) NULL DEFAULT NULL COMMENT '用户主键',
PRIMARY KEY (`userRoleId`)
)
COMMENT='用户角色关系表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
6. 角色资源表(t_sys_roleRes)
CREATE TABLE `t_sys_roleRes` (
`roleResId` VARCHAR(20) NOT NULL COMMENT '角色资源主键ID',
`roleId` VARCHAR(22) NOT NULL COMMENT '角色表主键ID',
`resId` VARCHAR(20) NOT NULL COMMENT '资源主键',
`isReadWrite` DECIMAL(1,0) NOT NULL DEFAULT 1 COMMENT '1,只读取2,可读写',
PRIMARY KEY (`roleResId`)
)
COMMENT='角色资源关系表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
7. 企业资源表(t_sys_orgRes)
CREATE TABLE `t_sys_orgRes` (
`orgResId` VARCHAR(20) NOT NULL COMMENT '角色资源主键ID',
`orgId` VARCHAR(22) NOT NULL COMMENT '角色表主键ID',
`resId` VARCHAR(20) NOT NULL COMMENT '资源主键',
`isReadWrite` DECIMAL(1,0) NOT NULL DEFAULT 1 COMMENT '1,只读取2,可读写',
PRIMARY KEY (`orgResId`)
)
COMMENT='角色资源关系表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
相关运营截图:




Java生鲜电商平台-RBAC系统权限的设计与架构的更多相关文章
- 26、生鲜电商平台-RBAC系统权限的设计与架构
说明:根据上面的需求描述以及对需求的分析,我们得知通常的一个中小型系统对于权限系统所需实现的功能以及非功能性的需求,在下面我们将根据需求从技术角度上分析实现的策略以及基于目前两种比较流行的权限设计思想 ...
- Java开源生鲜电商平台-财务系统模块的设计与架构(源码可下载)
Java开源生鲜电商平台-财务系统模块的设计与架构(源码可下载) 前言:任何一个平台也好,系统也好,挣钱养活团队这个是无可厚非的,那么对于一个生鲜B2B平台盈利模式( 查看:http://www.cn ...
- Java生鲜电商平台-定时器,定时任务quartz的设计与架构
Java生鲜电商平台-定时器,定时任务quartz的设计与架构 说明:任何业务有时候需要系统在某个定点的时刻执行某些任务,比如:凌晨2点统计昨天的报表,早上6点抽取用户下单的佣金. 对于Java开源生 ...
- Java生鲜电商平台-优惠券系统的架构设计与源码解析
Java生鲜电商平台-优惠券系统的架构设计与源码解析 电商后台:实例解读促销系统 电商后台系统包括商品管理系统.采购系统.仓储系统.订单系统.促销系统.维权系统.财务系统.会员系统.权限系统等,各系统 ...
- Java生鲜电商平台-商城系统库存问题分析以及产品设计对逻辑/物理删除思考
Java生鲜电商平台-商城系统库存问题分析以及产品设计对逻辑/物理删除思考 说明:在生鲜电商的库存设计,是后台的重点,也是难点,关乎商品是否存在超卖.商品的库存增加方式倒不难,直接在后台添加即可,而扣 ...
- Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战
Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战 Java生鲜电商平台- 什么是秒杀 通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动 比如说京东秒杀,就是一种定时定量秒杀,在规定 ...
- Java生鲜电商平台-促销系统的架构设计与源码解析
Java生鲜电商平台-促销系统的架构设计与源码解析 说明:本文重点讲解现在流行的促销方案以及源码解析,让大家对促销,纳新有一个深入的了解与学习过程. 促销系统是电商系统另外一个比较大,也是比较复杂的系 ...
- Java生鲜电商平台-App系统架构开发与设计
Java生鲜电商平台-App系统架构开发与设计 说明:阅读此文,你可以学习到以下的技术分享 1.Java生鲜电商平台-App架构设计经验谈:接口的设计2.Java生鲜电商平台-App架构设计经验谈:技 ...
- 33、生鲜电商平台-定时器,定时任务quartz的设计与架构
说明:任何业务有时候需要系统在某个定点的时刻执行某些任务,比如:凌晨2点统计昨天的报表,早上6点抽取用户下单的佣金. 对于Java开源生鲜电商平台而言,有定时推送客户备货,定时计算卖家今日的收益,定时 ...
随机推荐
- AwaitAsync(异步和多线程)
参考了一些大佬写的文章: https://www.cnblogs.com/yilezhu/p/10555849.html这个大佬写的文章,我还是很喜欢的 https://www.cnblogs.com ...
- webservice调用天气服务
常见服务:http://www.webxml.com.cn/zh_cn/support.aspx 可能用到缺少的ArrayOfString.java文件 package com.test.wes.we ...
- 【JavaWeb】JSTL标签库
JSTL标签库 JSTL标准标签库: JSTL用于简化JSP开发,提高代码的可读性与可维护性: JSTL由SUN(Oracle)定义规范,由Apache Tomcat团队实现: 引用JSTL核心库 核 ...
- 【XML】XML基本结构以及XML-Schema约束
XML 简介 1998年2月,W3C正式批准了可扩展标记语言的标准定义,可扩展标记语言可以对文档和数据进行结构化处理,从而能够在部门.客户和供应商之间进行交换,实现动态内容生成,企业集成和应用开发.可 ...
- C# Session 操作类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- CodeForces - 1236B (简单组合数学)
题意 有n种物品和m个背包,每种物品有无限个,现将若干个物品放到这些背包中,满足: 1.每个背包里不能出现相同种类的物品(允许有空背包): 2.在所有的m个背包中,每种物品都出现过. 求方案数,对10 ...
- 2. Java程序的运行机制
一.完成一个Java程序的流程:编辑Java源代码→编译Java程序→运行Java程序 1. 在记事本中编写Java程序,然后保存为.java类型文件(Java源文件) 2. 使用javac命令将源文 ...
- 9.Java基础_for/while/do-while循环
/* for循环(同C++) 初始化变量的作用域为循环体 出了循环体,初始化的局部变量消失 for(初始化;条件判断;条件控制){ 循环体; } while循环 while(条件判断){ 循环体; } ...
- HTML与CSS学习笔记(7)
1.响应式布局 利用媒体查询,即media queries,可以针对不同的媒体类型定义不同的样式,从而实现响应式布局. 常见选项: 媒体类型 and.not min-width.max-width: ...
- 20191028 牛客网CSP-S Round2019-1
花了 \(30min\) 打了 \(180\) 分的暴力... 仓鼠的石子游戏 问题描述 链接:https://ac.nowcoder.com/acm/contest/1100/A 仓鼠和兔子被禁止玩 ...