[关闭]
@Wangww0925 2019-08-07T08:02:22.000000Z 字数 9643 阅读 241

express 框架 【代替node原生http模块写法】

NodeJs


什么是express

Express框架是后台的javascript框架

为什么要使用express

原生Node开发,会发现有很多问题。比如:
    1. 呈递静态页面很不方便,需要处理每个HTTP请求,还要考虑304问题
    2. 路由处理代码不直观清晰,需要写很多个条件分支

总之原生Node开发不能集中精力写业务,要考虑很多其他的东西。所以,express可以帮助我们解决上述问题

安装Express框架 npm install express --save

--save参数,表示自动修改package.json文件,自动添加依赖项

参数

  1. var express = require("express");
  2. var app = express(); // 创建服务器
  3. console.log(app)

app 参数

  1. app.get(url, callback(req,res)); - get请求访问网址
  2. app.post(url, callback(req,res)); - post访问网址
  3. app.all(url, callback(req,res)); - 不管是get请求还是post请求
  4. use()
  5. listen()
  6. set()
  7. [EventEmitter: app]
  8. _events: { mount: [Function: onmount] },
  9. _eventsCount: 1,
  10. _maxListeners: undefined,
  11. setMaxListeners()
  12. getMaxListeners()
  13. emit()
  14. addListener()
  15. on()
  16. prependListener()
  17. once()
  18. prependOnceListener()
  19. removeListener()
  20. off()
  21. removeAllListeners()
  22. listeners()
  23. rawListeners()
  24. listenerCount()
  25. eventNames()
  26. init()
  27. defaultConfiguration()
  28. lazyrouter()
  29. handle()
  30. route()
  31. engine()
  32. param()
  33. path()
  34. enabled()
  35. disabled()
  36. enable()
  37. disable()
  38. acl()
  39. bind()
  40. checkout()
  41. connect()
  42. copy()
  43. delete()
  44. head()
  45. link()
  46. lock()
  47. 'm-search'()
  48. merge()
  49. mkactivity()
  50. mkcalendar()
  51. mkcol()
  52. move()
  53. notify()
  54. options()
  55. patch()
  56. propfind()
  57. proppatch()
  58. purge()
  59. put()
  60. rebind()
  61. report()
  62. search()
  63. source()
  64. subscribe()
  65. trace()
  66. unbind()
  67. unlink()
  68. unlock()
  69. unsubscribe()
  70. del()
  71. render()
  72. request()
  73. response()
  74. cache()
  75. engines()
  76. settings {
  77. 'x-powered-by': true,
  78. etag: 'weak',
  79. 'etag fn': [Function: generateETag],
  80. env: 'development',
  81. 'query parser': 'extended',
  82. 'query parser fn': [Function: parseExtendedQueryString],
  83. 'subdomain offset': 2,
  84. 'trust proxy': false,
  85. 'trust proxy fn': [Function: trustNone],
  86. view: [Function: View],
  87. views:
  88. 'C:\\Users\\Dooban000\\Desktop\\node\\6.5-06\\NodeJs_06\\views',
  89. 'jsonp callback name': 'callback'
  90. },
  91. locals {
  92. settings {}
  93. },
  94. mountpath: '/'

