Express学习笔记

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Express学习笔记相关的知识,希望对你有一定的参考价值。

注:该笔记来自于视频Node.JS-黑马程序员

概述

express是高度封装了http的第三方框架。

express官网:http://expressjs.com/

只需要像安装其他包那样,直接执行npm install express --save命令安装后就可以使用了。

Hello World

Hello World

第一次使用:

// 第一步,引入express
var express=require("express");

// 第二步,创建服务器应用程序,即原来的http.createServer()
var app=express();
// 当服务器收到get请求 / 的时候,执行回调函数
app.get('/',function (request, response) {
    response.send("hello express!");// 发送数据到客户端,但原来的write、end方法都可以使用,但推荐使用send方法。
});
app.get('/hello',function (request, response) {
    response.send("你好,Express!");
});
// 监听端口,相当于原来的server.listen()
app.listen(8888,function () {
    console.log("app is running at port 8888.");
});

公开静态资源

如果要公开静态目录中的资源,可以设置这样的代码:

// 公开指定目录,该目录下存放的是静态资源如图片、css、js等
// 其中'/public/'表示可以通过/public/xx的方式访问'./public/'目录下的静态资源文件xx
app.use('/public/',express.static('./public/'));

就可以通过http://localhost:8888/public/star.jpg访问public目录下的star.jpg文件了。

操作路径问题

关于文件操作路径和模块操作路径的问题:

/**
 * 如果这里不添加".",则也是从磁盘根目录开始
 * 所以模块加载的路径中的相对路径不能省略"./"
 */
var foo = require('/data/foo.js');
var foo = require("./data/foo.js")
/**
 * 在文件操作的相对路径中
 * ./data/a.txt是相对于当前目录
 * data/a.txt是相对于当前目录
 * /data/a.txt表示绝对路径,是当前文件模块所处磁盘根目录
 * C:/Users/data/a.txt表示绝对路径
 */
fs.readFile('./data/a.txt', function (err, data) {

});

nodemon

修改完代码后自动重启,即热部署。安装这个插件后,就可以不用每次修改代码后都重启程序,可以节约时间。

使用第三方命令行工具:nodemon来解决修改代码后重启服务器问题。

安装:npm install nodemon --global

安装完成后,使用nodemon 启动文件名来启动服务,会监视文件的变化,当文件发生变化时,自动重启服务器。

node app.js // 例如原来启动app.js

nodemon app.js // 安装nodemon后启动app.js

使用nodemon --version来验证是否安装成功。

基本使用

GET请求和POST请求

express获取GET请求和POST请求分别通过如下两个方法,并在对应的回调函数中进行请求的处理和响应:

  • app.get(path, callback);:处理GET请求。
  • app.post(path, callback);:处理POST请求。

注意:

  • app指的是通过express()创建的服务器应用程序对象。
  • path是请求路由。
  • callback是一个回调函数,有两个参数requestresponse,分别是http的请求对象和响应对象,既可以调用http上的方法,也可以调用express提供的方法。
// 当服务器收到get请求 / 的时候,执行回调函数
app.get('/', function (request, response) {
    response.send("hello express!");
});
app.get('/hello', function (request, response) {
    response.send("你好,Express!");
});
// 当服务器收到post请求/submit的时候,执行对应的回调函数
app.post('/submit', function (request, response) {
    response.send("这是一个POST请求");
});

开放静态资源

静态资源就是一些html、css、js以及图片等文件。在http和express中是无法直接通过路径进行访问的,需要配置进行开放。有如下三种方式:

// 公开指定目录,该目录下存放的是静态资源如图片、css、js等
// 其中'/public/'表示可以通过/public/xxx的方式访问'./public/'目录下的静态资源文件xxx
// 例如:http://localhost:8888/public/star.jpg
app.use('/public/', express.static('./public/'));
// 其中'/abc/d/'表示可以通过'/abc/d/xxx'的方式访问'./public/'目录下的静态资源文件xxx
// 例如:http://localhost:8888/abc/d/star.jpg
app.use('/abc/d/', express.static('./public/'));
// 当省略第一个参数的时候,则可以通过省略'/public'的方式来访问,这种方式的好处是可以省略'/public/'
// 例如:http://localhost:8888/star.jpg
app.use(express.static('./public/'));

在express中使用模板引擎art-template

参考官方文档:https://aui.github.io/art-template/

  • 第一步,安装

在项目的根目录下执行npm安装命令:

npm install art-template --save
npm install express-art-template --save
  • 第二步,配置。

在导入了express模块的所在js文件中配置express-art-tempalte:

// 第一步,引入express
// var express = require("express");
// 第二步,创建服务器应用程序,即原来的http.createServer()
// var app = express();

// 配置express-art-template,前面的四行代码是为了让你知道在哪配置express-art-template
// 配置express-art-template模板引擎
// 第一个参数表示当以.html结尾的文件的时候,使用art-template模板引擎
// express-art-template是专门用来在express中把art-template整合到express中的
// 虽然外面不需要引入art-template,但也必须安装,因为express-art-template依赖了art-template
app.engine('html', require('express-art-template'));
  • 第三步,使用

