当前位置: 首页 > news >正文

从零开始学Express,理解服务器,路由于中间件

        当我们初学前端时,常常只关注页面效果和交互,但随着项目复杂度提升,我们迟早会遇到“服务端”的问题:如何让一个页面的数据是从数据库来的?怎么让不同的用户看到不同的内容?这时候,我们就需要一个后端框架来帮我们处理这些需求。而对于 JavaScript 开发者来说,Express 是入门服务端开发最友好的一把钥匙。

        本文不会长篇大论地讲解底层原理,而是通过最直观、最简单的方式,带你快速理解:什么是服务器、路由、中间件,以及 Express 的核心用法。如果你刚刚接触 Node.js,希望用它写点后端的东西,这篇文章就是为你准备的。

 1.Express的简单使用

        express 是node中的服务器软件(封装的http模块),通过express可以快速的在node中搭建一个web服务器。

        使用步骤

        1.创建初始化项目

                创建文件夹然后终端输入 npm init -y

        2.安装express

                npm install express

      3.创建index.js 编写代码

//引入express
const express = require('express')
//一切皆对象服务器在程序里面也是对象
//获取服务器的实例对象
const app = express()
/*如果希望服务器可以正常访问 则需要为服务器设置路由路由可以根据不同的请求方式和请求地址来处理用户请求app.METHOD(...)METHOD可以是get post中间件-在express中我们使用app.use定义一个中间件中间件和路由很像 用法很像通常情况下 我们访问的直接是路由 但是有时候想要加一个中间件但是路由不区分请求的方式 只看路径只要访问的路径包含它就可以访问到和路由的区别1.会匹配所有的请求2.路径设置父目录
*/
//中间件
//next是回调函数的第三个参数 调用函数后可以触发后续的中间件 
app.use('/',(req,res,next)=>{console.log('收到请求')// res.send('中间件给你的响应')next()//next不能在响应处理完毕之后调用
})
app.use('/',(req,res)=>{console.log('收到请求')res.send('中间件给你的响应2222')})
//中间件用来干嘛 可以用来设置访问路由之前的权限 相当于访问路由之前设置一些(公关)处理
//http://localhost:3000 
//现在创建了一个路由 / (路由是接口)
//路由的回调函数执行的时候 会接受三个参数
//第一个 request 第二个response 
app.get('/hello',(req,res)=>{console.log('有人访问我了')//在路由中 应该做两件事//读取用户的请求(request)//req表示用户的请求信息 通过req可以获取用户的传递数据console.log(req.url)//用户请求的路由//根据用户的请求返回响应(response)//res表示服务器发送给客户端的响应信息//sendStatus()像客户端发送响应状态码// res.sendStatus(9999999)//status只是设置了状态码没有发送res.status(200)//send设置发送响应体res.send('这是我给你的东西 但其实没东西')
})
//启动服务器
//app.listen(端口号)用来启动服务器
//服务器就像一个房子就我们的计算机有非常多的软件
//怎么识别我们的服务器软件 
//端口楼里面的门牌号 3000端口号房间号 就是express服务你
//后面可以加一个回调函数 服务器启动后执行函数 现在可以通过3000端口访问服务器
//协议名://ip地址:端口号/路径
//http://localhost:3000/index.js localhost ===  127.0.0.1都是指本计算机
app.listen(3000,()=>{console.log('服务器已经启动')
})

        这就是一个基础的使用,我们访问http://localhost:3000/hello就会返回给你send()里面的内容。状态码在自定义,定义接收请求的路由格式app.METHOD('路径',(req,res)=>{})req,res通过传递函数调用函数时候参数拿过来直接用,这里就是我们的请求信息和响应信息。 

        中间件就是当我们访问路由的时候,如果设置了中间件,就会被中间件拦截,这里就是可以给路由设置一些权限要求等。