request 和 response 对象的具体介绍

  1. Request 对象 - 表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性
  2. req.app - callback为外部文件时,用req.app访问express的实例
  3. req.originalUrl - 获取原始请求URLreq.baseUrl + req.path】,例 /login/frsgrg/gtrgrtg/gtgtg/gwg
  4. req.baseUrl - 获取路由当前安装的URL路径,例 /login
  5. req.path - 获取请求路径,例 /frsgrg/gtrgrtg/gtgtg/gwg
  6. req.params - 获取路由的parameters
  7. req.query - 获取URL的查询参数串
  8. req.body & req.cookies - 获得「请求主体」/ Cookies
  9. req.fresh & req.stale - 判断请求是否还「新鲜」
  10. req.hostname & req.ip - 获取主机名和IP地址
  11. req.protocol - 获取协议类型
  12. req.route - 获取当前匹配的路由
  13. req.subdomains - 获取子域名
  14. req.accepts() - 检查可接受的请求的文档类型
  15. req.acceptsCharsets & req.acceptsEncodings & req.acceptsLanguages - 返回指定字符集的第一个可接受字符编码
  16. req.get() - 获取指定的HTTP请求头
  17. req.is() - 判断请求头Content-TypeMIME类型
  18. =======================================================================================
  19. Response 对象 - 表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据
  20. res.app - req.app一样
  21. res.send() - 结束请求,传送HTTP响应
  22. res.append() - 追加指定HTTP
  23. res.cookie(name, value, [option]) - 设置Cookie opition: domain / expires / httpOnly / maxAge / path / secure / signed
  24. res.clearCookie() - 清除Cookie
  25. res.download() - 传送指定路径的文件
  26. res.get() - 返回指定的HTTP
  27. res.json() - 传送JSON响应
  28. res.jsonp() - 传送JSONP响应
  29. res.location() - 只设置响应的Location HTTP头,不设置状态码或者close response
  30. res.redirect() - 设置响应的Location HTTP头,并且设置状态码302
  31. res.render(view,[locals],callback) - 渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
  32. res.sendFile(path, [options], [fn]) - 传送指定路径的文件 -会自动根据文件extension设定Content-Type
  33. res.set() - 设置HTTP头,传入object可以一次设置多个头;res.set()在res.append()后将重置之前设置的头
  34. res.status() - 设置HTTP状态码
  35. res.type() - 设置Content-TypeMIME类型


请求

请求注意事项:

url路由路径,可以忽略大小写

可以采用链式调用方法处理不同的路由

如果想使用不同的状态码,可以 res.status(404).send('内容');

如果想使用不同的Content-Type,可以 res.set('Content-Type', 'Mime类型');

app.get() 【get请求访问网址】

  1. app.get(url, callback(req,res));

例子:

node 执行文件 test.js

  1. var express = require("express");
  2. var app = express(); // 创建服务器
  3. app.get("/",(req,res)=>{
  4. res.send("<h1>hahahaha</h1>");
  5. })
  6. app.listen(8081);

执行命令

  1. npm install express --save
  2. node test.js

app.post() 【post访问网址】

  1. app.post(url, callback(req,res))

例子:

node 执行文件 test.js

  1. var express = require("express");
  2. var app = express(); // 创建服务器
  3. app.post("/",(req,res)=>{
  4. res.send("<h1>post请求</h1>")
  5. })
  6. app.listen(8081);

执行命令

  1. npm install express --save
  2. node test.js

app.all() 【不管是get请求还是post请求】

  1. app.all(url, callback(req,res));

例子:

node 执行文件 test.js

  1. var express = require("express");
  2. var app = express(); // 创建服务器
  3. app.all("*",(req,res)=>{
  4. res.status(404).send("<h1>404</h1>")
  5. })
  6. app.listen(8081);

执行命令

  1. npm install express --save
  2. node test.js

路由模糊匹配 app.get("/:content/:content1", callback(req,res)); 【req.params.content获取值】

表示模糊匹配路由路径内容,可以匹配任何路由路径的形式为/sfdsfdsf/sdsfsf

可以把 content 和 content1 当做变量 然后通过 req.params 来拿到值

req.params 为对象

例子:

node 执行文件 test.js

  1. var express = require("express");
  2. var app = express(); // 创建服务器
  3. app.get("/:number/:id",(req,res)=>{
  4. console.log(req.params);
  5. var number = req.params.number;
  6. var id = req.params.id;
  7. res.send(`${number}:::::${id}`);
  8. })
  9. app.listen(8081);

执行命令

  1. npm install express --save
  2. node test.js

效果图
image_1d29vqsu4c2iago691pnm1om19.png-11.4kB


app.use();

  1. app.use(url,callback(req,res));

注意:

匹配路由前缀,只要前缀匹配成功,那么所有的路由都会被执行

当路由路径为根路径的时候,express规定路由路径参数可以不写  【app.use("/",(req,res)=>{}) =>  app.use((req,res)=>{})】

