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