2.nodemon工具以及中间件的作用

       目前服务器代码修改后必须重启,希望有一种方式可以监视代码的修改。代码修改以后可以自动重启服务器 需要安装一个模块 nodemon(监视器)

        使用方式

                1.全局安装 npm install nodemon -g

        终端输入nodemon 就可以了 修改代码可以自动重启

        默认启动当前目录的index.js 如果不是index.js 加上名字 nodemon ./01_helloworld.js

                2.在项目中安装 npm install nodemon -D 开发依赖

                启动 npx nodemon npx执行node模块

        当我们创建express实例之后,实际上express有非常多的功能的。但是我们需要在中间件之中进行配置。比如我们希望当我们get访问http://localhost:3000/index.html。

        也就是服务器的代码希望可以被外部直接访问,我们就需要在中间件中配置静态资源目录。可以将页面html以及图片放进去这样可以从服务器获取到这些代码。

const express = require('express')
const path = require('node:path')
//创建服务器实例
const app = express()
//use()中间件
//配置路由 
//设置这个中间件之后 浏览器访问时会自动去public目录下寻找是否有静态资源
app.use(express.static(path.resolve(__dirname,'./public')))
app.get('/',(req,res)=>{/*希望用户访问我的根目录 我可以返回一个网页*/res.send('')
})
app.get('/login',(req,res)=>{//获取到用户名和密码//req.query表示查询字符串中的请求参数console.log(req.query)console.log(req.query.username)if(req.query.username==='奥巴马'&&req.query.password==='123123'){console.log('请求收到')res.send('登录成功')}else{res.send('登录失败')}
})
//启动服务器
app.listen(3000,()=>{console.log('服务器启动')
})

        这样我们就可以直接从浏览器获取到服务器中的页面了。用express.static设置静态文件目录,然后把希望外部可以直接访问的资源放进去就可以了。就可以通过文件名直接访问了。

        这里req和res就是请求和响应信息。

3.get请求的两种参数传递以及post请求

           1.get请求

 <form action="/login" method="get"><div>用户名 <input type="text" name="username"></div><div>密码 <input type="text" name="password"></div><div><input type="submit" value="登录"></div></form>
const express = require('express')
const path = require('node:path')
const app = express()
//配置一个静态资源的路径
//express很多功能都是中间件引入的
app.use(express.static(path.resolve(__dirname,'./public')))
//引入解析请求体的中间件
app.use(express.urlencoded())
///开头的路径 叫做绝对路径 /login实际上是 http://localhost/login
app.get('/login',(req,res)=>{if(req.query.username==='admin'&&req.query.password === '123123'){res.send('<h1>登录成功</h1>')}else{console.log('<h1>登录失败</h1>')}
})

        当我们直接用get方法发送请求的时候,我们在输入框输入的数据会在req.quert中以对象的形式传递过来,而我们直接在路径上设置参数的话。

//get请求发送参数第二种方式
///hello/:id 表示访问/hello/xxx时就会触发
//在路径中以冒号命名的部分我们称为param 在get请求它会被解析为请求参数
//params传递参数一般不会特别复杂 一般就是一个
app.get('/hello/:id',(req,res)=>{//约定由于配置//可以通过req.params获取参数console.log(req.params)//{ id: '123', age: '12', gender: '男' }res.send('<h1>这是hello路由</h1>')
})

        就会存储到params中,而且这个参数是在地址栏里面填写的。两种方式本质是相同的,params按照顺序传递。

        2.post请求

        post请求需要请求体,也就是body。但是我们express默认是没有给我们添加这个功能的,我们可以用中间件添加这个功能。

//引入解析请求体的中间件
app.use(express.urlencoded())
app.post('/login',(req,res)=>{console.log(req.query) //{}//默认情况下express不会自动解析请求体 需要中间件添加功能console.log(req.body)const username = req.body.usernameconst password = req.body.passwordif(username==='admin'&&password==='123123'){res.send('<h1>登录成功</h1>')}else{res.send('登录失败')}
})

        然后就可以接收post请求了。参数通过body拿取。

