zoukankan      html  css  js  c++  java
  • 15-Node


    typora-copy-images-to: media

    Express

    原生 http 在某些方面不足以应对我们的开发需求,为了加快开发效率,就要使用框架开发

    • 第三方 Web 开发框架
    • 高度封装了 http 模块
    • 更加专注于业务,而非底层细节

    安装和初始化

    # 初始化(生成package.json文件)
    npm init -y
    
    # 安装
    npm install express --save
    

    入门案例

    // 引入包
    var express = require('express');
    
    // 创建服务器应用,即原先的http.createServer()
    var app = express();
    
    // 公开指定的静态资源目录,客户端可以直接在浏览器访问该目录下的文件
    app.use( '/public/', express.static('./public/') );
    
    // 根据路径,执行不同的业务
    app.get('/', function (req, res){
        res.send('hello world');
    });
    app.get('/about', function(req, res){
      	console.log(req.query);	// 解析请求的url地址,转化为对象{}
        res.send('about us');
    });
    
    // 监听3000端口
    app.listen(3000, function(){
        console.log('app is running');
    });
    

    nodemon-自动重启服务器

    使用第三方命令行工具:ndoemon 来解决频繁修改代码重启服务器的问题

    nodemon 是一个基于node.js开发的第三方命令行工具,需要独立安装

    只要是通过 nodemon xxx.js 启动的服务,就会监视文件的变化,当文件发生变化的时候(保存文件的时候),自动重启服务器

    # 安装 nodemon
    npm install -g nodemon  // 全局安装
    
    # 使用nodemon
    # 由原先的 node app.js 改为:
    nodemon app.js
    

    路由

    基本概念

    在 Express 中,路由指的是客户端的请求服务器处理函数之间的映射关系

    Express 中的路由分 3 部分组成,分别是请求的类型请求的 URL 地址处理函数

    路由 = 请求方法 + 请求路径 + 请求处理函数

    语法

    app.METHOD(PATH, HANDLER)
    

    参数

    • METHOD - 请求方法
    • PATH- 请求路径
    • HANDLER - 请求处理函数

    GET和POST请求

    • get以及获取get请求参数
    // 以GET方法请求 / 的时候,执行对应的处理函数
    app.get('/', function(req, res){
      // get方式获取url中的参数,返回的是对象类型{name: 'jack', age: 11}
      let urlParams = req.query;
      res.send('get request');
    });
    
    • post以及获取post请求参数(需要第三方包 body-parser)
    // 以POST方法请求 / 的时候,执行对应的处理函数
    app.post('/', function(req, res){
      res.send('post request');
    });
    

    路由的匹配过程

    每当一个请求到达服务器之后,需要先经过路由的匹配,只有匹配成功之后,才会调用对应的处理函数。

    在匹配时,会按照路由的顺序进行匹配,如果请求类型和请求的 URL 同时匹配成功,则 Express 会将这次请求,转交给对应的 function 函数进行处理。

    注意

    • 1、按照定义的先后顺序进行匹配
    • 2、请求类型和请求的URL同时匹配成功,才会调用对应的处理函数

    模块化路由

    为了方便对路由进行模块化的管理,Express 不建议将路由直接挂载到 app 上,而是推荐将路由抽离为单独的模块

    将路由抽离为单独模块的步骤如下:

    • 1、创建路由模块对应的 .js 文件
    • 2、调用 express.Router() 函数创建路由对象
    • 3、向路由对象上挂载具体的路由
    • 4、使用 module.exports 向外共享路由对象
    • 5、使用 app.use() 函数注册路由模块

    1、创建路由模块

    // router/user.js
    
    // 导入 express
    const express = require('express');
    // 创建路由对象
    const router = express.Router();
    
    // 挂载具体的路由
    router.get('/user', (req, res)=>{
        console.log( req.query ); // { name: 'Jack', age: '10' }
        res.send( 'GET 请求' );
    });
    
    router.post('/user', (req, res)=>{
        console.log( req.body );    // {}
        res.send( 'POST 请求' );
    });
    
    // 向外暴露路由
    module.exports = router;
    

    2、注册路由模块

    // app.js
    
    const express = require('express');
    const app = express();
    // 引入路由
    const userRouter = require('./router/user.js');
    ...
    // 挂载路由
    app.use(userRouter);
    ...
    

    3、为路由模块添加前缀

    app.use('/api', userRouter);                         // 添加访问前缀 /api
    

    静态资源托管-static

    // 1. 当以 /public/开头的时候, 去 ./public/ 目录中找对应的资源(推荐使用,容易辨识)
    app.use('/public/', express.static('./public/'));
    
    // 2. 当省略第一个参数的时候,可以通过省略 /public 的方式来访问
    // 		如:完整的url: localhost:3000/public/login.html
    //          可以写成: localhost:3000/login.html 来访问资源
    app.use(express.static('./public/'));
    
    // 3. /a/ 可以看做是 ./public/的别名
    // url访问路径:localhost:3000/a/login.html
    app.use('/a/', express.static('./public/'));
    
    app.use(express.static('files'));
    app.use('/static', express.static(path.join(__dirname, 'public')));
    

    中间件

    中间件的概念

    中间件(Middleware ),特指业务流程的中间处理环节。

    Express中间件的调用流程

    当一个请求到达 Express 的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理

    Express 中间件的格式

    Express 的中间件,本质上就是一个 function 处理函数,Express 中间件的格式如下:

    注意:中间件函数的形参列表中,必须包含 next 参数。而路由处理函数中只包含 req 和 res。

    next 函数的作用

    next 函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。

    中间件的作用

    多个中间件之间,共享同一份 req 和 res。基于这样的特性,我们可以在上游的中间件中,统一为 req 或 res 对象添加自定义的属性或方法,供下游的中间件或路由进行使用

    // app.js
    // 中间件
    app.use( (req, res, next)=>{
    +    req.inTime = Date.now();        // 将请求时的时间挂载到 req 的属性inTime上
        next();
    } );
    
    // 路由
    app.get('/', (req, res)=>{
    +    res.send( '首页' + req.inTime ); // 访问 req.inTime 
    });
    app.get('/user', (req, res)=>{
    +    res.send( '用户页' + req.inTime ); // 访问 req.inTime 
    });
    

    中间件的使用

    全局中间件

    客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件

    通过调用 app.use(中间件函数),即可定义全局生效的中间件

    定义最简单的中间件函数

    // app.js
    
    // 1、定义最简单的中间件
    let mv = (req, res, next)=>{
        console.log( '最简单的中间件' );
        // 处理业务
    
        // 注意:当前中间件业务处理完毕之后,必须调用 next() 函数,把流转关系交给下一个中间件或路由
        next();
    }
    

    全局生效的中间件(挂载中间件)

    // app.js
    
    // 2、将mv注册为全局生效的中间件
    app.use(mv);
    

    定义全局中间件的简化形式

    // app.js
    app.use((req, res, next)=>{
        console.log( '最简单的中间件' );
        // 处理业务
    
        // 注意:当前中间件业务处理完毕之后,必须调用 next() 函数,把流转关系交给下一个中间件或路由
        next();
    });
    

    定义多个全局中间件

    可以使用 app.use() 连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用

    // app.js
    // 定义多个全局中间件
    app.use((req, res, next)=>{
        console.log( '定义的第1个全局中间件' );
        next();
    });
    app.use((req, res, next)=>{
        console.log( '定义的第2个全局中间件' );
        next();
    });
    
    // 调用该路由之前,依次触发了上面2个全局中间件
    app.get('/', (req, res)=>{
        res.send( 'GET Request' );
    });
    

    局部中间件

    定义局部中间件

    不使用 app.use() 定义的中间件,叫做局部生效的中间件

    // app.js
    // 局部中间件
    let mw = (req, res, next)=>{
        console.log( '这是局部中间件' );
        next();
    }
    
    app.get('/', mw, (req, res)=>{  // 中间件mw只会影响该路由
        res.send( 'get / 请求' );
    });
    
    app.get('/user', (req, res)=>{  // 中间件mw不会影响该路由
        res.send( 'get /user 请求' );
    });
    

    定义和使用多个局部中间件

    可以在路由中,通过如下两种等价的方式,使用多个局部中间件

    app.get('/', mw1, mw2, (req, res)=>{
        res.send( 'get / 请求' );
    });
    
    app.get('/', [mw1, mw2], (req, res)=>{
        res.send( 'get / 请求' );
    });
    

    中间件的5个使用注意事项

    • 1、一定要在路由之前注册中间件
    • 2、客户端发送过来的请求,可以连续调用多个中间件进行处理
    • 3、执行完中间件的业务代码之后,不要忘记调用 next() 函数
    • 4、为了防止代码逻辑混乱,调用 next() 函数后不要再写额外的代码
    • 5、连续调用多个中间件时,多个中间件之间,共享 req 和 res 对象

    中间件的分类

    为了方便大家理解和记忆中间件的使用,Express 官方把常见的中间件用法,分成了 5 大类

    • 1、应用级别的中间件
    • 2、路由级别的中间件
    • 3、错误级别的中间件
    • 4、Express 内置的中间件
    • 5、第三方的中间件

    应用级别的中间件

    通过 app.use()app.get()app.post()绑定到 app 实例上的中间件,叫做应用级别的中间件

    路由级别的中间件

    绑定到 express.Router() 实例上的中间件,叫做路由级别的中间件

    它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到 app 实例上,路由级别中间件绑定到 router 实例

    错误级别的中间件

    错误级别中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题

    格式:错误级别中间件的 function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是 (err, req, res, next)

    注意:错误级别的中间件,必须注册在所有路由之后

    Express 内置的中间件

    自 Express 4.16.0 版本开始,Express 内置了 3 个常用的中间件,极大的提高了 Express 项目的开发效率和体验

    • 1、express.static - 快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS 样式等(无兼容性无需配置
    • 2、express.json - 解析 JSON 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)
    • 3、express.urlencoded - 解析 URL-encoded 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)

    第三方的中间件

    非 Express 官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件

    在项目中,大家可以按需下载并配置第三方中间件,从而提高项目的开发效率

    例如:在 express@4.16.0 之前的版本中,经常使用 body-parser 这个第三方中间件,来解析请求体数据

    使用步骤

    • 1、运行 npm install body-parser 安装中间件
    • 2、使用 require 导入中间件
    • 3、调用 app.use() 注册并使用中间件

    注意:Express 内置的 express.urlencoded 中间件,就是基于 body-parser 这个第三方中间件进一步封装出来的

    自定义中间件

    需求

    自己手动模拟一个类似于 express.urlencoded 这样的中间件,来解析 POST 提交到服务器的表单数据

    步骤

    • 1、定义中间件
    • 2、监听 req 的 data 事
    • 3、监听 req 的 end 事件
    • 4、使用 querystring 模块解析请求体数据
    • 5、将解析出来的数据对象挂载为 req.body
    • 6、将自定义中间件封装为模块

    1、定义中间件

    使用 app.use() 来定义全局中间件

    2、监听 req 的 data 事

    在中间件中,需要监听 req 对象的 data 事件,来获取客户端发送到服务器的数据

    如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以 data 事件可能会触发多次,每一次触发 data 事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接

    3、监听 req 的 end 事件

    当请求体数据接收完毕之后,会自动触发 req 的 end 事件

    我们可以在 req 的 end 事件中,拿到并处理完整的请求体数据

    4、使用 querystring 模块解析请求体数据

    Node.js 内置了一个 querystring 模块,专门用来处理查询字符串。通过这个模块提供的 parse() 函数,可以轻松把查询字符串,解析成对象的格式

    5、将解析出来的数据对象挂载为 req.body

    上游中间件、下游中间件、路由之间,共享同一份 req 和 res。因此,我们可以将解析出来的数据,挂载为 req的自定义属性,命名为 req.body,供下游使用

    6、将自定义中间件封装为模块

    router

    导入的其他路由模块(见1.4 路由章节)

    express.static()

    静态资源托管(见1.5 静态资源托管-static 章节)

    body-parser

    获取表单post请求体 req.body 内容

    在express中获取表单post请求体数据

    在express中没有内置获取表单post请求体的API,需要使用第三方包 body-parser

    注意

    第三方中间件body-parser 已经在express@4.16.0版本中成为了内置中间件,配置如下

    app.use( express.urlencoded({ extended: false }) );
    app.use( express.json() );
    

    以下为express@4.16.0版本之前的用法

    安装

    npm install body-parser --save
    

    配置

    var express = require('express');
    // 1. 引入包
    + var bodyParser = require('body-parser');
    
    var app = express();
    // 2. 配置 body-parser
    // 只要加入这个配置,就会在req请求对象上多出一个属性: body, 可以直接通过req.body来获取表单post请求体数据
    + app.use( bodyParser.urlencoded({ extended: false }) );
    + app.use( bodyParser.json() );
    
    app.use(function(req, res){
      res.setHeader('Content-Type', 'text/plain');
      // 3. 可以直接通过req.body来获取表单post请求体数据
    +  res.end(JSON.stringify(req.body, null, 2));
    });
    

    express处理404页面

    express对于没有设定的请求路径,默认会返回 Can not get xxx

    如果想要定制404页面,需要通过中间件配置

    在自己的路由之后增加下面的代码

    // 文件路径
    
    app.use(function(req, res){
      // 所有未处理的请求路径都进入这里
      // 404
    });
    

    使用 Express 写接口

    1、创建基本的服务器

    // app.js
    const express = require('express');	// 1、导入express
    const app = express();				// 2、创建服务器实例 app
    // TODO
    app.listen(3000, ()=>{				// 3、监听3000端口,并启动服务器
        console.log( 'Server Running at http://127.0.0.1:3000' );
    });
    

    2、创建 API 路由模块

    // router.js
    const express = require('express');
    const router = express.Router();
    
    // 向外暴露 router
    module.exports = router;
    
    // app.js
    // 中间件 - 配置
    app.use(express.json());
    app.use(express.urlencoded({extended: false}));
    
    // 挂载路由
    const router = require('./d14-router');
    app.use('/api', router);
    

    3、编写 GET 接口

    // router.js
    // GET 请求
    router.get('/get', (req, res)=>{
        let query  = req.query;
        console.log( req1.body );
        res.send({
            status: 0,
            msg: '获取到 GET 请求',
            data: query
        });
    });
    

    4、编写 POST 接口

    // router.js
    // POST 请求
    router.post('/post', (req, res)=>{
        let body = req.body;
        res.send({
            status: 0,
            msg: '获取到 POST 请求',
            data: body
        });
    });
    

    5、处理错误的请求路径

    // router.js
    // 处理错误的请求路径
    router.use((req, res, next)=>{
        res.send({
            status: 1,
            msg: `没有匹配到 ${req.url} 请求`,
            data: {}
        });
    });
    

    6、处理错误

    有了错误处理,当服务器出错时,系统就不会再崩溃,只是向前端发送了错误提示

    // app.js
    // 处理错误
    app.use((err, req, res, next)=>{
        res.send({
            status: 2,
            msg: '出现错误',
            error: err.toString()
        });
    });
    

    跨域 - CORS

    接口的跨域问题

    刚才编写的 GETPOST接口,存在一个很严重的问题:不支持跨域请求

    解决接口跨域问题的方案主要有两种:

    • CORS(主流的解决方案,推荐使用
    • JSONP(有缺陷的解决方案:只支持 GET 请求)

    使用 cors 中间件解决跨域问题

    cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件,可以很方便地解决跨域问题。

    使用步骤分为如下 3 步:

    • 1、运行 npm install cors 安装中间件
    • 2、使用 const cors = require('cors') 导入中间件
    • 3、在路由之前调用 app.use(cors()) 配置中间件

    什么是 CORS

    CORS (Cross-Origin Resource Sharing跨域资源共享)由一系列 HTTP 响应头组成,这些 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源

    浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了 CORS 相关的 HTTP 响应头,就可以解除浏览器端的跨域访问限制。

    CORS 的注意事项

    • 1、CORS 主要在服务器端进行配置客户端浏览器无须做任何额外的配置,即可请求开启了 CORS 的接口。
    • 2、CORS 在浏览器中有兼容性。只有支持 XMLHttpRequest Level2 的浏览器,才能正常访问开启了 CORS 的服务端接口(例如:IE10+、Chrome4+、FireFox3.5+)。

    CORS 响应头部 - Access-Control-Allow-Origin

    响应头部中可以携带一个 Access-Control-Allow-Origin 字段,其语法如下:

    Access-Control-Allow-Origin: <origin> | *
    

    参数

    • origin - 指定了允许访问该资源的外域 URL
    • * - 允许来自任何域的请求

    示例

    // 表示只允许来自 百度 的请求
    res.setHeader( 'Access-Control-Allow-Origin', 'http://baidu.com' );
    
    // 允许来自任何域的请求
    res.setHeader( 'Access-Control-Allow-Origin', '*' );
    

    CORS 响应头部 - Access-Control-Allow-Headers

    默认情况下,CORS 仅支持客户端向服务器发送如下的 9 个请求头

    • 1、Accept
    • 2、Accept-Language
    • 3、Content-Language
    • 4、DPR
    • 5、Downlink
    • 6、Save-Data
    • 7、Viewport-Width
    • 8、Width
    • 9、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)

    如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过 Access-Control-Allow-Headers 对额外的请求头进行声明,否则这次请求会失败!

    CORS 响应头部 - Access-Control-Allow-Methods

    默认情况下,CORS 仅支持客户端发起 GETPOSTHEAD 请求

    如果客户端希望通过 PUTDELETE 等方式请求服务器的资源,则需要在服务器端,通过 Access-Control-Alow-Methods来指明实际请求所允许使用的 HTTP 方法

    示例

    CORS请求的分类

    客户端在请求 CORS 接口时,根据请求方式请求头的不同,可以将 CORS 的请求分为两大类

    • 简单请求
    • 预检请求

    简单请求

    同时满足以下两大条件的请求,就属于简单请求:

    • 1、请求方式GETPOSTHEAD 三者之一
    • 2、HTTP 头部信息不超过以下10种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type(只有三个值application/x-www-formurlencoded、multipart/form-data、text/plain)

    预检请求

    只要符合以下任何一个条件的请求,都需要进行预检请求:

    • 1、请求方式GETPOSTHEAD 之外的请求 Method 类型
    • 2、请求头包含自定义头部字段
    • 3、向服务器发送application/json 格式的数据

    在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。

    简单请求预检请求区别

    • 1、简单请求的特点:客户端与服务器之间只会发生一次请求
    • 2、预检请求的特点:客户端与服务器之间会发生两次请求OPTION 预检请求成功之后,才会发起真正的请求

    跨域 - JSONP 接口

    JSONP 的概念与特点

    概念:浏览器端通过 <script> 标签的 src 属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做 JSONP。

    特点:

    • JSONP 不属于真正的 Ajax 请求,因为它没有使用 XMLHttpRequest 这个对象。
    • JSONP 仅支持 GET 请求,不支持 POST、PUT、DELETE 等请求。

    创建 JSONP 接口的注意事项

    如果项目中已经配置了 CORS 跨域资源共享,为了防止冲突必须在配置 CORS 中间件之前声明 JSONP 的接口。否则JSONP 接口会被处理成开启了 CORS 的接口。

    实现 JSONP 接口的步骤

    • 1、获取客户端发送过来的回调函数的名字
    • 2、得到要通过 JSONP 形式发送给客户端的数据
    • 3、根据前两步得到的数据,拼接出一个函数调用的字符串
    • 4、把上一步拼接得到的字符串,响应客户端的script标签进行解析执行

    实现 JSONP 接口的具体代码

    在网页中使用 jQuery 发起 JSONP 请求

    调用 $.ajax() 函数,提供 JSONP 的配置选项,从而发起 JSONP 请求,示例代码如下:

    模板引擎整合

    express + art-template

    art-template的github仓库

    art-template官方文档

    安装

    npm install art-template --save
    npm install express-art-template --save
    

    配置

    // 参数1:当渲染以 .art 扩展名的文件的时候,使用art-template模板引擎
    // 参数2:express-art-template 专门用来在express中把 art-template 整合到express中
    // 这里虽然不需要加载art-template包,但是也必须安装,因为 express-art-template 依赖了 art-template
    app.engine('art', require('express-art-template'))
    
    // 可以修改成以html后缀名
    app.engine('html', require('express-art-template'))
    

    使用

    // express为response对象提供了一个方法:render(),当配置了模板引擎时就可以使用render()
    app.get('/', function(req, res){
      // 参数1: 不能写路径,默认会去项目中的views目录查找该模板文件
      // express有一个约定:把所有的视图模板文件都放在views目录中
      res.render('模板文件名', {模板数据});
    });
    

    修改默认的views视图渲染存储目录

    app.set('views', '新的render函数的默认路径')
    

    案例:用express重写留言本

    app.js

    let express = require('express');
    + let bodyParser = require('body-parser');
    
    let comments = [
        { username: '张三', message: '今天星期二!', dateTime: '2021-01-26 16:41:47' },
        { username: '李四', message: '你吃了吗?', dateTime: '2021-01-26 16:42:47' },
        { username: '王五', message: '还没有吃啊!', dateTime: '2021-01-26 16:43:47' },
        { username: '刘七', message: '是么', dateTime: '2021-01-26 16:44:47' }
    ];
    
    let app = express();
    // 公开静态资源目录
    app.use( '/public/', express.static('./public/') );
    // 配置模板引擎art-template
    app.engine('html', require('express-art-template'));
    
    // 配置body-parser,实现获取post请求体的数据
    + app.use(bodyParser.urlencoded({extented: false}));
    + app.use(bodyParser.json());
    
    app.get('/', function(req, res){
        // 渲染模板引擎
        res.render('index.html', {
            comments: comments
        });
    });
    
    app.get('/post', function(req, res){
        res.render('post.html');
    });
    
    // app.get('/post_submit', function(req, res){
    //     // 获取提交的参数,并保存到数组中
    //     let comment = req.query;    // req.query 可以返回一个对象类型的url参数
    //     comment.dateTime = '2021-1-27 21:23:43';
    //     comments.unshift(comment);
        
    //     res.redirect('/');
    // });
    app.post('/post', function(req, res){
        // 获取POST提交的参数,并保存到数组中
        // console.log(req.body);  // { username: '黑色冰凌', message: 'dada adad' }
    +    let comment = req.body;
        comment.dateTime = '2021-1-27 21:23:43';
        comments.unshift(comment);
        
        res.redirect('/');
    });
    
    app.listen(3000, function(){
        console.log('server running...');
    });
    

    案例:增删改查

    • 代码

      D:00web2015-Nodejsday03case03-student-manage-express

    • 起步

      • 初始化

        npm init -y
        npm i express --save
        npm i bootstrap --save
        npm i art-template --save
        npm i express-art-template --save
        npm i body-parser --save
        

      • 模板搭建

    • 路由设计

      请求路径 请求方法 get参数 post参数 备注
      /students get 渲染首页
      /students/add get 渲染添加学生页面
      /students/add post name,age,gender,hobbies 处理添加学生请求
      /students/edit get id 渲染编辑页面
      /students/edit post id,name,age,gender,hobbies 处理编辑请求
      /students/remove get id 处理删除请求
    • 入口模块 app.js

      • 创建服务

      • 配置相关服务

        • 配置模板引擎
        • 配置body-parser,解析post请求体参数
        • 提供静态资源服务
      • 注意:配置模板引擎和body-parser一定要在挂载路由之前

      • 挂载路由

        var router = require('./router');
        ...
        // 把路由挂载到app上
        app.use(router);
        

      • 监听端口,启动服务

    • 路由模块 router.js

      • 处理路由

        // 1. 引入express包
        var express = require('express');
        // 2. 创建一个路由容器
        var router = express.Router();
        ...
        // 3. 把路由都挂载到router这个路由容器中
        router.get('/', function(req, res){
          ...
        });
        ...
        // 4. 导出路由容器
        module.exports = router;
        

      • 根据不同的请求方法和请求路径处理不同的函数

        router.get('/', function(req, res){
          ...
        });
        
    • 模块职责要单一,不要乱写

      划分模块的目的就是为了提高项目代码的可维护性,提升开发效率

    • 数据保存到文件中

      • 先从文件中读取数据,转成对象
      • 向对象中push数据
      • 把对象转为字符串
      • 把字符串重新写入到文件中
    • 设计操作数据的API文件模块

      
      
    • 获取异步函数中返回的值

      // 如果需要获取一个函数中异步操作的结果,必须通过回调函数来获取
      + function fn(callback){
        setTimeout(function(){
          var data = 'hello';
      +    callback && callback(data);
          // 上面的相当于:
          // ( function(data){ console.log(data) } )()
        },1000);
      }
      
      + fn(function(data){
        console.log(data);
      });
      

    数据库

    MongoDB

    MySQL

    API

    express

    • express.json() - 解析 JSON 格式的请求体数据
    • express.raw()
    • express.Router() - 创建路由对象
    • express.static() - 托管静态资源
    • express.text()
    • express.urlencoded() - 解析 URL-encoded 格式的请求体数据

    app

    • Properties
      • app.locals
      • app.mountpath
    • Events
      • mount
    • Methods
      • app.get() - 处理GET请求的路由
      • app.post() - 处理POST请求的路由
      • app.put() - 处理PUT请求的路由
      • app.delete() - 处理DELETE请求的路由
      • app.use() - 注册全局中间件
      • app.engine() -
      • app.listen() - 启动服务器,监听服务器端口
      • app.all()
      • app.disable()
      • app.disabled()
      • app.enable()
      • app.enabled()
      • app.METHOD()
      • app.param()
      • app.path()
      • app.render()
      • app.route()
      • app.set()

    req

    • Properties
      • req.app - 当callback为外部文件时,用req.app访问express的实例
      • req.baseUrl - 获取路由当前安装的URL路径
      • req.body - 获得请求主体(POST方法传递的参数)
      • req.cookies - 获得Cookies
      • req.fresh - 判断请求是否还新鲜,同req.stale
      • req.hostname - 获取主机名
      • req.ip - 获取IP地址
      • req.ips -
      • req.method - 获取请求方法
      • req.originalUrl - 获取原始请求URL
      • req.params - 获取URL中的动态参数/user/:id(GET方法传递的参数)
      • req.path - 获取请求路径
      • req.protocol - 获取协议类型
      • req.query - 获取URL的查询参数串(GET方法传递的参数)
      • req.route - 获取当前匹配的路由
      • req.secure
      • req.signedCookies
      • req.stale - 判断请求是否还新鲜,同req.fresh
      • req.subdomains - 获取子域名
      • req.xhr
    • Methods
      • req.on() - 监听request请求事件(data, end, error, close, readable, pause, resume)
      • req.accepts() - 检查可接受的请求的文档类型
      • req.acceptsCharsets() - 返回指定字符集的第一个可接受字符
      • req.acceptsEncodings() - 返回指定字符集的第一个可接受字符编码
      • req.acceptsLanguages() - 返回指定字符集的第一个可接受语言
      • req.get() - 获取指定的HTTP请求头
      • req.is() - 判断请求头Content-Type的MIME类型
      • req.param()
      • req.range()

    res

    • Properties
      • res.app - 同req.app一样
      • res.headersSent
      • res.locals
    • Methods
      • res.append() - 追加指定HTTP头
      • res.attachment()
      • res.cookie(name,value [,option]) - 设置Cookie
      • res.clearCookie() - 清除Cookie
      • res.download() - 传送指定路径的文件
      • res.end() - 传送HTTP响应,并结束本次请求
      • res.format()
      • res.get() - 返回指定的HTTP头
      • res.json() - 传送JSON响应
      • res.jsonp() - 传送JSONP响应
      • res.links()
      • res.location() - 只设置响应的Location HTTP头,不设置状态码或者close response
      • res.redirect() - 设置响应的Location HTTP头,并且设置状态码302
      • res.render(view,[locals],callback) - 渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了
      • res.send() - 传送HTTP响应,并结束本次请求
      • res.sendFile() - 传送指定路径的文件 -会自动根据文件extension设定Content-Type
      • res.sendStatus()
      • res.set() - 设置HTTP头,传入object可以一次设置多个头。在res.append()后将重置之前设置的头
      • res.status() - 设置HTTP状态码
      • res.type() - 设置Content-Type的MIME类型
      • res.vary()

    router

    • Methods
      • router.all()
      • router.METHOD()
      • router.param()
      • router.route()
      • router.use()
  • 相关阅读:
    dojo自定义Widget
    奇怪的JS
    Dojo Widget系统(转)
    JS 中Promise 模式
    Structs 原理图
    ArcGIS Engine Style文件操作
    dojo.hitch 原理
    Android:解决cannot find zipalign的问题
    Bootstrap:解决Bootstrap下拉框需要双击才能打开的问题
    Clojure:添加gzip功能
  • 原文地址:https://www.cnblogs.com/pikachu/p/15429300.html
Copyright © 2011-2022 走看看