例子:

  1. var express = require("express");
  2. var app = express();
  3. app.use((req,res)=>{
  4. res.send("aaa");
  5. })
  6. app.listen(8081);


res.send() 结束请求

PS:res.send() 可以发送任何数据类型的数据,原生的nodejs发送的数据类型只能为字符串或者buffer

注意: 同个请求中不能有两个 res.send()

res.send("字符串") 【使用一】

PS:自动添加请求头text/html

例子:

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Document</title>
  6. </head>
  7. <body>
  8. <h1>hello world</h1>
  9. </body>
  10. </html>

node 执行文件

  1. var express = require("express");
  2. var fs = require("fs");
  3. var app = express(); // 创建服务器
  4. app.all("/",(req,res)=>{
  5. fs.readFile("./index.html",(err,data)=>{
  6. if(err){
  7. console.log(err);
  8. }
  9. if(!err){
  10. res.send(data.toString());
  11. }
  12. })
  13. });
  14. app.listen(8081);

效果图:
image_1d29ud3e8fiitfi1qp0bl02bgp.png-12.8kB

res.send(数组或对象) 【使用二】

PS:自动添加请求头application/json
json是一种数据传输格式,json包含有json数组和json对象
在发送对象或者数组的时候已经将数组或者对象进行转换为json字符串了

例子:

node 执行文件

  1. var express = require("express");
  2. var app = express(); // 创建服务器
  3. app.get("/",(req,res)=>{
  4. res.send([1,2,3,4,5,6]);
  5. })
  6. app.listen(8081);

效果图:
image_1d29uvfut1jerneqa2d1fql1hg916.png-12.9kB

res.send(buffer) 【使用三,不推荐】

PS:自动添加请求头 applicaiton/octet-stream

例子:

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Document</title>
  6. </head>
  7. <body>
  8. <h1>hello world</h1>
  9. <img src="1.jpg" alt="">
  10. </body>
  11. </html>

node 执行文件

  1. var express = require("express");
  2. var fs = require("fs");
  3. var app = express(); // 创建服务器
  4. app.all("/",(req,res)=>{
  5. fs.readFile("./index.html",(err,data)=>{
  6. if(err){
  7. console.log(err);
  8. }
  9. if(!err){
  10. // res.send(data)时,如果读取流中存在路径,则浏览器会下载
  11. res.send(data);
  12. }
  13. })
  14. });
  15. app.listen(8081);

效果图
image_1d2a0gv2n1rkr97u16m810kah2em.png-18.1kB

问题:res.send(data)时,如果读取流中存在路径,则浏览器会下载

因为在send的时候,express会自动识别内容,然后添加相对用的content-type类型。

当发送的内容为buffer对象的时候,添加的content-type类型为 application/octet-stream。但是浏览器不能识别解析这一种mime类型,所以只能下载

解决方法: 将buffer转换成字符串,即【使用一】 res.send(data.toString());


静态文件处理 app.use(express.static("文件夹"));

例子:

node执行文件

  1. var express = require("express");
  2. var app = express(); // 创建服务器
  3. // app.use("/", express.static("./project")); // "/" 可以省略
  4. app.use(express.static("./project"));
  5. app.listen(8081);

效果图
image_1d2a1g62nv1imamjsd1l99afe13.png-347.1kB


express框架 结合 ejs模板 【res.render() 数据绑定】

需要在应用中进行如下设置才能让 Express 渲染模板文件

  1. app.set('views', './test'); // 默认为这个目录; views: 放模板文件的目录
  2. app.set('view engine', 'ejs'); // 显示指定模板引擎为ejs; 【view engine: 模板引擎】

例子:

test/index.ejs

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Document</title>
  6. </head>
  7. <body>
  8. <h1>ejs</h1>
  9. <ul>
  10. <% for(var i=0;i<arr.length;i++){ %>
  11. <li><%= arr[i] %></li>
  12. <% } %>
  13. </ul>
  14. </body>
  15. </html>

