第二章day02:数据库设计与前端框架
1. 多租户Saas平台
1.1 多租户定义:
多租户技术(Multi-TenancyTechnology)
又称多重租赁技术:是一种软件架构技术,是实现如何在多用户环境下(此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。简单讲:在一台服务器上运行单个应用实例,它为多个租户(客户)提供服务。
- 从定义中我们可以理解:多租户是一种架构,目的是为了让多用户环境下使用同一套程序,且保证用户间数据隔离。
- 那么重点就很浅显易懂了,多租户的重点就是同一套程序下实现多用户数据的隔离
1.2 需求分析:
传统软件模式:
指将软件产品进行买卖,是一种单纯的买卖关系,客户通过买断的方式获取软件的使用权,软件的源码属于客户所有,因此传统软件是部署到企业内部,不同的企业各自部署一套自己的软件系统。
Saas模式:
指服务提供商提供的一种软件服务,应用统一部署到服务提供商的服务器上,客户可以根据自己的实际需求按需付费。用户购买基于WEB的软件,而不是将软件安装在自己的电脑上,用户也无需对软件进行定期的维护与管理
1.3 数据库方案
目前基于多租户的数据库设计方案通常有如下三种:
- 独立数据库
- 共享数据库、独立 Schema
- 共享数据库、共享数据表
1.独立数据库
每个租户一个数据库。
- 优点:为不同的租户提供独立的数据库,有助于简化数据模型的扩展设计,满足不同租户的独特需求;如果出现故障,恢复数据比较简单。
- 缺点: 增多了数据库的安装数量,随之带来维护成本和购置成本的增加
2.共享数据库、独立 Schema
即多个或所有的租户使用同一个数据库服务(如常见的ORACLE或MYSQL数据库),
但是每个租户一个Schema。
- 优点: 为安全性要求较高的租户提供了一定程度的逻辑数据隔离,并不是完全隔离;每个数据库可支持更多的租户数量。
- 缺点: 如果出现故障,数据恢复比较困难,因为恢复数据库将牵涉到其他租户的数据; 如果需要跨租户统计数据,存在一定困难。
3.共享数据库,共享数据表
即租户共享同一个Database,同一套数据库表(所有租户的数据都存放在一个数据库
的同一套表中)。在表中增加租户ID等租户标志字段,表明该记录是属于哪个租户的。
- 优点:所有租户使用同一套数据库,所以成本低廉。
- 缺点:隔离级别最低,安全性最低,需要在设计开发时加大对安全的开发量,数据备份和恢复最困难。
三种方式对比:
2. 数据库设计三范式
2.1 三范式介绍
数据库设计三大范式
数据库逻辑设计之三大范式通俗理解
- 三范式:
- 第一范式(1NF):确保每一列的原子性(做到每列不可拆分)
- 第二范式(2NF):在第一范式的基础上,非主字段必须依赖于主字段(一个表只做一件事)
- 第三范式(3NF):在第二范式的基础上,消除传递依赖
- 反三范式:
反三范式是基于第三范式所调整的,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。
举例说明:
- 第一范式:
此时的用户表是不满足第一范式的,因为对于address字段是可以继续拆分的:国家+城市
- 第二范式:
第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。
也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
用户表就应该只存储用户表的信息,后续两种信息应该存在成绩表/图书表中。
- 第三范式:
对于学生表:
因为存在依赖传递: (学号) → (学生)→(所在学院) → (学院电话) 。
可能会存在问题:
-
数据冗余:
有重复值; -
更新异常:
有重复的冗余信息,修改时需要同时修改多条记录,否则会出现数据不一致的情况
正确做法:
- 反三范式的出现
降低范式就是增加字段,允许冗余,达到以空间换时间的目的
。
【例】:如订单表,“金额”这个字段的存在,表明该表的设计不满足第三范式,因为“金额”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。但是,增加“金额”这个冗余字段,可以提高查询统计的速度,这就是以空间换时间的作法。
在Rose 2002
中,规定列有两种类型:数据列和计算列。
“金额”这样的列被称为“计算列”,而“单价”和“数量”这样的列被称为“数据列”。
2.2 三范式总结:
- 范式化
- 优点:
- 可以尽量的减少数据冗余,数据表更新快体积小
- 范式化的更新操作比反范式化更快
- 范式化的表通常比反范式化更小
- 缺点:
- 对于查询需要对多个表进行关联 导致性能降低
- 更难进行索引优化
- 反范式化
- 优点:
- 可以減少表的关联
- 可以更好的进行索引优化
- 缺点:
- 存在数据冗余及数据维护异常
- 对数据的修改需要更多的成本
3.前端框架:
了解前端技术栈(看得懂,会改就行):
- 技术栈
vue 2.5++,elementUI 2.2.2,vuex,axios,vue-router,vue-i18n, - 前端环境
node 8.++,npm 5.++
3.1安装与启动:
- 在vsCode中使用终端(命令安装文件):
通过淘宝镜像下载安装所有的依赖,几分钟后下载完成
如果没有安装淘宝镜像,请使用npm instal
cnpm install
1.1 关闭语法检查
打开 config/index.js 将useEslint的值改为false。
此配置作用: 是否开启语法检查,语法检查是通过ESLint 来实现的。
科普一下,什么是ESLint : ESLint是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码。
如果我们开启了Eslint , 也就意味着要接受它非常苛刻的语法检查,包括空格不能少些或多些,必须单引不能双引,语句后不可以写分号等等,这些规则其实是可以设置的。我们作为前端的初学者,最好先关闭这种校验,否则会浪费很多精力在语法的规范性上。如果以后做真正的企业级开发,建议开启
- 加载完成之后使用命令(编译并启动前端脚手架):
npm run dev
安装成功后可以点击链接进行访问:
3.2脚手架大纲:
├── assets | 资源
├── build | webpack编译配置
├── config | 全局变量
├── src | 源码
├── dist | 编译发布目录
├── index.html | 页面模板
├── package.json | npn包配置
├── static
└── test | 测试
├── e2e
└── unit
3.3前端执行步骤:
3.3.1 路由和菜单:
路由和菜单是组织起一个后台应用的关键骨架。本项目侧边栏和路由是绑定在一起的,所以你只有在@/router/index.js
下面配置对应的路由,侧边栏就能动态的生成了。大大减轻了手动编辑侧边栏的工作量。当然这样就需要在配置路由的时候遵循很多的约定:
- 这里的路由分为两种, constantRouterMap 和 asyncRouterMap 。
- constantRouterMap 代通用页面。
- asyncRouterMap 代表那些业务中通过 addRouters 动态添加的页面。
3.3.2 前端数据交互
一个完整的前端 UI 交互到服务端处理流程是这样的:
- UI 组件交互操作;
- 调用统一管理的 api service 请求函数;
- 使用封装的 request.js 发送请求;
- 获取服务端返回;
- 更新 data
从上面的流程可以看出,为了方便管理维护,统一的请求处理都放在 src/api 文件夹中,并且一般按照 model
纬度进行拆分文件:
api/
frame.js
menus.js
users.js
permissions.js
..
其中, src/utils/request.js 是基于 axios 的封装,便于统一处理 POST,GET 等请求参数,请求头,以及错
误提示信息等。具体可以参看 request.js。 它封装了全局 request拦截器 、 respone拦截器 、 统一的错误处
理 、 统一做了超时,baseURL设置等
3.4 Mock.js
Mock.js 是一款模拟数据生成器,旨在帮助前端攻城师独立于后端进行开发,帮助编写单元测试。提供了以下模拟功能:
- 根据数据模板生成模拟数据
- 模拟 Ajax 请求,生成并返回模拟数据
- 基于 HTML 模板生成模拟数据
实战例子:在vue中结合mock.js调试框架
//index.js
import Mock from 'mockjs'
import TableAPI from './table'
import ProfileAPI from './profile'
import LoginAPI from './login'
//如果发送请求的api路径匹配,拦截
//第一个参数匹配的请求api路径,第二个参数匹配请求的方式,第三个参数相应数据如何替换
Mock.mock(/\/table\/list\.*/, 'get', TableAPI.list)
//获取用户信息
Mock.mock(/\/frame\/profile/, 'post', ProfileAPI.profile)
Mock.mock(/\/frame\/login/, 'post', LoginAPI.login)
//以ProfileAPI.profile 为例:
//拦截到对应api后调用相应数据显示
//profile.js
export default {
profile:{
"code" : "10000",
"success" : true,
"message" : "登录成功",
"data" : {
mobile:"138000138000",
username:"张三ok",
company:"传智播客教育科技股份有限公司12345678",
email:"bipeng@itcast.cn",
}
}
}
扩展:
Mock.Random 提供的完整方法(占位符)如下:
TypeMethodBasicboolean, natural, integer, float, character, string, range, date, time, datetime, nowImageimage, dataImageColorcolorTextparagraph, sentence, word, title, cparagraph, csentence, cword, ctitleNamefirst, last, name, cfirst, clast, cnameWeburl, domain, email, ip, tldAddressarea, regionHelpercapitalize, upper, lower, pick, shuffleMiscellaneousguid, id
- 正确开启Mockjs的三种姿势:入门参考(一)
- Mock.mock(url, type, data)
参数名 | 参数需求 | 参数描述 | 例子 |
url | 可选: URL 字符串或 URL 正则 | 拦截请求的地址 | /mock |
type | 可选 | 拦截Ajax类型 | GET、POST |