days-01 ^

 

数据库建设

写在前面:关于数据库

> 数据库部分,往往是软件经过需求分析之后,在进行整体架构时确定数据实体,建设数据库
>
> 常见的数据库分类:`关系:专业术语,在数据库中关系表示二维表的意思`
>
> - 关系型数据库:以表的形式存储数据的数据库,经常用于常见的应用软件
>   - 常见的:`sqlite`、`access`、`mysql`、`mariadb`、`oracle`、`db2`、`sybase...`
> - 非关系型数据库:不以表的形式存储数据的数据库,经常用于大数据领域
>   - 常见的:`redis`、`mongodb`、...
>
> 关于数据库的使用:
>
> - 常见的图形化操作-熟练
>
> - 常见的操作语句(增删改查)-熟练

数据库建设

- `mysql 5.1++`以上版本
- `navicate` 图形化界面工具

```sql
-- 创建数据库
create database bz2107_0601
    default charset 'UTF8';

-- 指定数据库
use bz2107_0601;

-- 创建数据库
create table menus(
    id int auto_increment primary key comment '主键',
    title varchar(50) not null comment '菜单名称',
    icon varchar(100) comment '菜单图标',
    href varchar(100) comment '菜单链接',
    pid int default 0 comment '上级菜单编号',
    tps int default 0 comment '0 目录;1 菜单',
    sts int default 0 comment '0 启用 1 禁用'
);

-- 创建角色表
create table roles(
    id int auto_increment primary key comment '主键',
    role_name varchar(50) comment '角色名称',
    menu_ids varchar(200) comment '菜单编号列表'
);

-- 创建用户表
create table users(
    id int auto_increment primary key comment '主键',
    username varchar(50) not null comment '用户账号',
    userpass varchar(50) not null comment '用户密码',
    randstr varchar(20) not null comment '混淆码',
    nickname varchar(50) not null comment '昵称',
    phone varchar(20) comment '手机',
    email varchar(50) comment '邮箱',
    gender char(5) comment '性别',
    age int default 0 comment '年龄',
    role_id int default 3 comment '角色编号',
    role_name varchar(50) comment '角色名称'
);

# 添加测试数据
insert into menus(id, title, icon, href, pid, tps, sts)
    values(1, '首页', 'home', '/a/home', 0, 1, 0),
                (2, '系统管理', 'system', '', 0, 0, 0),
                (3, '菜单管理', 'menus', '/a/menus', 2, 1, 0),
                (4, '角色管理', 'roles', '/a/roles', 2, 1, 0),
                (5, '用户管理', 'users', '/a/users', 2, 1, 0),
                (6, '业务管理', 'business', '', 0, 0, 0),
                (7, 'LOGO设置', 'logo', '/a/logo', 6, 1, 0),
                (8, '登录页管理', 'login', '/a/login', 6, 1, 0),
                (9, '注册页管理', 'reg', '/a/reg', 6, 1, 0);
    

insert into roles(id, role_name, menu_ids)
    values(1, '系统管理员', '1,2,3,4,5,6,7,8,9'),
                (2, '业务管理员', '1,6,7,8,9'),
                (3, '会员', '');


insert into users(id, username, userpass, randstr, nickname, role_id, role_name)
    values
(1, 'admin', '312bf8e245be53e7b87c5ce639d605d3', 'uq58si', '管理员', 1, '系统管理员'),
(2, 'damu', '5c5f3d8172dff50c46b94e5731818ed1', 'qsnppq', '管理员', 2, '业务管理员'),
(3, 'tom', '0bc20c8b95421216b15adf498928ef1f', 'sgebcv', '管理员', 3, '会员');
 

### 项目初始化

确定项目开发环境:

> ① `NodeJS`环境
>
> ② `Express`脚手架

创建数据接口项目:

- `API`:`Application应用程序 Program 开发/编程 Interface 接口`

```shell
-- 全局安装express项目脚手架
$ npm install express-generator -g

-- 通过express命令快速创建一个项目
$ express -e bz210701api
```

创建好项目之后,安装依赖并启动项目

```shell
$ cd bz201701api
$ npm install 
$ npm start
```

打开浏览器,访问:`http://localhost:3000`,看到如下页面,表示项目初始化完成

