详解express搭建http服务,通过路由和中间件获取静态文件和动态数据的实现原理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解express搭建http服务,通过路由和中间件获取静态文件和动态数据的实现原理相关的知识,希望对你有一定的参考价值。
express方法
Express是一个简洁、灵活的node.js Web应用开发框架,是目前最流行的基于Node.js的Web开发框架. 它提供一系列强大的功能,比如:
模板解析
静态文件服务
中间件
路由控制
在node中使用express创建一个http请求,具体步骤如下:
1,引入express模块
2,执行express方法
3,express方法执行后返回一个http的监听函数,可以用返回的函数监听端口
通过使用中间件请求静态资源
express搭建服务
let express=require("express");
let app=express();
app.listen(8080);
express函数执行后,返回的是一个http的监听函数,就是http.createServer中的函数
在此函数上扩展了一个listen可以监听端口,app.listen就是基于以前封装的
app.listen=function (...arg) {
require("http").createServer(app).listen(...arg)
}
app.listen(8080,()=>{
"8080端口已开启"
})
基于express的监听函数app上扩展了很多的方法
express路由
必须method和path全都匹配上执行对应的callback
1.在处理请求路径和方式上,指明了请求的方式,包括get post delete put,RESTful风格中的动词,与之前相比不需在进行判断了
app.get("/sigin",function (req,res) {
res.setHeader("content-type","text/plain;charset=utf-8");
res.end("登录");
});
app.post("/sigin",function (req,res) {
res.setHeader("content-type","text/plain;charset=utf-8");
res.end("post登录");
});
//all表示所有的方法,*表示所有的路径,一般放到最后
app.all("*",function (req,res) {
res.end("404")
})
若请求localhost:8080/sigin,则返回登录
参数路由:
在路径中针对同一路径,我们可以通过路由参数,区分查一个或者多个内容,所有的路由参数都放到req.params对象中,
app.get("/user",function (req,res) {
res.end("select all")
});
app.get("/user/:id/:name",function (req,res) {
res.end("select one"+req.params.id+req.params.name);
});
2.如果想拿到请求的路径参数可以使用app.params()方法拿到,此方法具有拦截功能,只有调用了next()方法后才继续往下走
app.param("id",function (req,res,next) {
req.params.id=`你的学号是${req.params.id}`;
//res.end("123")
next();//调用了next就可以向下匹配,如果在这里结束了请求那就不走了
});
app.param("name",function (req,res,next) {
req.params.name=`你的名字是${req.params.name}`;
next();
})
app.get("/user/:id/:name",function (req,res) {
res.header("content-type","text/plain;charset=utf-8");
res.end("select one"+req.params.id+req.params.name);
});
响应成功返回内容:select one你的学号是1你的名字是md
中间键
访问到最终目标之前做一些事情,那么app.use()方法就可以
app.use()
1)功能
1.可以进行权限判断
2.可以对res和req的属性进行扩充
3中间键放在要执行的路径上面
4中间键默认情况下都匹配,可以指定匹配什么开头
2) 使用
在匹配路由,返回数据之前,如果我们想做一些事情,也可以使用中间件
app.use(function (req,res,next) {//不调用next就不继续往下走
console.log("过滤石头");
req.stone="too big";
res.end("hello");
next();
// next("错误");
});
app.use(function (req,res,next) {//不调用next就不继续往下走
console.log("过滤沙子");
req.sand="too small";
next();
});
app.get("/foot",function (req,res) {
console.log(req.stone,req.sand);
res.end("foot");
})
app.get("/water",function (req,res) {
console.log(req.stone,req.sand);
res.end("water");
});
app.use(function (err,req,res,next) {
console.log(err);
next();
})
如果next()里面传了参数,中间键走拥有四个参数的方法,即最后的方法
3)方法封装原理
function app() {
//每次调用use方法都会将方法存到数组中,默认调用数组的第一项,将next方法传递给数组中的函数,如果调用次函数 会继续执行数组中的下一项
app.middlereware=[];
}
app.use=function (cb) {
this.middlereware.push(cb);
};
app.use(function (res,req,next) {
console.log(1);
next();
});
app.use(function (res,req,next) {
console.log(2);
next();
});
app.use(function (res,req,next) {
console.log(3);
});
let index=0;
function next() {
app.middlereware[index++](null,null,next);
};
next();
扩展了res,req里的一些属性和方法
1)req上扩展的属性和方法
req.query.id 获取路由参数
req.path 获取路径
let express=require("express");
let app=express();
app.listen(8081);
app.get("/user",function (req,res) {
console.log(req.query.id);//express扩展的属性
console.log(req.url);//获取整个路径包括问号
console.log(req.path);//express扩展的属性
console.log(req.headers);//所有的都是小写
console.log(req.method);//所有的方法都是大写
})
2)res上扩展的属性和方法
1,res,json(),直接返回json格式的字符串返回
以前响应返回的数据需要通过JSON.stringFly()转化之后才能返回
app.get("/json",function (req,res) {
res.json({name:"你好",age:8});//响应json
});
2,以前返回一个页面文件需要通过fs读取,现在可以通过res.sendFile()方法拿到,路径必须是绝对路径
app.get("/",function (req,res) {
// res.sendFile("./index.html",{root:__dirname});不能通过../查找(root是不支持的)想读取到确切的文件 用path模块进行拼接即可
res.sendFile(require("path").join(__dirname,"..","index.html"))
});
3.返回状态码无需通过res.setStateCode(),可以使用res.send(),也可以返回中文,无需设置响应头的类型,可以根据返回的数据类型,自动设置返回的响应头类型
app.get("/send",function (req,res) {
// res.send("中文")
res.send(200)
});
send()方法的封装
app.use(function (req,res,next) {
res.mySend = function (data) {
if(typeof data === ‘object‘){
res.setHeader(‘Content-Type‘,‘application/json;charset=utf8‘);
return res.end(JSON.stringify(data));
}
if(typeof data === ‘string‘){
res.setHeader(‘Content-Type‘,‘text/plain;charset=utf8‘);
return res.end(data);
}
if(typeof data === ‘number‘){
res.statusCode = data;
res.end(require(‘_http_server‘).STATUS_CODES[data]);
}
};
next();
});
app.get(‘/send‘,function (req,res) {
res.mySend(500);
}
路由拆分(设置二级路由)获取动态数据
可以通过express上可以通过express.Router()和中间件设置子级路由把所有的子路由都放在一个routes文件夹下,该文件夹下可以放置多个相同的模块,每个模块中都需要引入express模块,设置子路由的路径和相应的方法,并将该模块导出moudle.export={},然后在主模块中引用routes文件夹子模块,通过require,然后通过中间件use()方法,匹配二级路由
let express = require(‘express‘);
let app = express();
let router = express.Router();
router.get(‘/login‘,fn)
app.use(‘/user‘,router);
bodyParser
app.use(bodyParser.json()); // 解析json application/json
app.use(bodyParser.urlencoded({extented:true})); // 解析表单 application/x-www-form-urlencoded
ejs用法
<!--引入模板--> <%include header.html%> <!--取值--> <h1><%=username%></h1> <p><%=password%></p> <!--js语句--> <%arr.forEach(item=>{%> <li><%=item%></li> <%})%> <!--转译--> <%-html%>
ejs模板渲染的文件默认是带有ejs后缀的文件,并且是放在当前目录下的view文件夹,并且在拿到数据后想要通过render函数渲染数据的话,渲染的模板文件是带有ejs后缀的,可以通过中间件把模板文件的后缀更改成html,view文件夹的名字更改为static文件
//更改默认模板的后缀
app.engine(‘html‘,require(‘ejs‘).__express);
// 更改模板路径,默认叫views
app.set(‘views‘,‘static‘);
// 配置默认模板后缀名字
app.set(‘view engine‘,‘html‘);
静态服务中间件
通过express.static()请求文件文件
app.use(express.static(‘文件夹‘))
重定向
res.redirect(‘路径‘);
由此我们就可以基于express方法搭建一个http,服务,通过express.Router(),搭建子级路由,获取和响应数据,通过express.static()方法可以请求静态资源,通过app.use()中间,对请求的路由,数据,响应的数据进行再处理,从而提高了整个hhtp请求的可控性
以上是关于详解express搭建http服务,通过路由和中间件获取静态文件和动态数据的实现原理的主要内容,如果未能解决你的问题,请参考以下文章