koa2重构博客项目

实现session存储在redis中

  • 基于koa-generic-session和koa-redis
    • koa-redis是基于redis的,所以必须安装redis
  • 在app.js中使用session中间件时,在session中间件内配置redis,则不需手动将session存储在redis内,直接将username等信息存储在session内即会同步到redis内

安装插件

安装插件koa-generic-session和koa-redis(koa-redis是基于redis的,所以必须安装redis):

1
npm i koa-generic-session koa-redis redis --save 

app.js使用插件 配置session和redis

  1. app.js中引入插件app.js
  2. app.js中,在routes前使用插件配置session和redisapp.js
    • app.keys即我们之前配置过的密匙,这里就用原来的,也可以是更复杂的
    • session数据是放在服务端的,cookie数据则存放在客户的浏览器上
      • path:可使用cookie的路由
      • httpOnly:true时前端js无法访问cookie
      • maxAge:cookie有效时间(毫秒)
    • 先把redis的配置环境写死,实际应该本地配置本地,线上配置线上
  3. 配置好后,每次用户发送http请求时,都会根据用户请求中的cookie到redis中获取session数据

routes-user.js验证

  1. routes-user.js中,添加一个测试路由routes-user.js
  2. 运行redis(redis安装目录下打开cmd,运行redis-server.exe redis.windows.conf启动redis)
  3. 运行项目,访问测试路由http://localhost:8000/api/user/session-test:![访问测试路由](https://i0.wp.com/ww1.sinaimg.cn/large/005H7IVsgy1gdk3fwjoanj31c9089gn0.jpg)
    • viewConut为访问次数,同一个浏览器多次访问会累加访问次数,但只存储一次session
  4. 查看是否存在redis中:redis目录下另启一个 cmd 窗口,原来的不要关闭(否则无法访问服务端),运行redis-cli后看到目前设置的所有key(keys *):cmd

回顾session和cookie

  1. 首先cookie是一个对象,里面存储的是userId、path等;session也是一个对象,其中存储的是username和password等。示意图
  2. cookie是存储在浏览器上的,session则可以存储在node中作为js变量或者存储在redis中。
  3. 流程总结
    1. 用户登录网页,在登录路由中将输入的username等数据放入session中,并使用redis的set方法将session数据同步存储到redis中
    2. 接下来每次访问网页时,首先执行的app.js就会根据用户请求中的cookie的userId,使用redis解析(读取)session得到username等数据,以此判断用户是否登录。

开发路由

项目安装mysql

npm i mysql xss --save --registry=https://registry.npm.taobao.org

复用blog-1中部分代码

  1. 统一数据返回格式:将blog-1中的model整个文件夹拷贝到blog-koa2文件夹下
  2. 数据库配置信息:将blog-1中的conf整个文件夹拷贝到blog-koa2文件夹下
    1. 在blog-koa2的app.js中引入conf中关于redis的配置信息,修改之前写死的redis配置blog-koa2的app.js
  3. 新建db文件夹,将blog-1中的db文件夹下的mysql.js拷贝过来。
  4. 拷贝controller整个文件夹,进行修改
    1. 按照async语法 修改blog.js:在每个函数前面添加async,返回值使用await关键词blog.jsawait处理Promise对象会直接得到resolve状态下返回的值,这样就没有Promise异步的问题了
      • blog.js中,async中遇到then时可这样修改blog.jsblog.jsblog.jsblog.js
    2. 修改user.js:
      1. user.js中需要用到cryp.js,所以拷贝blog-1中的utils文件夹下的cryp.js
      2. 一样按照async语法修改user.jsuser.js

创建 中间件(登录校验)

  • 新建middleware文件夹
    • 新建loginCheck.js文件,一样是判断session中是否有username,有则认为已登录,继续执行下一个中间件,没有则返回“未登录”:loginCheck.js

开发博客路由(routes-blog.js)

  1. list路由:routes-blog.js
  2. detail路由:routes-blog.js
  3. new路由:routes-blog.js
  4. update路由:routes-blog.js
  5. del路由:routes-blog.js
  6. 给需要的路由添加登录校验routes-blog.js

开发用户路由(routes-user.js)

  1. 一样引入需要使用的:routes-user.js
  2. login路由:routes-user.jskoa2框架中,app.js中我们时候用session中间件时配置了redis,故不需手动存储session到redis中