### 关于`windows`命令行

作为一个开发人员,命令行的交互方式是必须掌握的技能之一

- `windows`:命令提示符窗口
- `MacOS`:`shell`终端
- `Linux/Unix`:`Terminal`终端

#### (1) 打开命令行

开始菜单-> 输入:命令提示符  or  输入:cmd;可以找到并打开命令提示符窗口

按组合键`win + R`:打开运行窗口,输入cmd回车,可以直接打开命令提示符窗口

在任意打开的文件夹中,地址栏输入cmd直接回车,可以在当前文件夹路径中打开命令窗口

#### (2) 常见操作命令

- `dir`

  作用:查看当前文件夹中的所有文件 `directory 目录`

- `cls`:

​        作用:清除显示区域的内容 `cleans 清除`

- `cd`:

  作用:命令行中改变文件夹路径 `change directory 改变目录`

- `ipconfig`

  作用:查看自己的IP地址

- `nslookup`

  作用:查看指定域名的DNS服务器和域名真实地址

### 6、封装数据库访问模块

安装第三方模块,完成`mysql`数据库的访问:

- `mysql`:常用的连接数据库的基础模块
- `mysql2`:常用的封装了`Promise`的链接数据库的模块

 

#### (1)安装依赖

```shell
$  npm i mysql2 -S
```

#### (2)创建数据模块

创建`routes/db.js`用于封装数据库链接信息


const mysql = require('mysql2')

const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  database: 'test',
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

module.exports = pool.promise();

```

#### (3)全局配置

将和代码无关的配置信息,如数据库链接账号、密码等信息,单独抽取到一个配置文件中进行管理

创建全局配置文件:`bz20107api/config/global.json`

```json
{
  "mysql_conf": {
    "host": "localhost",
    "port": 3306,
    "user": "root",
    "password": "root",
    "database": "bz21070601",
    "waitForConnections": true,
    "connectionLimit": 10,
    "queueLimit": 0
  }
}
```

修改`db.js`,完善数据库访问模块


const mysql = require('mysql2')

const { mysql_conf } = require('../config/global.json')

const pool = mysql.createPool({
  host: mysql_conf.host,
  user: mysql_conf.user,
  password: mysql_conf.password,
  database: mysql_conf.database,
  waitForConnections: mysql_conf.waitForConnections,
  connectionLimit: mysql_conf.connectionLimit,
  queueLimit: mysql_conf.queueLimit
});

module.exports = pool.promise();

```

### 7、关于开发环境

大家开发软件/编写代码之前,首先要配置好自己的计算机开发环境,包含

- 代码运行环境:`NodeJS`平台软件,下载安装
- 代码编辑工具:文本编辑器,`Sublime/Editplus/VSCode/WebStrom...`

#### (1) `NodeJS`环境

初始化运行环境时,官方网站下载安装包 / 压缩包

- 安装包:`.exe`或者`.msi`文件,一键安装配置,适合新手
- 压缩包:可以下载压缩包进行配置(配置文件)安装

 

首先选择合适的软件位数:32bit(32位) / 64bit(64位)

- 选择和当前系统位数一致的软件

 

选择安装包或者压缩包

- 安装包:`.exe(execute) / .msi(MicroSoft Installer)`结尾的文件
  - 一键安装,自动配置
- 压缩包:`.zip`结尾的文件
  - 下载并解压到本地之后,需要添加对应的配置文件:`.npmrc`,指定软件的各种配置信息

 

#### (2) 开发工具

前端的开发工具,发展到现在根据不同的开发方向,使用的工具不同

- 2015~2016:前端刚刚兴起,主要的编辑工具是国外的一款`Sublime text2 / 3`

- `2017~2018`:`Webstorm / HBuilder / VSCode` 三分天下
- 2019年~:`VSCode`大行其道.....

```
1、专业前端开发人员:VSCode、HBuilder、小程序开发工具
2、小程序开发人员:HBuilder 、小程序工具
3、多端开发人员:HBuilder 、小程序工具
4、全栈开发人员:Webstorm | Intellij / Pycharm / Phpstrom / RubyStrom / DataGrip....
```