4.简单的登录案例 

        我们现在会写get和post路由了,那么我们就可以写简单的登录案例,比如当我们登录的时候,发送请求到这个路由,然后携带参数过来。我们提前写死一些账户然后进行对比,有的话就登录没有的话就返回登录失败。还有注册功能,当我们访问的注册路由的时候,携带参数过来,如果写死的账户里面没有,那么就用数组的方法把注册的参数数据推进去形成新用户。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h1>我是一个静态网页</h1><hr><h2>登录</h2><form action="/register" method="post"><div>用户名 <input type="text" name="username"></div><div>密码 <input type="password" name="password"></div><div>确认密码 <input type="password" name="repwd" placeholder="确认密码"></div><div><input type="texx" name="nickname" placeholder="昵称"></div><div><input type="submit" value="登录"></div></form>
</body>
</html>
const express = require('express')
const path = require('node:path')
const app = express()
//创建一个数组存储用户信息
const USERS =[{username:'admin',password:'123123',nickname:'超级管理员'},{username:'孙悟空',password:'123123',nickname:'用户'}
]
app.use(express.static(path.resolve(__dirname,'./public')))
app.use(express.urlencoded())
app.get('/login',(req,res)=>{if(req.query.username==='admin'&&req.query.password === '123123'){res.send('<h1>登录成功</h1>')}else{res.send('登录失败')console.log('<h1>登录失败</h1>')}
})
app.get('/hello/:id',(req,res)=>{//约定由于配置//可以通过req.params获取参数console.log(req.params)//{ id: '123', age: '12', gender: '男' }res.send('<h1>这是hello路由</h1>')
})
app.post('/login',(req,res)=>{const username = req.body.usernameconst password = req.body.password// USERS.map(user=>{//     if(user.username === username){//         if(user.password===password){//             res.send(登录成功 ${user.nickname})//             return//         }//     }// })// res.send('登录失败')const loginUser = USERS.find(item=>{return item.username === username && item.password===password})if(loginUser){res.send(登录成功 ${loginUser.nickname})}else{res.send('登录失败')}// if(username==='admin'&&password==='123123'){// res.send('<h1>登录成功</h1>')}// else{//     res.send('登录失败')// }
})
app.post('/register',(req,res)=>{//获取用户登录的数据console.log(req.body)const {username,password,repwd,nickname} = req.body//只验证用户名是否存在const user = USERS.find(item=>{return item.username === username || item.nickname === nickname})if(!user){//进入判断用户不存在USERS.push({username,password,nickname})res.send('恭喜你注册成功')}else{res.send('用户名存在')}})
//params以及查询字符串本质上没有区别 查询字符串对象形式传递参数 params按照顺序传
app.listen(3000,()=>{console.log('服务器启动了')
})

        这些代码就实现了登录注册的基本功能。

5.模板引擎 

        当然学后端node.js只是了解基本使用,比较现在还是主打前端开发。这里我们默认没有前端动态展示数据库数据,我们现在服务器写死一些数据希望可以去动态的展示,我们希望有一个东西,可以嵌套变量,在node里面叫做模板。

        html是静态页面 不会跟随服务器数据变化而变化。希望有一个东西 长的像网页 但是可以嵌套变量 这个东西node里面叫做模版。node存在很多个模版引擎 template engines 比如ejs。

       ejs是node中的一款模版引擎 使用步骤

                1.安装ejs

                2.配置express模版引擎为ejs

                        app.set('view engine','ejs')

                3.配置模版路径

                        app.set('views',path.resolve(__dirname,'views'))

        注意 模版引擎需要被express渲染后用户才能使用

        res.render()用来渲染一个模版引擎并将其返回给浏览器 render就是把ejs渲染并且返回给用户跟react 一样的 只不过react在前端这里是后台 后端环境。

        这是模板的目录需要放到views文件夹中。

const express = require('express')
const app = express()
const path = require('node:path')
const STUDENT = [{name:'sun',age:123,gender:'男',address:'花果山'},{name:'zhu',age:231,gender:'女',address:'高老庄'}
]
//将ejs配置为默认的模版引擎
app.set('view engine','ejs')
//配置模版路径
app.set('views',path.resolve(__dirname,'views'))
//配置静态资源路径
app.use(express.static(path.resolve(__dirname,'public')))
//配置请求体解析 body 
app.use(express.urlencoded())
//解析json请求体
//app.use(express.json())
/*可以写路由了
*/
app.get('/hello',(req,res)=>{res.send('hello')
})
//我们希望用户访问student路由的时候 可以返回一个页面里面有表格 存放的student数据
app.get('/students',(req,res)=>{//render可以将一个对象作为render的第二个参数传递 这样在模版中可以访问到对象中的数据//res.render('students',{name:'sun',age:'18'})//名字和ejs名一致//<%=name %>在ejs输出内容时 自动对字符串中的特殊符号进行转义 < 不会识别为标签//这个设计主要是为了避免xss 攻击//<%- %>会直接运行h1 以及js脚本等等res.render('students',{STUDENT})
})
//在所有路由的后面配置错误路由
//不写路径会匹配所以路径 上面路由都没有匹配到
app.use((req,res)=>{//这个执行 上面的路由都没有匹配res.status(404)res.send('你访问的地址被外星人劫持')
})
app.listen(3000,()=>{console.log('服务器已经启动')
})

        这里我们用render去渲染我们的模块,这样访问这个路由就可以返回一个页面给浏览器。然后第二个参数是对象,可以将动态展示的数据传递到模板,模板进行展示。

         

        这里是模板的写法,仍然是html写法只不过变量需要用<%= %>获取js代码需要<%%>包裹。

        

        说到底,Express 并不是一个神秘的东西,它只是对原生 Node HTTP 模块的一层“封装和简化”。我们只要记住三件事:

        它帮我们创建服务器(app.listen())

        它让我们能轻松写路由处理请求(app.get()、app.post())

        它通过中间件机制帮我们定制各种服务逻辑

        加上它对静态资源、模板引擎的良好支持,我们就能快速搭建出一个真正能跑的 Web 项目。

         

 

 

         

         

        

http://www.dtcms.com/a/312622.html

相关文章:

  • Ubuntu20.04 Carla安装与和Ros联合仿真
  • OpenCV轻松入门_面向python(第一章OpenCV入门)
  • Kafka——怎么重设消费者组位移?
  • 北京-4年功能测试2年空窗-报培训班学测开-第六十六天
  • 「iOS」————属性关键字底层原理
  • Jupyter Notebook 中高效处理和实时展示来自 OpenCV 和 Pillow 的图像数据探究
  • 网络缓冲区的设计以及C++实现
  • 【Python练习】075. 编写一个函数,实现简单的语音识别功能
  • 项目日记---高并发内存池整体框架
  • 人工智能与医疗健康:AI 助力医疗的新格局
  • 信号传播速度与延时
  • [硬件电路-143]:模拟电路 - 开关电源与线性稳压电源的详细比较
  • PLC传感器接线与输出信号接线
  • Redis实战(7)-- 高级特性 Redis Stream数据结构与基础命令
  • 【0基础PS】PS工具详解--文字工具
  • .NET 开源节点编辑器,将你的程序功能模块节点化
  • pytorch 安装
  • Paxos 算法是什么?介绍 RAFT 和 ZAB,以及它们之间的区别?会有脑裂问题吗?为什么?
  • 算法竞赛阶段二-数据结构(39)数据结构栈模拟实现
  • AI陪伴赛道,热闹背后是真需求还是泡沫?
  • 应急响应整理
  • Back to the Features:附录A
  • [创业之路-532]:知识、技能、技术、科学各自解决什么问题?
  • 手机(电脑)与音响的蓝牙通信
  • 15_01_opencv_形态学滤波
  • 动态置信度调优实战:YOLOv11多目标追踪精度跃迁方案(附完整代码)
  • C++引用:高效安全的别名机制详解
  • 用于 UBI 的 Elasticsearch 插件:从搜索查询中分析用户行为
  • centos9 安装docker engine
  • Parcel 使用详解:零配置的前端打包工具