Express

1. express安装

  1. 全局安装express命令:npm install express-generator -g

  2. 生成项目:express 项目名

  3. 安装依赖:cd 项目名

    cnpm install

  4. 启动项目(端口默认3000):npm start

  5. 安装nodemon跟cross-env(对不同环境进行监听,热监听):cnpm i nodemon cross-env --save-dev

  6. 修改package.json中的配置:

    "scripts": {
        "start": "node ./bin/www",
        "dev": "cross-env NODE_ENV=dev nodemon --inspect=9829 ./bin/www.js",
        "prod": "cross-env NODE_ENV=prod nodemon ./bin/www.js"
    }
    
  7. 重写启动项目:npm run dev

2. 了解express入口app.js代码,及相关插件作用

  1. app是本次访问的一个实例,每次http请求都会创建一个app实例。

  2. res.json({ }):

    • 将json数据以字符串格式返回到客户端,类似于req.end(“json字符串”)。
    • 自动设置返回格式:res.setHeader(“Content-type”, “application/json”);
  3. 如何解析表单、json格式的数据:

    • express.json():解析请求头req.headers["content-type"] == "application/json"的请求参数,并存放到req.body中。

    • express.urlencoded():解析请求参数是表单类型的数据,并存放到req.body中。

    app.use(express.json());
    app.use(express.urlencoded({ extended: false }));
    
  4. cookie-parser:解析cookie,并将其存放到req.cookie中

    var cookieParser = require('cookie-parser');
    app.use(cookieParser());
    
  5. morgan:用来写日志

    var logger = require('morgan');
    app.use(logger('dev'));
    
  6. 如何创建子路由? 子路由跟父路由关系?

    1. 创建子路由

      • 引入express
      • 实例化: let router = express.Router()
      • router.get(“子路由路径”, 中间件函数)
      var express = require('express');
      var router = express.Router();
      router.get('/', function(req, res, next) {
        res.send('respond with a resource');
      });
      module.exports = router;
      
    2. app.js中的父路由,跟子路由的关系

      //例如:在app.js中注册user路由?
      //"/users"是父路由,要访问usersRouter中的路由,得拼接上当前父路由'/users'.
      app.use('/users', usersRouter);
      

3. express中间件、中间件函数

  1. next( ):会执行下一个符合条件的函数,若不执行next( )请求就会在当前位置结束。

  2. express()中几个处理路由的函数:当 请求路径 满足 处理路由函数条件 的时候就会进去执行对应的中间件函数。

    • 任意请求路径都会进入的中间件函数

      app.use((req, res, next) => { })
      
    • 路由在请求路径中存在,就会进到这个中间件函数

      app.use("路由", (req, res, next) => {})
      
    • get方式的请求,并且路由在请求路径中存在才会进到这个中间件函数

      app.get("路由", (req, res, next) => { })
      
    • post方式的请求,并且路由在请求路径中存在才会进到这个中间件函数

      app.post("路由", (req, res, next) => {})
      

4.登陆: express-session 跟 connect-redis实现将登陆信息存放到session、redis中

  1. 安装:

    cnpm i redis --save
    cnpm i express-session --save
    cnpm i connect-redis --save
    
  2. App.js中配置:express-session、connect-redis、设置返回客户端cookie

    const session = require("express-session");
    const RedisStore = require("connect-redis")(session);
    
    //连接redis相关配置
    //初始化指定tokenId值的req.session空间,并将tokenId返回到客户端的cookie中
    const {redisClient} = require("./db/redis");
    const sessionStore = new RedisStore({
      client: redisClient
    });
    app.use(session({
      resave: false,
      saveUninitialized: true,
      secret: "jiangyf0725",
      //自动将sessionId返回到客户端的cookie中
      cookie: {
        path: '/',
        httpOnly: true,
        maxAge: 24 * 60 * 60 *1000
      },
      //redis跟session进行绑定
      store: sessionStore 
    }));
    
  3. 登陆成功接口,将用户信息存放到req.session中

    //由于app.js中redis跟session进行绑定,因此设置session的同时会自动将用户信息存放到redis中
    req.session.name = name;
    req.session.password = password;
    

5.登陆:登陆校验中间件

//检验中间件:创建middleware文件夹存放自定义中间件,创建检验中间件文件loginCheck.js
const {SuccessModel, ErrorModel} = require("../model/resModel");

module.exports = (req, res, next) => {
    if(req.session.name) {
        next();
        return
    }else {
        res.json(
            new ErrorModel("尚未登陆")
        )
    }
}

//在需要做校验的路由处使用
const loginCheck = rquire("./middleware/loginCheck");
app.use('/api/blog', loginCheck, blogRouter);

6. morgan写日志

  1. 生成环境:将日志写到指定文件中

    开发环境:将日志写在控制

    const env = process.env.NODE_ENV;
    if(env == 'dev') {
      //开发环境
      app.use(logger('dev'));
    }else {
      //生产环境写日志文件路径
      const aceessPathName = path.join(__dirname, "log", "access.log");
      const writeStream = fs.createWriteStream(aceessPathName, {
        flag: "a"
      })
      app.use(
          logger('combined', {stream: writeStream})
      );
    }
    

7. 中间件原理

  1. 分析:

    • app.use用来注册中间件,先收集起来
    • 遇到HTTP请求,根据path、method判断触发哪些
    • 实现next机制,即上一个通过next触发下一个
  2. 面向对象实现express中间件

    const http = require("http");
    let slice = Array.prototype.slice;
    
    class LikeExpress {
        constructor() {
            this.routes = {
                use: [],
                get: [],
                post: [],
            }
        }
    
        register(path) {
            let infos = {};
            if (typeof path == 'string') {
                infos.path = path;
                infos.stack = slice.call(arguments, 1);
            } else {
                infos.path = "/";
                infos.stack = slice.call(arguments, 0);
            }
            return infos;
        }
    
        use() {
            const info = this.register.apply(this, arguments);
            this.routes.use.push(info);
        }
    
        get() {
            const info = this.register.apply(this, arguments);
            this.routes.get.push(info);
        }
    
        post() {
            const info = this.register.apply(this, arguments);
            this.routes.post.push(info);
        }
    
        mathPath(method, url) {
            //存放路径匹配上的路由的中间件函数
            let stack = [];
    
            //根据method,拿到满足method条件的中间件函数
            let arr = this.routes.use;
            arr.concat(this.routes[method]);
    
            //循环所有中间件函数,将满足url条件的存放到stack
            arr.map(item => {
                if (item.path.indexOf(url) == 0) {
                    stack.push(item.stack);
                }
            })
    
            return stack;
        }
    
        nextHandle(req, res, stacks) {
            let next = () => {
                //拿到第一个匹配的中间件
                let middleware = stacks.shift();
                if (middleware) {
                    //执行中间件
                    middleware(req, res, next);
                }
            }
            next()
        }
    
        callback(req, res) {
            const method = req.method;
            const url = req.url.toLocaleLowerCase();
    
            let stacks = this.matchPath(method, url);
    
            //实现next功能
            this.nextHandle(req, res, stacks);
    
        }
    
        listen(...arg) {
            const server = http.createServer(this.callback);
            server.listen(...arg);
        }
    }
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值