### 8、数据业务模块

构建一个数据接口项目,项目的层级关系如图所示:

![image-20220601144431873](assets/image-20220601144431873.png)

#### (1)菜单业务数据模块

创建文件夹:`services/`,创建菜单业务模块:`serivces/menus.service.js`


const db = require('../routes/db')

class MenuService {
  /** 查询全部菜单 */
  async findAll(){
    const statement = `select id, title, icon, href, pid, tps, sts from menus`
    let [rows] = await db.query(statement)
    return rows
  }

  /** 分页查询菜单 */
  async findByPage(page=1, size=10) {
    const startId = (page - 1) * size
    const statement = `select id, title, icon, href, pid, tps, sts from menus limit ?, ?`
    let [rows] = await db.query(statement, [startId, size])
    return rows
  }

  /** 查询菜单总数 */
  async findTotal() {
    const statement = `select count(1) as cnt from menus`
    let [rows] = await db.query(statement)
    return rows
  }

  /** 根据名称查询菜单 */
  async findByTitle(title) {
    const statement = `select id, title, icon, href, pid, tps, sts from menus where title = ?`
    let [rows] = await db.query(statement, [title])
    return rows
  }

  /** 根据编号查询菜单 */
  async findById(id) {
    const statement = `select id, title, icon, href, pid, tps, sts from menus where id = ?`
    let [rows] = await db.query(statement, [id])
    return rows
  }

  /** 增加菜单 */
  async add(title, icon, href, pid, tps) {
    const statement = `insert into menus(title, icon, href, pid, tps)
                        values(?,?,?,?,?)`
    let [rows] = await db.query(statement, [title, icon, href, pid, tps])
  }

  /** 编辑菜单 */
  async edit(id, title, icon, href, pid, tps, sts) {
    const statement = `update menus set title = ?, icon = ?, 
                                    href= ?, pid = ?, tps = ?,
                                    sts = ? where id = ?`
    let [rows] = await db.query(statement, [title, icon, href, pid, tps, sts, id])
  }

  /** 删除菜单 */
  async delete(id) {
    const statement = `delete from menus where id = ?`
    return await db.query(statement, [id])
  }
}

module.exports = new MenuService()

// test
// const ms = new MenuService()
// ms.findByPage(1, 3).then(res => console.log(res))

```

### 路由模块

#### (1) 模块构建

创建`routes/menus.js`路由模块,用于处理菜单数据

- `Dyno File Utils `:`vscode`插件,通过快捷键的方式创建文件夹和文件
- `Alt + N`:输入`名称/` 创建文件夹,输入`名称`表示创建文件
- `Ctrl + P`:快捷切换不同的文件


const express = require('express')

const router = express.Router()

module.exports = router

```

需要在`main.js`中注册

```js
....
var menusRouter = require('./routes/menus')
...

app.use('/menus', menusRouter)
....
```

#### (2) 数据查询

包含了查询全部菜单、分页查询菜单、查询菜单总数

编辑`menus.js`文件,添加对应路由函数
const express = require('express')

const router = express.Router()

const menuService = require('../services/menus.service')

/**
 * 查询菜单列表
 *    参数:q  1-查询全部  2-分页查询
 */
router.get('/list', async (req, res) => {
  // 解构数据
  let {q=1, page=1, size=10} = req.query
  let ret = []
  // 查询数据
  if(parseInt(q) === 1) {
    ret = await menuService.findAll()
  } else if(parseInt(q) === 2) {
    ret = await menuService.findByPage(page, size)
  }
  // 返回结果
  res.json({
    code: 200,
    msg: 'ok',
    data: ret
  })
})

/** 查询菜单总数 */
router.get('/total', async(req, res) => {
  let ret = await menuService.findTotal()
  res.json({
    code: 200,
    msg: 'success',
    data: ret
  })
})

module.exports = router

```

 

#### (3) 增加数据

编辑` routes/menus.js`,新增添加菜单的路由函数

```js

