静态服务器 VS 静态服务器
也叫动态网页 VS 静态网页
判断依据
- 没有请求数据库,就是静态服务器
- 请求了数据库,就是动态服务器
这次直接用 JSON 文件当做数据库
引入 jQuery 的方法: (www.bootcdn.cn/jquery/)
新建目录 db (数据库缩写),在 db 下新建 users.json,数据库的结构就是数组,里面是哈希表
[
{"id":1,"name":"wbs","password":"zzz"},
{"id":2,"name":"tom","password":"aaa"}
]
复制代码
怎么读和写数据库呢?在根目录下新建 test.js
const fs = require("fs");
//读数据库
const usersString = fs.readFileSync("./db/users.json").toString();
const usersArray = JSON.parse(usersString); //把字符串变成对应的数组对象
console.log(usersArray);
//写数据库
const user3 = { id: 3, name: "kok", password: "bbb" };
usersArray.push(user3);
const string = JSON.stringify(usersArray);
fs.writeFileSync("./db/users.json", string);
复制代码
写入数后的 users.json
[
{"id":1,"name":"wbs","password":"zzz"},
{"id":2,"name":"tom","password":"aaa"},
{"id":3,"name":"kok","password":"bbb"}
]
复制代码
JSON.stringify()
//序列化JSON.parse()
//返序列化type of
可以查看对象类型
目标 1 :实现用户注册功能
- 用户提交用户名和密码
users.json
里就新增了一行数据
思路
- 前端写一个 form,让用户填写 name和 password
- 前端监听 submit 事件
- 前端发送 post 请求,数据位于请求体
- 后端接收 post 请求
- 后端获取请求体中的 name 和 password
- 后端存储数据
具体步骤
- 在 pubilc 目录下 新建 regist.html,写一个 form 表单
- 监听 submit 事件
- 阻止form表单的默认事件
- 获取用户数据:找到input的name为name的元素,获得用户输入的值,找到input的name为password的元素,获得用户输入的值
- 用 ajax 发送 POST 请求,把数据传给服务器
- 请求的url是/register
- 传给服务器的数据也就是请求体内容为刚刚获取的用户数据的json字符串
- 请求体的类型也就是传给服务器的数据类型为json
- 再用.then设置请求成功函数(跳转到登录页面(/sign_in.html))和失败后的函数(啥也不干)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
//直接抄淘宝的 meta vp
<meta
name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"
/>
<title>注册</title>
</head>
<body>
<form id="registerForm">
<div>
<label>用户名 <input type="text" name="name" /></label>
</div>
<div>
<label>密码 <input type="password" name="password" /></label>
</div>
<div>
<button type="submit">注册</button>
</div>
</form>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
const $form = $("#registerForm");
$form.on("submit", (e) => {
e.preventDefault(); //阻止 form 表单默认事件
const name = $form.find("input[name=name]").val(); //找到相应的 name 和 password 的值
const password = $form.find("input[name=password]").val();
console.log(name, password);
$.ajax({
method: "POST",
url: "/register",
contentType: "text/json; charset=UTF-8", //让服务器知道我们上传的是 JSON 字符串
data: JSON.stringify({ name, password }),
}).then(
() => {
alert("注册成功");
location.href = "https://juejin.cn/sign_in.html";
},
() => {}
);
});
</script>
</body>
</html>
复制代码
很显然, register 的请求会得到一个 404,因为 register 不对应任何一个文件,服务器如何获取到用户的 name 和 password 呢,那就需要在请求这个文件之前,看一下有没有 register ,server.js 代码如下
var http = require("http");
var fs = require("fs");
var url = require("url");
var port = process.argv[2];
if (!port) {
console.log("请指定端口号好不啦?\nnode server.js 8888 这样不会吗?");
process.exit(1);
}
var server = http.createServer(function (request, response) {
var parsedUrl = url.parse(request.url, true);
var pathWithQuery = request.url;
var queryString = "";
if (pathWithQuery.indexOf("?") >= 0) {
queryString = pathWithQuery.substring(pathWithQuery.indexOf("?"));
}
var path = parsedUrl.pathname;
var query = parsedUrl.query;
var method = request.method;
/******** 从这里开始看,上面不要看 ************/
console.log("有个傻子发请求过来啦!路径(带查询参数)为:" + pathWithQuery);
if (path === "/register" && method === "POST") {
response.setHeader("Content-Type", "text/html;charset=utf-8");
//读数据库
const userArray = JSON.parse(fs.readFileSync("./db/users.json"));
const array = [];
//监听请求的上传事件,把chunk数据push到数组里,因为数据可能是一点一点上传,每上传一点,我就往数组里push一点数据
request.on("data", (chunk) => {
array.push(chunk);
});
//监听请求的结束事件,先把array里的数据变成字符串,这个字符串符合JSON语法,然后在把字符串变成js对象
request.on("end", () => {
const string = Buffer.concat(array).toString();
const obj = JSON.parse(string);
//写入数据库
const lastUser = userArray[userArray.length - 1];
const newUser = {
//新用户
// id 为如果最后一个用户存在 id就是最后一个用户的 id + 1,否则就是1
id: lastUser ? lastUser.id + 1 : 1,
name: obj.name,
password: obj.password,
};
userArray.push(newUser);
fs.writeFileSync("./db/users.json", JSON.stringify(userArray));
response.end();
});
} else {
response.statusCode = 200;
// 默认首页
const filePath = path === "/" ? "/index.html" : path;
const index = filePath.lastIndexOf(".");
// suffix 是后缀
const suffix = filePath.substring(index);
const fileTypes = {
".html": "text/html",
".css": "text/css",
".js": "text/javascript",
".png": "image/png",
".jpg": "image/jpeg",
};
response.setHeader(
"Content-Type",
`${fileTypes[suffix] || "text/html"};charset=utf-8`
);
let content;
try {
content = fs.readFileSync(`./public${filePath}`);
} catch (error) {
content = "文件不存在";
response.statusCode = 404;
}
response.write(content);
response.end();
}
/******** 代码结束,下面不要看 ************/
});
server.listen(port);
console.log(
"监听 " +
port +
" 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:" +
port
);
复制代码
目标 2:实现用户登录功能
- 首页 home.html,已登录用户可看到自己用户名
- 登录页 sign_in.html,供提交用户名和密码
- 输入的用户名密码如果是匹配的,就自动跳转首页
sign_in.html 思路
- 前端写一个 form,让用户填写name和password
- 前端监听submit事件
- 前端发送 post请求,数据位于请求体
- 后端接收post请求
- 后端获取请求体中的name和password
- 后端读取数据,看是否有匹配的name和password
- 如果匹配,后端应标记用户已登录,可是怎么标记?
新建登录页 sign_in.html,思路 register.html 相同
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"
/>
<title>登录</title>
</head>
<body>
<form id="signInForm">
<div>
<label>用户名 <input type="text" name="name" /></label>
</div>
<div>
<label>密码 <input type="password" name="password" /></label>
</div>
<div>
<button type="submit">登录</button>
</div>
</form>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
const $form = $("#signInForm");
$form.on("submit", (e) => {
e.preventDefault(); //阻止 form 表单默认事件
const name = $form.find("input[name=name]").val(); //找到相应的 name 和 password 的值
const password = $form.find("input[name=password]").val();
$.ajax({
// ajax 发送 POST 请求
method: "POST",
url: "/sign_in",
contentType: "text/json; charset=UTF-8", //让服务器知道我们上传的是 JSON 字符串
data: JSON.stringify({ name, password }),
}).then(
() => {
alert("登录成功");
location.href = "https://juejin.cn/home.html";
},
() => {}
);
});
</script>
</body>
</html>
复制代码
在 server.js 写 sign_in 路由
- 后端接收post请求
- 后端获取请求体中的name和password
- 后端读取数据,看是否有匹配的name和password
if (path === "/sign_in" && method === "POST") {
response.setHeader("Content-Type", "text/html;charset=utf-8");
//读数据库
const userArray = JSON.parse(fs.readFileSync("./db/users.json"));
const array = [];
request.on("data", (chunk) => {
array.push(chunk);
});
request.on("end", () => {
const string = Buffer.concat(array).toString();
const obj = JSON.parse(string);
const user = userArray.find( //在数据库中找匹配的 name 和 password
(user) => user.name === obj.name && user.password === obj.password
);
if (user === undefined) { //没找到
response.statusCode = 400;
response.end(`{'errorCode': 4001}`);
} else { //找到了
response.statusCode = 200;
response.end();
}
});
}
复制代码
目标 3 :标记用户已登录 Cookie
Cookie 定义:
- Cookie是服务器下发给浏览器的一段字符串
- 浏览器必须保存这个Cookie(除非用户删除)
- 之后发起相同二级域名请求(任何请求)时,浏览器必须附上Cookie
以公园门票作为对比(画图)
- 假如你是公园检票员,你怎么知道谁能进谁不能进?
- 有票能进,没票不能进
- Cookie就是门票
- 有Cookie就是登录了,没Cookie就没登录
- 那后端给浏览器下发一个Cookie不就完事了嘛
Cookie 具体语法看 mdn
开发者工具 Application => Cookie
可以查看
在 public 目录下新建 home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>首页</title>
</head>
<body>
<p>{{loginStatus}}</p>
<a href="https://juejin.cn/post/sign_in.html">登录</a>
</body>
</html>
复制代码
建议只在后端设置 Cookie ,永远不要在前端设置 Cookie
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END