一、Koa2安装
创建一个空白目录,然后进入终端,并在终端对koa进行安装:
复制 # 项目初始化
$ npm init -y
# 安装koa2
$ npm i koa2 -S
# 安装nodemon
$ npm i nodemon -D
二、入口文件
在项目根目录创建 app.js
文件,并在上一步操作中生成的 package.json
里配置:
复制 {
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon app.js"
},
}
在 app.js
中:
复制 const Koa = require('koa2');
const app = new Koa();
const port = 9000;
/*
解释下面这段代码:
app.use()方法是:将给定的中间件方法添加到此应用程序。简单说就是调用中间件
app.use() 返回 this, 因此可以链式表达
*/
app.use(async (ctx)=>{
ctx.body = "Hello, Koa";
// ctx.body是ctx.response.body的简写
})
app.listen(port, ()=>{
console.log('Server is running at http://localhost:'+port);
})
然后运行 npm run start
,并在浏览器输入 http://localhost:9000/
即可看到页面效果。
提示:
为了以后对端口和IP的管理方便,其实可以将IP与端口放在一个文件导出,然后导入使用,这样就可以方便管理:
复制 // 生产环境域名:http://xxx.com 开发环境域名:http://localhost
const host = "http://localhost";
// 生产环境端口:自定义 开发环境域名:9000
const port = 9000;
module.exports = {
host, port
}
然后到app.js或者需要使用IP与端口的文件中导入使用:
复制 const {host, port} = require("./utils")
app.listen(port, ()=>{
console.log(`Server is running at ${host}:${port}`);
})
三、洋葱模型
学Koa必须要了解 洋葱模型
:
Koa
和 Express
都会使用到中间件,Express的中间件是顺序执行,从第一个中间件执行到最后一个中间件,发出响应:
Koa是从第一个中间件开始执行,遇到 next
进入下一个中间件,一直执行到最后一个中间件,在逆序,执行上一个中间件 next
之后的代码,一直到第一个中间件执行结束才发出响应。
对于这个洋葱模型,我们用代码来解释一下。假如把上面的代码改写成:
复制 const Koa = require('koa2');
const app = new Koa();
const port = 9000;
app.use(async (ctx, next)=>{
console.log(1)
await next();
console.log(2)
})
app.use(async (ctx, next)=>{
console.log(3)
await next();
console.log(4)
})
app.use(async (ctx)=>{
console.log(5)
})
app.listen(port, ()=>{
console.log('Server is running at http://localhost:'+port);
})
那么在浏览器刷新后,控制台得到的顺序是:
现在可以看到,我们通过 next
可以先运行下个中间件,等中间件结束后,再继续运行当前 next()
之后的代码。
四、路由安装
当需要匹配不同路由时,可以安装:
将 app.js
修改:
复制 const Koa = require('koa2');
const Router = require('koa-router');
const app = new Koa();
const router = new Router();
const port = 9000;
router.get('/', async (ctx)=>{
ctx.body = "根路径";
})
router.get('/manage', async (ctx)=>{
ctx.body = "管理系统";
})
app.use(router.routes(), router.allowedMethods());
app.listen(port, ()=>{
console.log(`Server is running at http://localhost:${port}`);
})
此时,到浏览器刷新并在地址栏最后添加 /manage
即可得到根路径内容和列表模块内容。
备注:
复制 // 调用router.routes()来组装匹配好的路由,返回一个合并好的中间件
// 调用router.allowedMethods()获得一个中间件,当发送了不符合的请求时,会返回 `405 Method Not Allowed` 或 `501 Not Implemented`
allowedMethods方法可以做以下配置:
app.use(router.allowedMethods({
// throw: true, // 抛出错误,代替设置响应头状态
// notImplemented: () => '不支持当前请求所需要的功能',
// methodNotAllowed: () => '不支持的请求方式'
}))
五、路由拆分
当项目较大,路由较多时,我们需要划分模块。此时,就需要对路由进行拆分。这个项目的后端要服务于Web官网和后台管理系统,因此我们将路由划分成两个模块:web与manage。
1、创建 router
文件夹
创建router文件夹,并在其中创建:index.js
(路由总入口文件)、manage/index.js
(manage模块路由入口文件)、web/index.js
(web模块路由入口文件):
复制 // app.js
const Koa = require("koa2");
const router = require("./router")
const app = new Koa();
const port = 9000;
// 调用router中间件
app.use(router.routes(), router.allowedMethods());
app.listen(port, ()=>{
console.log(`Server is running at http://localhost:${port}`);
})
// index.js
const Router = require("koa-router");
const manage = require("./manage");
const web = require("./web");
const router = new Router();
router.get("/", async ctx=>{
ctx.body = "根路径"
})
router.use("/manage", manage.routes(), manage.allowedMethods());
router.use("/web", web.routes(), web.allowedMethods());
module.exports = router;
// manage/index.js
const Router = require("koa-router")
const router = new Router();
router.get('/', async ctx=>{
ctx.body = "管理系统"
})
module.exports = router;
// web/index.js
const Router = require("koa-router")
const router = new Router();
router.get('/', async ctx=>{
ctx.body = "官网"
})
module.exports = router;
到浏览器刷新 localhost:9000/manage
与 localhost:9000/web
即可得到manage和web两个模块返回的数据。
2、路由重定向(了解)
那么有同学会问了,如果我想直接从 localhost:9000
重定向到 localhost:9000/home
该怎么办?
我们可以在 router/index.js
中做如下配置:
复制 router.use('/home', home.routes(), home.allowedMethods());
...
router.redirect('/', '/home');
3、404无效路由
如果被访问到无效路由,那么我们可以统一返回404页面:
在 router
下 errorPage.js
:
复制 const Router = require('koa-router');
const errorPage = new Router();
errorPage.get('/', async (ctx) => {
ctx.body = "访问页面不存在";
})
module.exports = errorPage;
在 router/index.js
中:
复制 const errorPage = require("./errorPage")
// 404页面路由
router.use("/404", errorPage.routes(), errorPage.allowedMethods());
在 app.js
中引用:
复制 // 匹配不到页面的全部跳转去404
app.use(async (ctx, next) => {
await next();
if (parseInt(ctx.status) === 404) {
ctx.response.redirect("/404")
}
})
app.use(router.routes(), router.allowedMethods());
六、后端允许跨域(了解)
前端想跨域,可以设置proxy。如果后端允许跨域,可以如下操作:
复制 // 安装koa2-cors
$ cnpm i koa2-cors
// 引入koa2-cors中间件
const cors = require("koa2-cors");
// 这里cors中间件一定要写在路由之前
app.use(cors());
app.use(router.routes(), router.allowedMethods())
七、读取静态资源文件
首先安装 koa-static
,命令行代码如下:
然后在项目的根目录下创建 assets
后,将图片资源(图片自己随便找一张)文件夹 images
放到其中。我们假定404页面需要返回一张错误警告图,可以在 app.js
中执行以下操作:
复制 // 引入
const path = require('path')
const static = require('koa-static')
// 获取静态资源文件夹
app.use(static(path.join(__dirname, '/assets')));
...
app.use(router.routes(), router.allowedMethods())
假设其中有一张图片叫做 404.gif
,那么我们打开浏览器,访问:http://localhost:9000/images/404.gif
即可得到图片。这里注意:
路径上不需要写assets,因为我们已经指定了访问资源时, http://localhost:9000 自动指向 assets 文件夹。由此,我们知道数据库中图片的地址只需要填写 /images/404.gif
即可。
如果我们希望打开404页面就显示这张图,就需要做如下步骤:
1、安装mime-types
2、使用fs读取文件
修改errorPage.js:
复制 const Router = require("koa-router")
const router = new Router();
const fs = require("fs")
const path = require("path")
const mime = require("mime-types")
router.get('/', async ctx=>{
const filePath = path.join(__dirname, "../assets/images/404.gif");
const file = fs.readFileSync(filePath); // 读取文件
const mimeType = mime.lookup(filePath) // 读取文件类型
ctx.set("content-type", mimeType); // 设置返回类型(这一步很重要)
ctx.body = file; // 返回图片
})
module.exports = router;
八、MySQL安装【软件还需整理】
1、Windows卸载MySQL
如果你曾装过MySQL,请务必先卸载干净。
首先检查电脑是否安装过MySQL,Windows执行:开始->运行->输入 services.msc
。如果看到有MySQL,就代表安装了,如图:
如果没有,就可以忽略删除MySQL这一步了。但如果看到了这一项,请右键先停止这项服务,然后:
快捷键 win+r
输入 regedit
进入注册表,找到 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Eventlog\Application\MySQL
文件夹并对其进行删除。
如果有以下两个文件夹:
删除 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\Eventlog\Application\MySQL文件夹。 删除 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MySQL的文件夹。 注册表里没有这两个文件,就不用删除了。
然后找到mysql的安装位置,将mysql文件夹删掉:
再到控制面板搜索 mysql
,确认已经没有了才可以,否则也进行卸载。
然后是另一个地方的:C:\Program Files (x86)\MySQL
还有一个隐藏文件下的,先点击【查看】->勾选【隐藏的项目】:
然后返回 C:/
,可以看到一个名为ProgramData的文件夹,点开找到里面的MySQL,删除就行了
到此位置,恭喜你将mysql删干净了。
2、MySQL安装(Mac)
3、MySQL安装(Windows)
下载完成后,直接解压并放到指定的目录中。例如:D:\server\mysql-5.7.23-winx64。
在mysql目录中新建 my.ini
,并进行如下配置:
复制 [client]
# 设置mysql客户端默认字符集
default-character-set=utf8
[mysqld]
# skip-grant-tables
#设置3306端口
port = 3306
# 设置mysql的安装目录
basedir=D:\\server\\mysql-5.7.23-winx64
# 设置mysql数据库的数据的存放目录
datadir=D:\\server\\mysql-5.7.23-winx64\\data
# 允许最大连接数
max_connections=200
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
进入 mysql目录
下的 bin目录
,命令行执行:
复制 # 初始化数据库
$ .\mysqld --initialize --console
假如你得到:
复制 ...
2018-04-20T02:35:05.464644Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: sQjjZSffo6)C
...
代表初始化成功,并且 sQjjZSffo6)C
就是你的登录密码,可以在登陆后修改。你可以通过以下命令查询mysql版本:
复制 $ .\mysqladmin --version
# 得到:mysqladmin Ver 8.42 Distrib 5.7.23, for Win64 on x86_64
然后以管理员身份进入这个bin目录,并输入以下安装命令:
启动输入以下命令即可启动mysql:
如果你出现了上图的错误,可以执行:
复制 $ .\mysqld --remove
Service successfully removed.
$ .\mysqld --install
Service successfully installed.
$ net start mysql
MySQL 服务正在启动 .
MySQL 服务已经启动成功。
这样就算是mysql安装并启动成功了。
4、修改MySQL密码
现在修改mysql密码,重新打开 my.ini
,把这一行的注释解掉:
然后重启mysql:
复制 $ net stop mysql
$ net start mysql
此时的mysql密码已经被取消,可以随意输入密码进入:
然后修改密码:
复制 $ mysql> use mysql;
$ mysql> update user set authentication_string=password("123456") where user="root";
$ mysql> flush privileges; # 刷新权限
$ mysql> quit; # 退出mysql
注意:密码字段名 5.7 版本的是 authentication_string ,之前的为 password 。
然后重新回到 my.ini
把刚刚那行注释掉:
重启mysql:
复制 $ net stop mysql
$ net start mysql
再一次尝试连接mysql:
复制 $ .\mysql -uroot -p123456
出现以下界面,代表成功:
由于版本等问题,建议在连接mysql成功后,再一次执行:
复制 $ mysql> alter user user() identified by "123456";
十、Navicat安装【软件还需整理】
Navicat for MySQL
是一套全面的前端工具为数据库管理、开发和维护提供了一款直观而强大的图形界面,能同时连接 MySQL 和 MariaDB 数据库。
有关 Navicat for MySQL
软件的下载和安装,大家可以百度搜索,当然,我这里也给大家找到一篇文章:
https://www.cnblogs.com/yanghongtao/p/10976526.html
1、Windows安装
下载解压后直接双击两个.exe程序进行安装与绿化:
2、Mac安装
打开直接拽入应用程序即可。
十一、数据库基本操作语句
1、数据库的连接与断开
如果希望在系统全局均可连接mysql,可以在系统环境变量配置mysql的bin目录。
复制 # 连接数据库
$ mysql -uroot -p123456
# 断开数据库
$ mysql> quit;
# 或者
$ mysql> exit;
2、数据库基本操作
数据库的创建、删除、显示与选择。
复制 # 创建数据库
$ mysql> create database test;
# 删除数据库(不要轻易使用)
$ mysql> drop database test;
# 显示数据库
$ mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
8 rows in set (0.04 sec)
# 选择数据库
$ mysql> use test;
3、表操作
每个数据库都是由若干张表构成,每张表都是用来存储字段与数据的。以下是常用的表操作:
a. 创建表:
复制 # 创建一张用户表(包含id、用户名与密码)
/*
INT 整数型
PRIMARY KEY 主键约束
AUTO_INCREMENT 自增约束
VARCHAR 长字符串
COMMENT 字段注释
*/
create table user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(30) COMMENT '用户名称',
password VARCHAR(30) COMMENT '用户密码'
);
Query OK, 0 rows affected (0.02 sec)
什么是自增约束?
如果字段id被定义为AUTO_INCREMENT,在插入一行数据的时候,自增值的行为如下:
1.如果插入数据时id字段指定为0、null或未指定值,那么就把这个表当前的AUTO_INCREMENT值填到自增字段
2.如果插入数据时id字段指定了具体的值,就直接使用语句里指定的值
b. 删除表(不要随便使用):
复制 drop table user;
Query OK, 0 rows affected (0.01 sec)
c. 查看表:
复制 show tables;
+----------------+
| Tables_in_test |
+----------------+
| user |
+----------------+
1 row in set (0.00 sec)
d. 描述表(查看该表的字段):
复制 describe user;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(30) | YES | | NULL | |
| password | varchar(30) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
4、Navicat使用
打开安装好的Navicat软件,连接后其实也可以看到刚刚的这些数据:
5、表数据的增删改查
以上表操作中我们创建了一张user表,现在我们通过对这张表进行CRUD(增删改查)。
a. 增加表数据
复制 $ mysql> INSERT INTO user VALUES (null, "张三", "123456");
$ mysql> INSERT INTO user VALUES (null, "李四", "234567");
这里要注意:id是自增的字段,填写0或null都会从1开始自增。
b. 查询表数据
如果想要查询user表中所有的数据:
复制 $ mysql> SELECT * FROM user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | 张三 | 123456 |
| 2 | 李四 | 234567 |
+----+----------+----------+
2 rows in set (0.00 sec)
c. 更新表数据
假设现在想要修改李四的密码:
复制 $ mysql> UPDATE user SET password="999999" WHERE username="李四";
# 更新后可以查询李四的密码
$ mysql> SELECT password FROM user WHERE username="李四";
+----------+
| password |
+----------+
| 999999 |
+----------+
1 row in set (0.00 sec)
d. 删除表数据
假设现在想要删除张三这条数据:
复制 $ mysql> DELETE FROM user WHERE username="张三";
# 删除后查询表数据
$ mysql> SELECT * FROM user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 2 | 李四 | 999999 |
+----+----------+----------+
1 row in set (0.00 sec)
有关数据库基本操作语句的介绍就到这里,后续在项目中会有更多实战性应用。
十二、NodeJs中操作MySQL
1、创建连接池
NodeJs中想要连接MySQL,需要先在项目内安装mysql库:
在操作下面的代码时,先创建一个数据库,本项目将创建一个名为cms的数据库。另外,在cms中添加一张user表,然后填充部分数据:
复制 # 创建数据库cms
$ mysql> CREATE DATABASE cms;
# 选择数据库cms
$ mysql> USE DATABASE cms;
# 创建user表
$ mysql> CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(30) COMMENT "用户名称",
password VARCHAR(30) COMMENT "用户密码"
);
# 新增user表数据
$ mysql> INSERT INTO user VALUES (null, "张三", "123456");
$ mysql> INSERT INTO user VALUES (null, "李四", "aaasss");
然后到utils.js中,引入mysql并创建连接池:
复制 // 引入mysql
const mysql = require("mysql");
// 创建连接池
const pool = mysql.createPool({
host: "localhost", // 连接的服务器(代码托管到线上后,需改为内网IP,而非外网)
port: 3306, // mysql服务运行的端口
database: "cms", // 选择某个数据库
user: "root", // 用户名
password: "123456", // 用户密码
})
//对数据库进行增删改查操作的基础
const query = (sql,callback) => {
pool.getConnection(function(err,connection){
connection.query(sql, function (err,rows) {
callback(err,rows)
connection.release()
})
})
}
module.exports = {
host, port, query
}
2、Node中使用连接池
假设用户访问/manage即可查询数据库cms中表user的数据。这样的话,需要找到manage/index.js:
复制 const Router = require("koa-router")
const router = new Router();
const utils = require("../../utils")
router.get('/', async ctx=>{
let data = await new Promise((resolve, reject)=>{
// 写一句sql语句
var sql = `SELECT * FROM user`;
utils.query(sql, (err, data)=>{
if(err) reject(err);
resolve(data); // 返回拿到的数据
})
})
ctx.body = data; // 将查询结果返回到页面中
})
module.exports = router;
3、查询指定字段
使用逗号隔开字段,这种选择方式会返回一个数组
复制 SELECT username,password FROM user
至此,我们已经可以实现在Koa中操作数据库。