/** 增加菜单数据 */
router.post('/add', async(req, res) => {
  // 请求体中解构数据
  let {title='', icon='', href='', pid=0, tps=0} = req.body
  // 数据逻辑验证
  if(title.trim() === '' || href.trim() === '') {
    res.json({
      code: 601,
      msg: '缺少关键参数',
      data: []
    })
    return
  }

  // 数据业务验证
  let ret = await menuService.findByTitle(title)
  if(ret.length > 0) {
    res.json({
      code: 602,
      msg: '该菜单名称已经存在',
      data: []
    })
    return 
  }

  // 添加数据
  let ret2 = await menuService.add(title, icon, href,pid, tps)
  console.log(ret2)
  if(ret2.insertId > 0) {
    res.json({
      code: 200,
      msg: 'ok',
      data: [{id: ret2.insertId, title, icon, href, pid, tps}]
    })
  } else {
    res.json({
      code: 700,
      msg: '系统繁忙,请稍后再试',
      data: []
    })
  }
  
})
```

 

#### (4) 编辑数据

编辑文件`routes/menu.js`,新增编辑菜单路由函数

```js

/** 编辑菜单 */
router.put('/edit', async(req, res) => {
  // 解构数据
  let {id=-1, title='', icon='', href='', pid=0, tps=0, sts=0} = req.body
  // 数据校验
  if(id === -1 || title.trim() === '' || href.trim() === '') {
    res.json({
      code: 601,
      msg: '缺少关键参数',
      data: []
    })
    return
  }
  // 编辑数据
  let ret = await menuService.edit(id, title, icon, href, pid, tps, sts)
  if(ret.affectedRows > 0) {
      // 返回响应
      res.json({
        code: 200,
        msg: 'edit ok',
        data: [{id, title, icon, href, pid, tps, sts}]
      })
  } else {
    res.json({
      code: 700,
      msg: '系统繁忙,请稍后再试',
      data: []
    })
  }
  
})
```

 

#### (5) 删除数据

编辑文件:`routes/menu.js`

```js

/** 根据id删除菜单 */
router.delete('/del', async(req, res) => {
  // 1、解构数据
  let {id} = req.query
  // 2、删除数据
  await menuService.delete(id)
  // 3、返回结果
  res.json({
    code: 200,
    msg: 'delete ok',
    data: []
  })
})

```

### 关于HTTP规范

从90年代出现了WEB应用,针对网络应用中数据的传输就开始出现了各种规范,其中最重要的一种规范就是超文本传输协议规范,主要应用于网站应用!

针对生活中数据的操作方式,HTTP规范了多种代码数据操作方式

> 查询数据:HTTP规范中,提供了GET请求方式
>
> 新增数据:HTTP规范中,提供了POST请求方式
>
> 修改数据:HTTP规范中,提供了PUT请求方式
>
> 删除数据:HTTP规范中,提供了DELETE请求方式
>
> 了解基本信息:不需要了解完整信息的情况下,HTTP规范中提供了HEAD请求方式
>
> 了解存活情况:只需要对方返回数据即可,称为心跳请求;HTTP规范中提供了OPTIONS请求方式
>
> 了解操作记录:不需要返回实体数据,只需要返回基础记录,HTTP规范提供了TRACE请求方式
>
> 保持长链接关系,HTTP规范提供了一种CONNECT请求方式

 

一般应用开发时,前后端耦合项目开发,需要使用的请求方式:

> - GET
> - POST

方式:

- 数据的运算方式:常用的加减乘除
- 数据的操作方式:常用的增删改查,简称`CRUD`,
  - `CREATE增加`、`RETRIEVE查询`、`UPDATE修改`、`DELETE删除`

> - GET
> - POST
> - PUT
> - DELETE

涉及到服务器开发和运维,会用到HTTP其他请求方式

> - OPTIONS 发送心跳请求
> - HEAD 处理响应优化
> - TRACE 跟踪业务事务

 

### 12、数据接口测试工具

测试工具,本身属于后端开发人员和测试人员的常用工具

针对数据接口进行测试:常用的工具

- `RestClient`:代码级、命令行测试工具
- `PostMan`:视图工具
- `APIPOST`:视图工具
- `Apifox`:推荐 -接口测试工具

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值