node执行文件

  1. var express = require("express");
  2. var app = express(); // 创建服务器
  3. app.set("views","./test"); // 设置ejs模板存放的地方
  4. app.set("view engine","ejs"); // 显示指定模板引擎为ejs
  5. var data = {
  6. arr:['html',"css",'javascript']
  7. }
  8. app.get("/",(req,res)=>{
  9. res.render("index", data); // 数据替换
  10. })
  11. app.listen(8081);

效果图
image_1d2bpbba28p9p8v1tnt1c7kippm.png-13kB


中间件 app.get("/",(req,res,next)=>{})

在express中路由路径的匹配是从上往下匹配的,如果有一个匹配成功,就不会再去匹配下面的路由路径,这个时候如果想让他继续去匹配其他的路由就需要使用next中间件了

注意:不一定是get请求,可以是 app.use() 等

如何理解中间件的作用?

中间件可以预先处理所有请求再转交给特定的路由来进行处理。

例子:

node执行文件

  1. var express = require("express");
  2. var app = express();
  3. // 中间件
  4. app.get("/",(req,res,next)=>{
  5. console.log("11111")
  6. res.send("hahaha");
  7. next();
  8. })
  9. app.get("/",(req,res)=>{
  10. console.log("22222");
  11. })
  12. app.listen(8081);

效果图
image_1d2c2qufe1uus1o4473g5f53hp13.png-97.5kB

例子: 模糊匹配路径

node执行文件

  1. var express = require("express");
  2. var app = express();
  3. // /teacher/123456
  4. // /student/1234567891
  5. app.get("/:username/:id",(req,res,next)=>{
  6. var username = req.params.username;
  7. var id = req.params.id;
  8. if(username == "teacher" && /^\d{6}$/.test(id)){
  9. res.send(`查询的老师id为:${id}`);
  10. return;
  11. }
  12. if(username == "student" && /^\d{10}$/.test(id)){
  13. res.send(`查询的学生id为:${id}`);
  14. return;
  15. }
  16. next();
  17. })
  18. app.get("/:username/:id",(req,res,next)=>{
  19. res.send("输入错误");
  20. next();
  21. })
  22. app.get("*",(req,res)=>{
  23. res.status(404).send("no resource")
  24. })
  25. app.listen(8081);

效果图
image_1d2c344aq79k1u7g1pcl1rnf12i91g.png-246.2kB


express中get请求和post请求的参数 【req.query 获取URL的查询参数串 & body-parser模块】

get请求

GET请求的参数在URL中,在原生Node中,需要使用url模块来识别参数字符串。在Express中,不需要使用url模块了。可以直接使用req.query对象。

post请求

POST请求在express中不能直接获得,必须使用body-parser模块。使用后,将可以用req.body得到参数。但是如果表单中含有文件上传,那么还是需要使用formidable模块
  1. var bodyParser = require('body-parser')
  2. app.post("/login",bodyParser.urlencoded({extended:false}),(req,res)=>{
  3. res.send(req.body);
  4. })

例子

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Document</title>
  6. </head>
  7. <body>
  8. <form action="/login" method="get">
  9. 用户名: <input type="text" name="username">
  10. <br>
  11. 密码: <input type="text" name="password">
  12. <br>
  13. <button>提交</button>
  14. </form>
  15. </body>
  16. </html>

PS:根据请求方式修改 method="get"

node 执行的文件

  1. var express = require("express");
  2. var fs = require("fs");
  3. var bodyParser = require('body-parser')
  4. var app = express();
  5. app.get("/",(req,res)=>{
  6. fs.readFile("./index.html",(err,data)=>{
  7. res.send(data.toString());
  8. })
  9. })
  10. // get请求
  11. app.get("/login",(req,res)=>{
  12. res.send(req.query);
  13. })
  14. // post请求
  15. app.post("/login",bodyParser.urlencoded({extended:false}),(req,res)=>{
  16. res.send(req.body);
  17. })
  18. app.listen(8081);

get请求效果图
image_1d2c53frn1kh1fqp1ljp1e8f7v147.png-16.9kB

post请求效果图
image_1d2c50frc5ha70p1rmmsgs1sds2a.png-11.5kB


作者 wendy
2019 年 1月 21日

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注