本文共 11816 字,大约阅读时间需要 39 分钟。
const http = require('http');const fs = require('fs');const url = require('url');const path = require('path');http.createServer((request,response)=>{ // 将请求的路由取出来 不携带参数 let requestUrl = url.parse(request.url).pathname; // 如果是小图标 直接返回 if (requestUrl == '/favicon.ico'){ return false; } // 获取本次请求文件的后缀名 来确定请求的类型 let extname = path.extname(requestUrl); // 使用后缀名 确定响应类型 let mime = getMime(extname); fs.readFile('./xiaou' + requestUrl,(error,data)=>{ if (error){ console.log(error); }else{ response.writeHead(200,{ 'Content-type':mime}); response.end(data); } })}).listen(3000,'127.0.0.1',()=>{ console.log('服务器正在运行......');})function getMime(name){ switch (name){ case '.html': return 'text/html'; case '.css': return 'text/css'; default: return 'text/plain'; }}
let query = url.parse(request.url).query; // querystring模块中有一个parse方法 他能将get参数转化为对象格式 let userObj = qs.parse(query); // 想userObj中追加属性 追加黑名单 userObj.blacklist = 1; // 将原有数据读取出来 并将其转化为数组 let userArr = JSON.parse(readPageFile('./data/user.json',200,response)); // 给添加的数据追加ID userObj.id = userArr[userArr.length - 1].id + 1; // 向数组中追加数据 userArr.push(userObj); // 将数组写入到JSON中 覆盖写 response.writeHead(200,{ 'Content-type':'text/html;charset=utf-8'}); fs.writeFile('./data/user.json',JSON.stringify(userArr),{ encoding:'utf-8',flag:'w'},err=>{ err ? console.log(err) : response.end('注册成功'); })
// 定义一个空数组 准备装取post数据 let arr = []; // post方式提交 使用事件驱动 两个事件 一个是data事件 一个是end事件 // 使用request对象触发data事件 第一个参数是事件名data // 第二个参数是回调函数 回调内置一个参数 参数是传输的数据 post数据 request.on('data',(chunk)=>{ arr.push(chunk); }) // 使用end事件结束post传参 request.on('end',()=>{ // 获取post数据 let query = Buffer.concat(arr).toString(); // querystring模块中有一个parse方法 他能将get参数转化为对象格式 let userObj = qs.parse(query); // 将所有的用户取出来 并转化为数组 let userArr = JSON.parse(readPageFile('./data/user.json',200,response)); // 匹配登录 使用find方法进行查找数据是否存在 // userObj.username : 登录者的用户名 // element.username : 所有已注册的用户名 let result = userArr.find(element=>element.username == userObj.username); // 判断 if (result == undefined){ response.writeHead(200,{ 'Content-type':'text/html;charset=utf-8'}); response.end("") }else{ if (result.blacklist == 0){ response.writeHead(200,{ 'Content-type':'text/html;charset=utf-8'}); response.end("") }else{ if (result.password != userObj.password){ response.writeHead(200,{ 'Content-type':'text/html;charset=utf-8'}); response.end("") }else{ response.writeHead(200,{ 'Content-type':'text/html;charset=utf-8'}); response.end("") } } } })
整体案例
const http = require('http');const fs = require('fs');const url = require('url');const path = require('path');const qs = require('querystring');http.createServer((request,response)=>{ let requestUrl = url.parse(request.url).pathname; if (requestUrl == '/favicon.ico'){ return false; } if (requestUrl == '/'){ requestUrl = '/index'; } if (requestUrl == '/index'){ response.end(readPageFile('./view/home.html',200,response)); }else if (requestUrl == '/login'){ response.end(readPageFile('./view/dl.html',200,response)); }else if (requestUrl == '/register'){ response.end(readPageFile('./view/zc.html',200,response)); }else if (requestUrl == '/insert'){ let query = url.parse(request.url).query; // querystring模块中有一个parse方法 他能将get参数转化为对象格式 let userObj = qs.parse(query); // 想userObj中追加属性 追加黑名单 userObj.blacklist = 1; // 将原有数据读取出来 并将其转化为数组 let userArr = JSON.parse(readPageFile('./data/user.json',200,response)); // 给添加的数据追加ID userObj.id = userArr[userArr.length - 1].id + 1; // 向数组中追加数据 userArr.push(userObj); // 将数组写入到JSON中 覆盖写 response.writeHead(200,{ 'Content-type':'text/html;charset=utf-8'}); fs.writeFile('./data/user.json',JSON.stringify(userArr),{ encoding:'utf-8',flag:'w'},err=>{ err ? console.log(err) : response.end(""); }) }else if (requestUrl == '/loginto'){ // 定义一个空数组 准备装取post数据 let arr = []; // post方式提交 使用事件驱动 两个事件 一个是data事件 一个是end事件 // 使用request对象触发data事件 第一个参数是事件名data // 第二个参数是回调函数 回调内置一个参数 参数是传输的数据 post数据 request.on('data',(chunk)=>{ arr.push(chunk); }) // 使用end事件结束post传参 request.on('end',()=>{ // 获取post数据 let query = Buffer.concat(arr).toString(); // querystring模块中有一个parse方法 他能将get参数转化为对象格式 let userObj = qs.parse(query); // 将所有的用户取出来 并转化为数组 let userArr = JSON.parse(readPageFile('./data/user.json',200,response)); // 匹配登录 使用find方法进行查找数据是否存在 // userObj.username : 登录者的用户名 // element.username : 所有已注册的用户名 let result = userArr.find(element=>element.username == userObj.username); // 判断 if (result == undefined){ response.writeHead(200,{ 'Content-type':'text/html;charset=utf-8'}); response.end("") }else{ if (result.blacklist == 0){ response.writeHead(200,{ 'Content-type':'text/html;charset=utf-8'}); response.end("") }else{ if (result.password != userObj.password){ response.writeHead(200,{ 'Content-type':'text/html;charset=utf-8'}); response.end("") }else{ response.writeHead(200,{ 'Content-type':'text/html;charset=utf-8'}); response.end("") } } } }) }else{ response.end(readPageFile('./view/404.html',404,response)); }}).listen(3000,'127.0.0.1',()=>{ console.log('服务器正在运行......');})// 读取页面的函数function readPageFile(pageUrl,status = 0,response = { }){ response.writeHead(status,{ 'Content-type':'text/html'}); return fs.readFileSync(path.resolve(__dirname,pageUrl),'utf-8');}
Express 是一个简洁而灵活的 Node.js Web应用框架, 提供一系列强大特性帮助你创建各种Web应用
如果不计中间件,主体框架只有一千余行代码,非常简练
Express 不对 Node.js 已有的特性进行二次抽象,我们只是在它之上扩展了Web应用所需的功能
Express内部还是使用的http模块实现服务器创建和监听, 对http模块进行了二次封装
express自身内部只是扩展了路由和中间件
下载express模块, 命令 npm install express
在.js文件中, 引入express模块 初始化服务器对象
设置路由接口地址 (以供浏览器访问) 监听端口号 (给服务器设置端口号)
URL目录部分太长了, 可以让后台规定路由的路径(/api/getNew), 然后当访问时, 让后台去转发寻找
例如: 访问 /image/rB.jpg 就相当于 访问的是上面的路径资源 (但是具体访问什么, 还是后台说了算)
不同的路径, 对应的不同路由 (路由 = 路径)
所以所有的请求, 都看后台如何处理
API接口 = 路由 = 路径 = url地址
get路由 : 只能通过get方式进行访问
post路由 : 只能通过post方式进行访问
all路由 : 可以使用任何方式进行访问
use路由 : 可以使用任何方式进行访问
const express = require('express');// console.log(express);// 实例化一个应用 使用这个应用const app = express();// console.log(app);// 使用express创建一个路由 get方法app.get('/index',(request,response)=>{ // 在express中 我们响应数据使用send方法 注意 send和end一样 只能响应字符串 response.send('第一个程序');});// 使用post方法创建一个路由app.post('/ppp',(request,response)=>{ response.send('第二个程序 这是post');})// 使用all方法 接受所有的方式app.all('/all',(request,response)=>{ response.send('这是第三程序 可以接受任何');})// 使用use中间件 接受任何方式// app.use('/uuu',(request,response)=>{ // response.send('这是use方法');// })app.use((request,response)=>{ response.send('404');})// 监听app.listen(3000,'127.0.0.1',()=>{ console.log('服务器正在运行......');})
? 匹配0个或者1个字符 ?前边的
+ 匹配1个或多个+号前边的字符
* 通配符 匹配0个或者多个 *所在的位置
() 将里边的字符算作一个整体
正则匹配路由
const express = require('express');const app = express();// 定义路由// 正则表达式匹配路由// ? : 零次或一次匹配其前字符// app.get('/ab?cd',(request,response)=>{ // response.send('匹配成功');// })// + : 一次或多次匹配其前字符 至少一次// app.get('/ab+cd',(request,response)=>{ // response.send('匹配成功');// })// () : 将括号中当成一个整体// app.get('/a(bc)?d',(request,response)=>{ // response.send('匹配成功');// })// * : 零次、一次或多次匹配*所在位置// app.get('/ab*cd',(request,response)=>{ // response.send('匹配成功');// })// 正则表达式匹配app.get(/a/,(request,response)=>{ response.send('匹配成功');})app.listen(3000,'127.0.0.1',()=>{ console.log('服务器正在运行');})
携带参数的路由 参数以:分开
路径参数是命名的url字段 用于捕获在url中的位置
捕获的值放在req.params中 路径的:user_id user_id对象的键
const express = require('express');const app = express();// 定义路由/* 在使用路由传递参数的时候 和get参数差不多 都是通过地址栏进行传递参数 但是还是有些不同的 至于不同点 在路由传参中 我们在浏览器端 不需要在使用?进行传递参数 只需要直接传递就可以了 在我们后端接受参数的时候 不需要使用url或者query等方法 我们直接使用:参数名就可以了 直接定义在路由中 在后台接受到参数的时候 我们的参数存储在request对象中的params属性中 他是一个属性 也是一个对象 对象中的数据就是路由参数 是键值对的形式存在的 如果说没有传参 没有参数 那么默认值是空对象*/app.get('/index/:name/:age',(request,response)=>{ let { name,age} = request.params; console.log(request.params); console.log(name,age); response.send('你好 兔头');})app.listen(3000);
也就是我们说的二级路由
一个网站中至少有几十个路由 不能都写在一个页面 那样读取困难 优化不好
所以说 我们每一个模块的路由都是分开写的 分别写在不同的路由模块中
定义路由模块 我们需要使用到express中的Router对象
Express是一个自身功能极简,完全是路由和中间件构成一个web开发框架
一个Express应用就是在调用各种中间件。中间件在Express开发中很重要
中间件函数能够访问请求对象 (req)、响应对象 (res) 以及应用程序的请求/响应循环中的下一个中间件函数
该next功能是中间件函数中的一个功能,当被调用时,它将执行当前中间件之后的中间件
下一个中间件函数通常由名为 next 的变量来表示
内置中间件我们只使用一个 使用static
static : 渲染静态资源的中间件
urlencode : 使用第三方中间件完成功能 接受表单数据
json : 使用第三方中间件完成功能 接受JSON数据
const express = require('express');const path = require('path');const app = express();// 使用static渲染进行资源// 使用use中间件进行渲染// 内置一个或者两个参数// 第一个参数是路由 可选// 第二个参数是express.static方法 方法内置一个参数 参数是渲染的资源路径// 主要的作用是渲染CSS JS IMAGE等静态资源// app.use(express.static('../xiaou/'));app.use('/xiaou',express.static(path.resolve(__dirname,'../xiaou/')));app.listen(3000,'127.0.0.1',()=>{ console.log('服务器正在运行......');})
status : 处理http响应码
send : 处理404
自定义中间件是自己定义的中间件 使用同名路由
路由中没有响应 需要使用next调用下一个中间件
最后一个路由将其直接响应出去
const express = require('express');const app = express();// 自定义中间件中 回调函数中可以传递第三个参数// 在自定义中间键中 有若干个路由 但是都是一个名字 不能有响应// 但是可以有next 使用next方法调用下一个同名中间件app.use('/index',(request,response,next)=>{ let hotSearch = [ { name : '口红'}, { name : '面膜'}, { name : '项链'}, { name : '箱包'}, { name : '高跟鞋'}, { name : '防晒霜'}, { name : '耳钉'}, { name : '搓衣板'} ]; request.hotSearch = hotSearch; next();})app.use('/index',(request,response,next)=>{ let first = [ { name : '导弹'}, { name : '原子弹'}, { name : '氢弹'}, { name : '达姆弹'}, { name : '荷包蛋'}, { name : '茶叶蛋'}, { name : '混蛋'}, { name : '滚蛋'} ]; request.first = first; next();})app.use('/index',(request,response)=>{ let footer = [ { name : '优就业'}, { name : '中公教育'}, { name : '腾讯'}, { name : '网易'}, { name : '饿了吗'}, { name : '美团'}, { name : '赶集网'}, { name : '智联'} ]; let arr = [request.hotSearch,request.first,footer]; response.send(arr);})app.listen(3000,'127.0.0.1',()=>{ console.log('服务器正在运行......');})
第三方中间件使用的其实就是第三方模块
依赖于express的第三方模块就是express的中间件
常用的第三方中间件有
body-parser
cookie-parser
express-session
multer
crypto
ejs
pug
nodemon
转载地址:http://ltse.baihongyu.com/