还是通过response.render(path, object);来使用art-template模板引擎,其中path参数直接写文件名即可,它会自动去views文件夹下找对应的文件,所以通常我们会自己创建views文件夹作为存放html视图文件的目录;object是一个对象,表示要传入到对应模板文件中的数据对象。代码示例如下:

app.get('/hello', function (request, response) {
    // express默认会去项目中的views目录中找hello.html文件
    // express为Response响应对象提供了一个render()方法
    // 该方法默认是不可以使用的,但如果配置了模板引擎就可以使用了
    // 第一个参数不能写路径,写文件名即可,因为默认会去views目录中查找模板文件
    // 也就是说express默认约定开发人员把所有的视图文件都放到views目录中
    response.render('hello.html', {
        title: 'Hello World'
    });
});

  • 第四步,扩展

如果希望默认的views视图渲染存储目录,则可以通过如下方式进行修改:

// 注意,第一个参数views一定不能写错
app.set('views', 目录路径);

重定向

express的response.redirect('/')也可以实现重定向。

app.get('/send', function (request, response) {
    // 以前重定向的方法
    response.statusCode = 302;
    response.setHeader('Location', "/");
    // 使用express后的重定向方法
    response.redirect('/');
});

在Express中获取表单GET请求参数

express内置了一个API,可以直接通过request.query来获取请求参数,是一个对象。

app.get('/hello', function (request, response) {
    // http://localhost:8888/hello?name=zhangsan&age=12&sex=m
    console.log(request.query);// { name: 'zhangsan', age: '12', sex: 'm' }
    console.log(request.query.name);// zhangsan
    console.log(request.query.age);// 12
    console.log(request.query.sex);// m
});

在Express中获取表单POST请求参数

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

  • 第一步,安装body-parser
npm install body-parser --save
  • 第二步,配置

在引入了express模块中的js文件引入body-parser并进行配置:

// 第一步,引入express
// var express = require("express");
// 引入body-parser
var bodyParser = require('body-parser');
// 第二步,创建服务器应用程序,即原来的http.createServer()
// var app = express();
// 配置body-parser
// 只需要加入这个配置,则会在请求对象request上多出来一个body属性
// 就可以直接通过request.body来获取表单POST请求体数据
// parse application/x-www-form-urlencoded
// 被注释掉的express导入代码是为了让你关注body-parser的导入和配置
app.use(bodyParser.urlencoded({extended: false}));
// parse application/json
app.use(bodyParser.json());
  • 第三步,使用

请求对象request会多一个body属性,就是POST表单提交的数据。

// 当服务器收到post请求/submit的时候,执行对应的回调函数
app.post('/submit', function (request, response) {
    // http://localhost:8888/submit
    console.log(request.body);// [Object: null prototype] { username: 'zhangsan', password: '123456' }
    console.log(request.body.username);// zhangsan
    console.log(request.body.password);// 123456
    response.send(request.body);// {"username":"zhangsan","password":"123456"}
});

处理404

在路由的最后(即post和get最后)添加如下代码:

// 如果要定制404,需要通过中间件来配置,只需要在路由之后添加如下代码
app.use(function (request, response) {
	// 所有未处理的请求路径都会跑到这里来
	// 处理404的逻辑
});

中间件

参考文档:http://expressjs.com/en/guide/using-middleware.html

概念

Express的中间件就是一个请求处理方法,把用户从请求到响应的整个过程分发到多个中间件去处理,提供代码的复用性。

其实Express的中间件非常类似于Servlet的过滤器和SpringMVC的拦截器。

中间件通过app.use()方法进行设置。

中间件分类

应用程序级别的中间件

匹配所有的请求路径,不关心任何请求路径和请求方法(GET和POST)的中间件。格式如下:

