Express

在原生node中如果路由和业务代码过多,代码会越来越复杂,难以阅读和维护,耦合的代码太多会导致修改时可能引入新的bug,我们可以使用express来解决这些问题。Express是一个可以在node.js中使用MVC框架。

如何使用express?

1、本地安装:npm install express
2、引用express以后可以得到一个函数,调用此函数使用各种方法

let express=require('express');//express是一个函数,执行后返回一个监听函数。node不支持import,只能使用commonjs。
let app=express();
app.listen(8080);//监听端口

app是http中的监听函数?

app.listen=function(){
	let server=require('http').createServer(this);
	return server.listen(...arguments);
	//server.apply(server,arguments)
}

使用路由

路由是根据客户端的不同的请求返回不同的响应,通过请求方法和路径执行对应的监听函数。可以定义多个路由,匹配的时候从上一次往下一次匹配,如果匹配方法名和路径都匹配上,则执行对应的监听函数并结束响应,如果有任何一个没有匹配上,则往下继续匹配,如果都没有匹配上,则报错,页面显示CANNOT+HTTP方法+路径名
创建一个路由:监听函数.方法(路径名,执行对应的函数)

方法有get,post,put,delete,options;options试探性,一般在post之前先发一个。
options请求方法主要有两个用途:
1、获取服务器支持的HTTP请求方法
2、用来检查服务器的性能。AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。

curl客户端使用方法

1、指定请求头:
curl -H 'content-type:application/json;charset=utf-8' http://localhost:8080/users
2、指定方法名
curl -X POST http://localhost:8080;在命令窗口执行的到请求的方法
3、指定请求体
curl --data "name=zfpx&age=8" http://localhost:8080/users

all和*

all可以匹配所有方法,*可以匹配所有路径

app.all('*',function(req,res){
	res.end('404');
})
	all代表所有匹配的方法,一般用来匹配404页面,放到所有路由的最下面,否则会截断。

express扩展属性和方法

* req.host 返回请求头里取得主机名(不包含端口号)
* req.path  相当于pathname,express提供的,获取路径
* req.query  相当于query,express提供的,获取请求的方法
* req.method   方法,node自带的,获取查询的字符串
* req.headers   请求体,node自带的,header取值时key都是小写的,获取请求头
* req.params 可以用来获取请求URL中的参数值

express路径支持正则写法

app.get(//article/d+/,function(req,res){
	//获取当前请求的路径 req.path
	let id=//article/(d+)/.exec(req.path)[1];
	res.end(`这是第${id}篇文章`)
})
上述方法也可以借助req.params获取路径参数。

app.get('/article/:id/',function(req,res){
    res.end(`第${req.params.id}文章详情`);
});

/article/1   /article/:aid=>params{aid:1}
/article/1/name/2 /article/:aid/name/:age=> params{aid:1,age:2}
这其中:aid相当于代表一个位置占位符,表示必须有,但是可以是随机的

use

中间件是一个处理函数,它是在路由匹配之间执行的,每个app.use表示一个中间件,它的特点是:

1、中间件在路由的最上面执行,先执行中间件,再执行路由
2、可以写路径,还可以不写路径,不写默认是'/'
3、可以扩展属性和方法,类似req.path,req.query将属性和方法放在req或者res上。
4、可以用next函数,决定是否向下执行,如果调用next则可以向下执行。
5、做权限判断
6、从中间件到路由的过程函数中的req和res是同一个,而且中间件可以写多个。
7、next中如果传递参数,就会执行错误中间件,错误中间件一般放在最后
主要功能就是扩展属性和方法,放置公共逻辑,权限判断
函数的length属性可以获取函数参数的个数

let http=require('http');
function app(req,res){
	let index=0;
	function next(){
		let fn=app.routes[index++];
		fn(req,res,next);
	}
	next();
}
app.routes=[];
app.use=function(fn){
	app.routes.push(fn);
}
app.use(function(req,res,next){
	console.log(1);
	next()
})
app.use(function(req,res,next){
	console.log(2);
})
http.createServer(app);
错误中间件
app.use((err,req,res,next)=>{
     console.log(err);
     res.end('权限出错')
});

路由中间件

1、实现划分路由模块,引用用户模块

app.use('/user',require('./user'));
前面的是访问的路径,后面的是引用的文件的路径,后面的require('./user')应该是一个函数
app.all("*",function(req,res){
	res.send('404');
})

2、导出用户模块

var express = require('express');
var router = express.Router();
router.get('/signin',function(req,res){//此时的路径相当于子路径,并且里面任然可以写小中间件。
    res.end('登录');
});
module.exports = router;

send

send方法向浏览器发送一个响应信息,并可以智能处理不同类型的数据,并在输出响应时会自动进行一些设置,比如HEAD信息,HTTP缓存支持等等。
1、当参数为一个String时或者Buffer,Content­Type默认设置为"text/html"
2、当参数为Array或Object时,Express会返回一个JSON
3、当参数为一个Number时,并且没有上面提到的任何一条在响应体里,Express会帮你设置一个响应体,比如:200会返回字符"OK"。

1.可以发送json
2.可以自动处理编码格式和类型
3.会自动将数字转化成对用statusText

app.use(function (req,res,next) {
  res.send = function (data) {
    if(typeof data=='string'|| Buffer.isBuffer(data)){
      res.setHeader('content‐type','text/html;charset=utf8')
      res.end(data);
    }else if(typeof data=='object'){
      res.setHeader('content‐type','application/json;charset=utf8');
      res.end(JSON.stringify(data));
	    }else if(typeof data=='number'){
	      res.statusCode=data;
	      res.end(require('_http_server').STATUS_CODES[data]);
		  }
	};
  next();
});

静态服务中间件

如果要在网页中加载静态文件(css、js、img),就需要另外指定一个存放静态文件的目录,当浏览器发出非HTML文件请求时,服务器端就会到这个目录下去寻找相关文件。

提供静态文件服务器,如果没有找到,则向下执行
let path=require('path');
app.use(express.static(path.resolve(__dirname,'views')))//views下的所有文件都是静态文件
实现static服务
let path=require('path');
let fs=require('fs');
let static=(url)=>(req,res,next)=>{
	//如果当前的URL和req.path拼接,如果这个文件存在读取这个文件,返回这个文件
    //如果文件不存在,调用next();
    let pathname=path.join(url,req.path);
    fs.existsSync(pathname,function(flag){
		if(flag){
			fs.readFile(pathname,function(err,data){
				res.end(data);
			})	
		}else{
			next();
		}	
	})
}

redirect

跳转路径,重定向到指定的url地址。redirect方法允许网址的重定向,跳转到指定的url并且可以指定status,默认为302方式。
res.redirect([status],url);

解析请求体

分别解析json类型和表单类型数据
接收的数据:
1、"{name:1,age:2}"json格式
2、"name=1&age=2" formData,通过from表单传递的数据

//body-parser第三方express插件,相当于中间件
let bodyParser=require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));如果前端传过来的是formData格式会用此中间件来解析
app.use(bodyParser.json());//如果前端传递过来的是json数据会执行此中间件来解析
app.post('/signup',function(req,res){
    res.send(req.body);//传递过来的数据解析后,放在req.body这个属性上
});
原文地址:https://www.cnblogs.com/Juphy/p/6985159.html