Artikel ini membawakan anda pengetahuan yang berkaitan tentang ekspres ialah rangka kerja pembangunan web yang pantas, terbuka dan minimalis berdasarkan platform Node.js.
Express ialah rangka kerja pembangunan web berdasarkan platform Node.js, 快速、开放、极简
. Membina pelayan web
Intipati Express: ia ialah pakej pihak ketiga pada npm, yang menyediakan cara mudah untuk mencipta pelayan web dengan cepat.
Menggunakan rangka kerja pembangunan Express, anda boleh mencipta pelayan laman web web atau pelayan antara muka API dengan sangat mudah dan pantas
Tapak web rasmi: https://www.expressjs.com.cn/
Muat turun dan pasang:
npm init -ynpm i express -S
Langkah untuk menggunakan:
const express = require('express')const app = express()app.get(路由,回调) // get是请求方法app.listen(端口号)
Kaedah permintaan juga menyokong:
get - query permintaan - syarat dalam lajur alamat
siaran - tambah permintaan - data dalam badan permintaan
letak - ubah suai permintaan - syarat dalam bar alamat - data dalam badan permintaan
padam - padam permintaan - syarat dalam bar Alamat
Setiap kaedah kata kerja digunakan untuk memproses permintaan yang sepadan. Kecuali untuk satu kaedah:
app.all() // 可以用来处理任意请求方式
Walaupun kaedah semua boleh mengendalikan sebarang permintaan, cuba gunakannya sesedikit mungkin, atau cuba untuk tidak menggunakannya.
Nyahpepijat menggunakan posmen
Padanan tepat
// 匹配根路径的请求app.get('/', function (req, res) { res.send('root');});// 匹配 /about 路径的请求app.get('/about', function (req, res) { res.send('about');});// 匹配 /random.text 路径的请求app.get('/random.text', function (req, res) { res.send('random.text');});
Bukan padanan tepat
// 匹配 acd 和 abcdapp.get('/ab?cd', function(req, res) { res.send('ab?cd');});// 匹配 abcd、abbcd、abbbcd等app.get('/ab+cd', function(req, res) { res.send('ab+cd');});// 匹配 abcd、abxcd、abRABDOMcd、ab123cd等app.get('/ab*cd', function(req, res) { res.send('ab*cd');});// 匹配 /abe 和 /abcdeapp.get('/ab(cd)?e', function(req, res) { res.send('ab(cd)?e');});
aksara ?, , * dan () ialah subset ungkapan biasa, - dan ditafsirkan secara literal dalam laluan berasaskan rentetan.
Padanan biasa:
// 匹配任何路径中含有 a 的路径:app.get(/a/, function(req, res) { res.send('/a/');});// 匹配 butterfly、dragonfly,不匹配 butterflyman、dragonfly man等app.get(/.*fly$/, function(req, res) { res.send('/.*fly$/');});
Gunakan fungsi panggil balik untuk memproses penghalaan:
app.get('/example/a', function (req, res) { res.send('Hello from A!');});
Pemprosesan berbilang :
app.get('/example/b', function (req, res, next) { console.log('这处理完之后会交给下一个函数处理'); next();}, function (req, res) { res.send('Hello from B!');});
Gunakan tatasusunan fungsi panggil balik untuk mengendalikan penghalaan:
var cb0 = function (req, res, next) { console.log('CB0') next()}var cb1 = function (req, res, next) { console.log('CB1') next()}var cb2 = function (req, res) { res.send('Hello from C!')}app.get('/example/c', [cb0, cb1, cb2])
Campurkan menggunakan fungsi dan tatasusunan fungsi untuk mengendalikan penghalaan:
var cb0 = function (req, res, next) { console.log('CB0') next()}var cb1 = function (req, res, next) { console.log('CB1') next()}app.get('/example/d', [cb0, cb1], function (req, res, next) { console.log('response will be sent by the next function ...') next()}, function (req, res) { res.send('Hello from D!')})
res.download() // 提示下载文件。 res.end() // 终结响应处理流程。 res.json() // 发送一个 JSON 格式的响应。 res.jsonp() // 发送一个支持 JSONP 的 JSON 格式的响应。 res.redirect() // 重定向请求。 res.render() // 渲染视图模板。 res.send() // 发送各种类型的响应。 res.sendFile() // 以八位字节流的形式发送文件。 res.sendStatus() // 设置响应状态代码,并将其以字符串形式作为响应体的一部分发送。
contoh muat turun:
// 响应下载 - res.download(被下载的源文件,下载后的文件名称,回调函数)res.download("./test.html",'b.html',err=>{ if(err){ console.log("下载失败"); }else{ console.log("下载成功"); }})
contoh json:
// 给客户端响应json数据// res.json(json格式的数据)let obj = { name:"张三", age:12, wife:"翠花", children:['阿大','阿二','小明']}res.json(obj)
contoh jsonp:
// 给客户端发起的jsonp请求做响应,响应的是json数据// res.jsonp(json格式的数据)let obj = { name:"张三", age:12, wife:"翠花", children:['阿大','阿二','小明']}res.jsonp(obj)
contoh ubah hala:
// res.redirect() 用来跳转路由的 - /a这个路由,其实/b这个路由就正好可以处理他,就可以在/a这个路由处理中,将这次请求交给/b这个路由去处理res.redirect('/index')app.get('/index',(req,res)=>{ let data = fs.readFileSync('./test.html') res.end(data)})
hantar contoh:
// res.send() - 用于给客户端响应字符串的 - 字符串中如果是标签,可解析成html - 自动设置数据类型和编码let html = ` <h2>这是一个h2标签</h2> `// res.end 不会自动设置数据类型,也不会设置编码// res.end(html)res.send(html)
sendFail contoh:
// res.sendFile() 用于给客户端响应一个文件res.sendFile(__dirname + '/test.html')
sendStatus contoh:
// sendStatus是自动设置响应状态码,并将对应的响应状态描述响应给客户端 res.sendStatus(404) // 响应 not found res.sendStatus(200) // 响应 ok
req.url // 请求的路径 - 如果有?传参,这个路径中也会带有参数 req.method // 请求方法 req.path // 请求路径 - 如果有?传参,这个路径中不包含参数 req.protocol // 协议 req.params // 获取get请求的参数 - 针对动态路由传参 - restful风格的参数 - 最终获取到的是对象,对象的键,就是路径指定的名称 req.query // 获取get请求的参数 - 针对传统形式传参 - 使用?参数 - 最终获取到的是对象
Express menyediakan kaedah yang sangat berguna yang dipanggil express.static()
Melalui kaedah ini, anda boleh mencipta pelayan sumber web statik dengan mudah:
app.use(express.static('public')) // app.use()表示使用(中间件) // 现在可以访问public目录下所有的文件 // 如public/aa.jpg文件,则可以通过 : http://xxxx/images/aa.jpg
express juga menyokong penciptaan. awalan fail maya untuk fail sumber statik (sebenarnya ia tidak wujud dalam sistem fail Anda boleh menggunakan fungsi express.static
untuk menentukan direktori statik maya, seperti berikut:
Maksud awalan:boleh mengelirukan orang lain dan menghalang orang lain daripada meneka struktur direktori pelayan kami pada tahap tertentu
- boleh membantu kami mengatur dan Mengurus dengan lebih baik sumber statik
app.use('/static', express.static('public'))
"/" di hadapan awalan mesti ditambah, jika tidak, ia akan menjadi salah. 【404】Kini anda boleh menggunakan
sebagai awalan untuk memuatkan fail dalam folder /static
: public
http://localhost:3000/static/images/kitten.jpg http://localhost:3000/static/css/style.css http://localhost:3000/static/js/app.js http://localhost:3000/static/images/bg.png http://localhost:3000/static/hello.html
Gunakan app.use( ) kaedahSetiap aplikasi boleh mempunyai berbilang direktori statik.biasanya ditulis sebelum pemantauan laluan tertentu.
app.use(express.static('public'))app.use(express.static('uploads'))app.use(express.static('files'))
pemetaan antara. Dalam Express, penghalaan merujuk kepada hubungan pemetaan antara permintaan (alamat) yang dimulakan oleh klien dan kaedah pemprosesan bahagian pelayan (fungsi).
Penghalaan dalam ekspres dibahagikan kepada tiga bahagian, iaitu permintaanjenis (kaedah), permintaan uri (alamat) dan fungsi pemprosesan yang sepadan .
Apabila permintaan pelanggan sampai ke pelayan, ia pertama kali dipadankan dengan peraturan penghalaan Hanya selepas perlawanan berjaya, fungsi pemprosesan yang sepadan akan dipanggil. Apabila dipadankan, ia akanpadanan dalam susunan penghalaan Jika jenis permintaan dan URL yang diminta berjaya dipadankan pada masa yang sama, Express akan memindahkan permintaan ke fungsi yang sepadan untuk. pemprosesan.
app.<get>(uri,(req,res)=>{})// use方法并不是请求类型方法,但是它放的位置与请求方法一致</get>
Pisah kepada beberapa fail penghalaan (fail js, satu fail js ialah modul).
Seperti namanya, penghalaan dimodulasikan,diuruskan dalam unit modul (fail js) dan burung-burung bulu berkumpul bersama .
Idea teras: bongkar jika boleh (bongkar sehingga tidak boleh dibongkar, nyahganding, kohesi tinggi, gandingan rendah). Apabila membangunkan projek, jika semua peraturan penghalaan dipasang ke dalam fail kemasukan, penulisan dan penyelenggaraan program akan menjadi lebih sukar. Oleh itu, ekspres menggunakan kaedah express.Router() untuk mencipta pengendali modular penghalaan untuk fungsi pengurusan modular penghalaan, yang boleh memisahkan keperluan perniagaan yang berbeza kepada modul yang berbeza, dengan itu memudahkan penyelenggaraan kod dan pengembangan projek. Langkah:app.use('/admin',adminRouter) // /admin开头的请求路径,交给adminRouter模块处理app.use('/front',frontRouter) // /front开头的请求路径,交给frontRouter模块处理
let {adminRouter} = require('./admin/admin')let {frontRouter} = require('./front/front')
导入的文件还未定义,创建文件
const express = require('express')const adminRouter = express.Router() // 创建路由对象// 通过路由对象处理剩余的请求adminRouter.get('/goods',(req,res)=>{ res.send('这是admin模块的goods页面')})// 导出模块module.exports = {adminRouter}
此时,我们又两种方案去处理请求:
同一个请求路径使用不同的请求方法多次请求的简写:
app.route('/book') .get(function(req, res) { res.send('Get a random book'); }) .post(function(req, res) { res.send('Add a book'); }) .put(function(req, res) { res.send('Update the book'); });
中间件(middleware)可以理解为业务流程的中间处理环节,可以理解成中间过滤器。
中间件可以分类可分如下几类:
内置中间件,也就是express本身自带无需npm安装
第三方中间件
非 Express 官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中可以通过npm进行安装第三方中间件并配置,从而提高项目的开发效率。例如body-parser (解析post数据的)此中间件可以很方便帮助我们获取到post提交过来的数据。
自定义中间件,开发者自己编写的(中间件的本质其实就是一个function)
如果从使用层面去考虑,中间件可以划分为:
express提供了好用的内置中间件,如提供一个静态资源管理的中间件,通过此中间件就可以帮助为我们快速搭建一个静态资源服务器:
app.use('前缀',express.static('托管目录地址'))
在express中,除了内置的express.static()
中间件,还内置了另外2个常用的中间件:
express.json()
app.use(express.json())
req
请求对象的body
属性上使用示例:
// 有了这个中间件以后,我们可以从客户端给服务器端发送json数据,这个json数据会放到请求对象req的body属性上app.use(express.json())app.post('/p1',(req,res)=>{ // express.json中间件可以让数据挂在req的body属性上 console.log(req.body); res.send('this p1 request is ended')})
首先必须是post请求,然后必须有数据,但是数据不能是以前的 x-www-form-urlencoded这样的数据,必须是raw的数据
然后请求头的content-type 必须是 application/json
express.urlencoded()
app.use(express.urlencoded({extended: false}))
req
请求对象的body
属性上注意,
- 后面提及的这2个常用内置中间件存在兼容性问题。
- 上述2个中间件都说把数据处理之后挂到req.body上,但是实际上并不会出现我们想的覆盖的问题。
案例:使用json、urlencoded中间件来接收json数据与表单post数据,发送可以通过postman来进行
自定义中间件,其本质就是定义一个处理请求的函数,只是此函数中除了有request和response参数外还必须包含一个next参数,此参数作用让中间件能够让流程向下执行下去直到匹配到的路由中发送响应给客户端。也可以通过给request对象添加属性来进行中间件数据的向下传递
function mfn(req,res,next){ //. 自己需要定义的逻辑流程 // 中间件最后一定要执行此函数,否则程序无法向下执行下去 next()}
注意:在整个请求链路中,所有中间件与最终路由共用一份req
和res
案例:依据上述的共用特性,自定义一个中间件来接收post提交的表单数据(意义:内置那中间件是不是存在兼容性问题)
在express中,其允许我们使用第三方的中间件来进行对数据进行处理。比较典型的例如:可以使用第三方中间件来接收post数据。
以使用body-parser
中间件来接收post数据为例,步骤如下:
body-parser
npm i -S body-parser
body-parser
app.use(body.urlencoded({extended: false}))
req.body
获数post中数据在使用的时候,
body-parser
库的语法与前面看的express内置的express.urlencoded
中间件的语法非常相似,原因是内置中间件是基于body-parser
来实现的。
其他第三方中间件:http-proxy-middleware/cors/cookie-session …
**作用:**专门用来捕获整个项目发生的异常错误,从而防止项目异常崩溃的问题产生(友好显示异常)。
**格式:**错误级别中间件的函数参数中,必须有四个形参,分别是(err,req,res,next)
问:多出来的err参数有什么作用呢?
答:里面包含了错误的信息,err.message属性中就包含了错误的文本信息,这个信息可以在中间件中输出给用户看。
app.get('/',(req,res) => { throw new Error('服务器内部发生了致命的错误!') res.send('Welcome to my homepage')})app.use((err,req,res,next) => { console.log('发生了错误:' + err.message) res.send('Error!' + err.message)})
**案例:**要求指定一个路径(可能路由对应的文件不存在),读取文件内容,输出给用户
注意事项:错误级别中间件要想发挥其作用,必须写在所有的路由的后面,是否是app.listen
之前无所谓。
**作用:**用于处理404的请求响应
// 假设定义这个路由,但是实际请求的时候请求了/12345,这个时候就会404app.post("/1234", (req, res, next) => { res.send('你请求成功了')});// 404的输出// 该中间件也需要写在最后(与异常中间件的顺序无所谓,只要确保其在所有的路由方法之后就可)app.use((req,res,next) => { // 输出404错误 res.status(404).send('<h1>404</h1>') // 先指定404状态码,然后再输出错误信息})
404错误中间件也要求在所有的正常请求路由的后面去声明使用,不要放在路由的前面,否则会导致后面的路由都是404错误。
**注意点:**错误级别的中间件,必须在所有路由之后注册,至于404中间件与异常中间件,谁先谁后无所谓。
模板页面:页面:https://404.life/
cookie的原理是在浏览器中开辟了一个用来存储http请求中的数据,第一次保存之后,下次请求只要还是使用的当前浏览器,就能访问到浏览器这个空间中的数据。
cookie会作为键值对,在响应头和请求头之间携带。
cookie的特点:
npm i cookie-parser -S
使用:
// 导入 const cookieParser = require('cookie-parser') // 中间件 app.use(cookieParser()); // 请求头获取 req.headers.cookie // 获取所有cookie // 响应头设置 res.cookie(键,值,{maxAge: 有效期-毫秒}) // 设置cookie
cookie是存储在浏览器的,所以安全性不高,所以一些重要数据就不能存储在cookie中,且cookie的存储空间有限制,所以就有了session。
session是存储服务器端的,session需要依赖cookie,session数据存储会在cookie中存放一个sessionid,这个sessionid会跟服务器端之间产生映射关系,如果sessionid被篡改,他将不会跟服务器端进行隐射,因此安全系数更高。且session的有效期比较短。通常是20分钟左右,如果浏览器在20分钟内没有跟服务器进行交互,服务器就会删除session数据。
npm i cookie-session -S
使用:
// 导入:const session = require('cookie-session')// session配置session({ name:"sessionId", secret:"asdfasdfqwer", // 给sessioinId加密使用的秘钥,随便填写 maxAge:20*60*1000 // 20分钟})// 设置sessionreq.session[键] = 值// 获取sessionreq.session[键]
npm i bcryptjs -S
使用:
var bcrypt = require('bcryptjs'); // 加密 密文 = bcryptjs.hashSync(明文[,数字]); // 数字,将使用指定的轮数生成盐并将其使用。推荐 10 // 验证 bcryptjs.compareSync(明文,密文); // 通过返回true,失败返回false
npm install jsonwebtoken
使用:
// 加密生成tokenvar jwt = require('jsonwebtoken');var token = jwt.sign(被加密的对象, 盐);// 验证jwt.verify(token, 盐, function(err, decoded) { // decoded是解密后的对象});
npm i multer -S
使用:
var multer = require('multer')var upload = multer({ dest: path.join(__dirname,'public','image') }) // 指定上传的文件路径app.post('/profile', upload.single('上传表单name值'), function (req, res, next) { // req.file 是上传的文件信息 - 可以从中获取到文件名称、路径、后缀 - 拼接路径存入mongodb})
npm i mysql -S
使用:
// 导入const mysql = require("mysql");// 创建连接对象const db = mysql.createConnection({ host:"localhost", user:"root", password:"root", database:"test"});// 连接db.connect(err=>{ if(err){ console.log("连接失败,错误:"+err); return; } console.log("连接成功");});// 执行语句db.query("",(err,result)=>{ if(err){ console.log("失败,错误:"+err); return; } console.log("成功"); console.log(result);});
npm i svg-captcha -S
使用:
const svgCaptcha = require('svg-captcha') // 创建验证码 let captcha = svgCaptcha.create(); // captcha是是一个对象,其中包含data键和text键,text是验证码上的字符,data是一个svg标签直接可以显示为一张图片
npm install nodemailer --save
使用:
const nodemailer = require('nodemailer')// 1. 创建发送器const transport = nodemailer.createTransport({ // 需要你发送放邮箱的 stmp 域名和密码和一些其他信息 // 需要你去复制一下, 找到下载的 nodemailer 第三方包 // nodemailer -> lib -> well-known -> services.json "host": "smtp.qq.com", "port": 465, "secure": true, // 证明你的身份 auth: { // 发送方邮箱的用户名 user: '邮箱号', // stmp 允许密码 pass: '授权码' }})// 2. 发送邮件transport.sendMail({ // 从那个邮箱发送 from: '发送方邮箱', // 发送到哪里, 可以写一个字符串, 书写邮箱, 也可以写一个数组, 写好多邮箱 to: ['接收方邮箱', '接收方邮箱'], // 邮件标题 subject: '标题', // 本次邮件的 超文本 内容 html: ` 您好: 本次的验证码是 <h1> 2345 </h1> 请在 3 分钟内使用 <br> ------------------------<br> 前途无限股份有限公司 `, // 本次邮件的 文本 内容 // text: ''}, function (err, data) { if (err) return console.log(err) console.log('邮件发送成功') console.log(data)})
在一个web应用程序中,如果只是使用服务器端代码来编写客户端html代码,前后端不分离,那么会造成很大的工作量,而且写出来的代码会比较难以阅读和维护。如果只是使用客户端的静态的HTML文件,那么后端的逻辑也会比较难以融入到客户端的HTML代码中。为了便于维护,且使后端逻辑能够比较好的融入前端的HTML代码中,同时便于维护,很多第三方开发者就开发出了各种Nodejs模板引擎,其中比较常用的就是Jade/Pug、Ejs和art-template 等模板引擎。
目的:使后端逻辑能够比较好的融入前端的HTML代码中,同时便于维护
网址:
art-template 是一个简约、超快的模板引擎。
开发模式:
传统开发模式:
前端代码和后端代码写在了一起
混合在了一起,但是这种文件有要求,文件通常都是后端语言的文件中才能写后端的逻辑 - 这样的话,对于我们前端攻城狮特别不友好,因为我们前端攻城狮负责html页面,但是在html页面中不能写后端的逻辑,如果将html页面放在后端的文件中,我们又需要学习后端语言
此时,模板引擎出现了 - 模板引擎其实就是让我们可以在html页面中书写后端的逻辑 - 循环/判断 …
模板引擎有很多种:jade/ejs/art-tamplate …
模板引擎最终能在html中写逻辑,相当于我们代码前后端混合在一起的一种语法,最终为什么能被浏览器所识别?因为浏览器在识别之前,我们的模板引擎需要进行编译 - html代码
前后端分离开发模式:
html一个人去写;
后端接口另一个人去写;
双方之间对接,使用接口文档
html上所有的数据,都是通过ajax请求回来,并通过dom操作显示在页面中的
模板引擎渲染速度测试:
特性
下载安装:
# 安装 npm i -S art-template express-art-template
配置:
// 模板引擎配置 // 指定art-template模板,并指定模块后缀为.html app.engine('html', require('express-art-template')); // 指定模板视图路径 app.set('views', path.join(__dirname, 'views')); // 省略指定模块文件后缀后名称(可选,在渲染时可以省略的后缀) app.set('view engine', 'html')
art-template 支持**标准语法与原始语法**。标准语法可以让模板易读写,而原始语法拥有强大的逻辑表达能力。标准语法支持基本模板语法以及基本 JavaScript 表达式;原始语法支持任意 JavaScript 语句,这和 Ejs一样。
使用art-template展示一个视图(html文件)
将视图放入views目录下(允许分目录)
编写代码,展示视图的方式是`res.redner(文件的路径)
app.get('/', (req, res) => { // 输出视图 res.render('404.html')})
控制层返回数据(在js控制层中赋值变量到视图中)
app.get(uri,(req,res)=>{ res.render(模板,{ username: '张三', age: 25, gender: '女', hobby: ['篮球','乒乓球','羽毛球'] })})
变量输出:
<!-- 标准语法 -->{{ username }}<!-- 或者 --><!-- 原始语法 -->
在默认情况下,上述输出方式不能将带有HTML标记的内容让浏览器解析,只会原样输出。如果需要将HTML标记让浏览器,则请使用下述方式输出数据:
<!-- 标准语法 -->{{@ username}}<!-- 原始语法 -->
条件判断:
{{if 条件}} … {{else if 条件}} … {{/if}} … …
循环:
<!-- 支持 数组和对象的迭代 默认元素变量为$value 下标为$index 可以自定义 {{each target val key}}-->{{each 循环的数据}} {{$index}} {{$value}} {{/each}} {{each 循环的数据 val key}} {{key}} {{val}} {{/each}}
如果使用默认的键、值的名字(index,value)则其前面的
$
一定要写!一定要写!!!如果使用的自定义的键、值的名字,则前面的
$
一定不能写!!不能写!!
模板导入:
{{include '被引入文件路径'}}
- 如果是当前路径下的一定要写
./
,不写则从磁盘根下开始寻找- 被include的文件后缀名默认为
.art
,如果不是请勿省略- 在子模板中最好不要有html、head和body标签(否则容易出现样式错误的问题)
模板继承:
被继承的模板:
<meta> <!-- 类似于vue的插槽 --> <title>{{block 'title'}}My Site{{/block}}</title> <!-- block占位符 content此占位的名称 --> {{block 'content'}}{{/block}}
需要继承的子模板:
<!--extend 继承 -->{{extend './layout.html'}} {{block 'title'}}首页{{/block}} {{block 'content'}} <p>This is just an awesome page.</p>{{/block}}
bootcss在线构建器:https://www.bootcss.com/p/layoutit/
更多编程相关知识,请访问:编程入门!!
Atas ialah kandungan terperinci Disyorkan untuk mengumpul! Bawa anda selangkah demi selangkah dan ajar anda cara bermula dengan ekspres. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!