// app是express实例
app.use(function(request,response,next){
	// 对request和response的处理
	next();
}

例如:

app.use(function (request, resonse, next) {
    // request:请求对象
    // response:响应对象
    // next:是一个函数,表示通过该中间件。当一个请求进入中间件后,如果需要请求另外一个方法则需要使用next()方法。next是一个方法,用来调用下一个中间件。注意:next()方法调用下一个方法的时候,也会匹配请求路径和方法(而不是调用紧挨着的哪一个)
    console.log(request.url);
    next();// 表示继续下一个中间件
});

而还有一种关心请求路径和请求方法的中间件,格式如下:

app.use(路径, function(request, response, next){
	// 对request和response的处理
	next();
});

例如:

app.use('/hello', function (request, response, next) {
    // 只有'/hello'路径的请求才会进入该中间件
    console.log(request.url);
    next();
});

路由级别的中间件

严格匹配请求路径和请求方法的中间件。
get:

app.get('/',function(req,res){
	res.send('get');
});

post:

app.post('/a',function(req,res){
	res.send('post');
});

put:

app.put('/user',function(req,res){
	res.send('put');
});

delete:

app.delete('/delete',function(req,res){
	res.send('delete');
});

错误处理中间件

app.use(function(err,req,res,next){
    console.error(err,stack);
    res.status(500).send('Something broke');
});

配置使用404中间件:这个顺序必须放到最后一个中间件,即最后一个use也该放到get、post后面

app.use(function(req,res){
    res.render('404.html');
});

配置全局错误处理中间件:

app.get('/a', function(req, res, next) {
	fs.readFile('.a/bc', funtion() {
		if (err) {
        	// 当调用next()传参后,则直接进入到全局错误处理中间件方法中
        	// 当发生全局错误的时候,我们可以调用next传递错误对象
        	// 然后被全局错误处理中间件匹配到并进行处理
			next(err);
		}
	})
});
//全局错误处理中间件
app.use(function(err,req,res,next){
    res.status(500).json({
        err_code:500,
        message:err.message
    });
});

内置中间件

express提供一个内置中间件,可以用来开放静态资源。如:

app.use(express.static('public'))

具体请参考文档:express.static()

第三方中间件

我们使用过一些第三方中间件,如body-parse处理POST请求体、如session处理session信息保存。

  • body-parser
  • compression
  • cookie-parser
  • mogran
  • response-time
  • server-static
  • session

参考文档:http://expressjs.com/en/resources/middleware.html

Express的CRUD

准备工作

按照下图创建文件夹和文件:

  • node_modules:安装包的时候会自动创建,管理着第三方包。
  • public:存放项目需要用到的一些公共资源,如css、js、图片等。
  • views:该文件夹存放着html视图文件。
  • app.js:项目的启动程序文件。
  • db.json:由于没有使用数据库,所以将数据持久化存储到本地文件中,以json格式存储。
  • package.json:包说明文件,在使用npm init命令时自动创建。
  • package-lock.json:包版本锁定文件,也是在安装包时自动创建的。
  • README.md:项目说明文件,自己写一些说明给该项目。
  • router.js:处理路由的文件。
  • student.js:数据增删改查操作,只是是将数据存储到db.json文件中。

安装包:在该项目下打开命令行窗口执行如下命令安装需要的包。

npm install --save express
npm install --save body-parser
npm install --save art-template
npm install --save express-art-template

初步创建app.js文件,让程序基本运行起来。

// 导入express模块
var express = require('express');

// 创建服务器
var app = express();

// 处理请求
app.get('/', function (request, response) {
    response.send('hello world.');
});

// 监听端口
app.listen(8989, function () {
    console.log('服务运行中,可通过 http://127.0.0.1:8989/ 访问...');
});

路由设计如下:

路由设计

请求方法请求路径get参数post参数备注
GET/students渲染学生列表
GET/students/newPage学生新增页面
POST/students/newname、sex、age新增学生
GET/students/editPage学生编辑页面
POST/students/editid编辑学生
GET/students/deleteid删除学生

创建路由文件router.js

将所有的请求路由写在router.js文件中:

// 渲染学生列表页面
app.get('/students', function (request, response) {

});

// 渲染学生新增页面
app.get('/students/newPage', function (request, response) {

});

// 新增学生
app.get('/students/new', function (request, response) {

});

// 渲染学生编辑页面
app.get('/students/editPage', function (request, response) {

});

// 编辑学生
app.get('/students/edit', function (request, response) {

});

// 删除学生
app.get('/students/delete', function (request, response) {

});

上面代码的app应该来自app.js中的app对象,那么如何将app.js与router.js文件关联起来呢?

第一种方式:不推荐。
第二种方式:使用express提供的路由挂载方式。
所以此时app.js文件内容如下:

// 导入express模块
var express = require('express');
// 导入路由router.js
var router = require('./router');

// 创建服务器
var app = express();

// 把路由容器挂载到app服务中
app.use(router);

// 监听端口
app.listen(8989, function () {
    console.log('服务运行中,可通过 http://127.0.0.1:8989/ 访问...');
});

// 将app对象暴露出去
module.exports = app;

router.js

// 0.Express提供了一种更好的方式,专门用来包装路由
var express = require('express');
// 1.创建一个路由容器
var router = express.Router();
// 2.router.get()或router.post()就是将路由都挂载到router路由容器中

// 渲染学生列表页面
router.get('/students', function (request, response) {

});

// 渲染学生新增页面
router.get('/students/newPage', function (request, response) {

});

// 新增学生
router.post('/students/new', function (request, response) {

});

// 渲染学生编辑页面
router.get('/students/editPage', function (request, response) {

});

// 编辑学生
router.post('/students/edit', function (request, response) {

});

// 删除学生
router.get('/students/delete', function (request, response) {

});

// 3.把router暴露出去
module.exports = router;

所以最后配置好的app.js文件内容如下:

// 导入express模块
var express = requireexpress学习笔记一

Express学习笔记

[原创]java WEB学习笔记61:Struts2学习之路--通用标签 property,uri,param,set,push,if-else,itertor,sort,date,a标签等(代码片段

[express.js学习笔记]理解Router

nodejs学习笔记--Express下安装模版引擎ejs

express框架解析——学习笔记