前端联调

  1. 运行前后端项目,前端运行在8001端口,后端运行在8000端口:运行前后端项目
  2. 运行nginx和redis
  3. 测试所有功能:
    1. (未登录)进入首页就会产生一个和cookie的id:session的id此时session并未存储到redis中示意图
    2. 进入登录页,登录zhangsan帐号后,产生另一个id,这个id会存储在session中登录zhangsan帐号后
    3. 存储在redis中的cookie对应的session的内容session中存储着username
  4. 接下来每次发送的请求进入app.js后就会根据cookie进入redis中读取对应的session,通过session中的username来判断用户登录与否

日志

  • 现在只讲使用koa-morgan插件记录access log并写入文件
  • 自定义日志先使用console.log和console.error即可,至于如何写入文件等后面再讲

记录access log

  1. 新建logs文件夹用于存放日志-新建access.log文件用于存放访问日志
  2. koa2框架中自带的koa-logger插件起一个开发环境下规范打印格式的效果,比如:使用koa-logger插件之后
  3. 但koa-logger插件只是美化打印效果,并不能用于记录access log

koa-morgan插件

  1. 这里我们需要使用express框架的morgan插件来记录access log
    • 但morgan只支持express框架,所以需要先做一个兼容,通过koa-morgan来安装,使其可以运行在koa2开发环境中安装插件
    • morgan插件的使用方法morgan(参数1,参数2)
      • **参数1**:(字符串)可选'dev'/'combined'等,决定log字符串格式
        • 比如,一般开发环境下选择dev比如dev线上环境则选择完善一点的格式combined
      • 参数2:可省略
  2. app.js中
    1. 需要写入文件就需要引入path和fs,需要记录access log就需要引入koa-morganapp.js
    2. app.js
  3. 测试
    1. 测试开发环境测试开发环境
    2. 测试线上环境
      1. package.json中,由于我们还没学pm2,先改nodemonpackage.json
      2. 运行线上环境运行线上环境
      3. 访问几次不同的页面,可看到access.log中已有日志:access.log

自定义日志

  1. 自定义日志先使用console.log和console.error即可,至于如何写入文件等后面再讲
  2. 比如,在routes-blog.js中,自定义日志routes-blog.js
  3. 效果:打印自定义日志

koa2中间件原理

  • 可参考koa官网
  • app.use()用于注册中间件
  • next机制:即上一个中间件通过next()触发下一个中间件
  • 注意:koa中间件不涉及路由功能,故不涉及method和path的判断!注意区分koa路由和koa中间件注意区分koa路由和koa中间件
  • 官网的“级联”中有一个中间件示例
  • 洋葱圈模型:中间件之间通过next函数联系,当一个中间件调用 next() 后,会将控制权交给下一个中间件, 直到下一个中间件不再执行 next() 后, 将会沿路折返,将控制权依次交换给前一个中间件。

中间件示例

  1. 新建koa2-test文件夹,npm init -y初始化环境
  2. 将package.js中的main改成app.js,新建app.js,将官网示例拷入app.js
    • 该示例中有3个中间件
    1. logger记录日志
    2. x-response-time记录请求时间
    3. response返回
  3. 安装koa框架npm i koa --save --registry=https://registry.npm.taobao.org
  4. 运行node app.js,访问8000端口:8000端口再访问http://localhost:8000/aaa和http://localhost:8000/bbb
  5. 控制台可看到:结果访问8000端口耗时5ms,后面因为不需要加载东西,所以aaa和bbb都是0ms
  6. 代码执行过程:代码执行过程
    1. 运行项目时首先进入app.js
    2. app.js中注册了3个中间件
    3. 首先进入logger中间件,但马上就由next进入x-response-time中间件
    4. 在x-response-time中记录了当前时间,又由next进入response中间件
    5. 在response中间件返回Hello World显示在页面上
    6. 此时又返回继续执行response中间件,计算出时间差,并将时间差设置到ctx中
    7. 执行完后相当于第6行代码执行完,即又返回logger中间件中执行7、8行代码,从ctx中获取刚才设置的时间差,并最终打印出来

洋葱圈模型

  • 上面示例的代码运行方式就是洋葱圈模型洋葱圈模型各个中间件之间看似分离,实则是包裹的关系,第一个中间件包含了第二个中间件,第二个又包含了第三个
  • 从代码来看:
    • 比如,给每个中间件加上开始于结束例子
    • 结果结果