Nodejs的学习Ⅳ(静态与动态服务器的简单搭建、npm的上传包、在公网上部署服务器、MySQL的安装)
程序员文章站
2022-07-10 20:20:02
...
一、静态服务器
能够根据需要请求的文件,原封不动的将服务器磁盘中的数据直接返回给到浏览器。
具体事例:
let http = require('http'); // 引入http模块
let path = require('path') // 引入path模块
let fs = require('fs') // 引入文件模块
let server = http.createServer() // 创建server对象
server.on('request', function(req, res) { // 监听客户端发送过来的请求,req请求对象包含了请求的相关的信息,res对象用于响应内容,可以通过这个对象帮助我们快速实现HTTP响应
let urlObj = path.parse(req.url) // 解析路径,注意这里的路径是‘\’开头的
if(req.url == "/") { // 识别请求的路径,在这里是主页
res.setHeader("content-type", "text/html; charset = utf-8") // 告诉浏览器返回数据的编码,以免乱码
res.end('这里是主页') // 把数据响应给浏览器
}else if(urlObj.dir == '/static') { // 判断是否请求静态资源
res.setHeader("content-type", getContentType(urlObj.ext)) // 设置响应头(返回数据的格式)
let rs = fs.createReadStream('./static/' + urlObj.base) // 读取静态文件信息
rs.pipe(res) // 通过管道把数据响应给浏览器
}else { // 其他情况
res.setHeader("content-type", "text/html; charset = utf-8") // 设置响应头
res.end("404 页面找不到") // 返回数据
}
})
server.listen(80, function() { // 启动服务器,监听服务端口
console.log("服务已启动:http:127.0.0.1")
})
function getContentType(extName) { // 此函数目的是:根据请求的资源返回该资源的MIME格式
switch(extName) {
case ".jpg":
return "image/jpeg";
case ".html":
return "text/html;charset=utf-8";
case ".js":
return "text/javascript;charset=utf-8";
case ".json":
return "text/json;charset=utf-8";
case ".gif":
return "image/gif";
case ".css":
return "text/css"
}
}
不过上面有一点小缺陷,在于在 路径判断里面的if与else很多 , 逻辑混乱,下面就来改进他
// main.js文件
const http = require('http');
const url = require('url');
const fs = require('fs');
class httpApp { // 发布者
constructor() {
this.server = http.createServer(); // 开启http服务
this.requestList = {}; // 记录订阅者
this.handler(); // 注册事件
}
on(requestWay, requestFn) { // 订阅者订阅发布者
this.requestList[requestWay] = requestFn;
}
handler() {
this.server.on('request', (request, response) => { // 注册服务器监听request事件
let urlObj = url.parse(request.url); // 解析请求的url
let regexp = /(.*?)(\..*?)?$/; // 字符串匹配
regexp.exec(urlObj.pathname)
if(urlObj.pathname in this.requestList) { // 检查url是否在订阅目录内
this.requestList[urlObj.pathname](request, response) // 在就执行函数
}else if(RegExp.$1.indexOf('/static') >= 0 ) { // 判断是否为静态资源
let path = '.' + RegExp.$1 + RegExp.$2; // 得到静态资源的目录结构
response.setHeader('Content-type', getContentType(RegExp.$2)) // 设置响应头
let rs = fs.createReadStream(path); // 读取静态文件
rs.pipe(response) // 把静态文件传出去
}else { // 其他不存在请求
response.setHeader('Content-type', 'text/plain; charset= utf-8')
response.end('路径不存在');
}
})
}
run(port, fn) {
this.server.listen(port, fn) // 启动服务器
}
}
function getContentType(extName) { // 此函数目的是:根据请求的资源返回该资源的MIME格式
switch(extName) {
case ".jpg":
return "image/jpeg";
case ".html":
return "text/html;charset=utf-8";
case ".js":
return "text/javascript;charset=utf-8";
case ".json":
return "text/json;charset=utf-8";
case ".gif":
return "image/gif";
case ".css":
return "text/css"
}
}
module.exports = { // 导出模块
httpApp
}
---------------------------------------------------------------------------------------------------------------
// index.js文件
const { httpApp } = require('./main');
let instanceHttp = new httpApp(); // 实例化自封装的http模块
instanceHttp.on('/', (req, res) => { // 注册事件,订阅者订阅发布者
console.log(req.url);
console.log(1);
res.setHeader('Content-type', 'text/plain; charset= utf-8');
res.end('这是主页')
})
instanceHttp.on('/login', (req, res) => { // 注册事件,订阅者订阅发布者
console.log(req.url);
console.log(2);
res.setHeader('Content-type', 'text/plain; charset= utf-8');
res.end('这是登陆界面')
})
instanceHttp.on('/category', (req, res) => { // 注册事件,订阅者订阅发布者
console.log(req.url);
console.log(3);
res.setHeader('Content-type', 'text/plain; charset= utf-8');
res.end('这是分类')
})
instanceHttp.run(80, () => { // 启动服务
console.log('服务已启动');
})
二、动态服务器
index.js文件
const { httpApp } = require('./main');
const { render } = require('./utils');
let instanceHttp = new httpApp();
instanceHttp.on('/', (req, res) => {
res.setHeader('Content-type', 'text/plain; charset= utf-8');
res.end('这是主页')
})
instanceHttp.on('/login', (req, res) => {
res.setHeader('Content-type', 'text/plain; charset= utf-8');
res.end('这是登陆界面')
})
instanceHttp.on('/category', (req, res) => {
res.setHeader('Content-type', 'text/plain; charset= utf-8');
res.end('这是分类')
})
instanceHttp.on('/profile', async (req, res) => {
res.setHeader('Content-type', 'text/html; charset= utf-8');
res.end(await render(person, './index.html')) // 获取动态的页面
})
let person = {
name: '李老板',
gender: '男',
age: 30
}
instanceHttp.run(80, () => {
console.log('服务已启动');
})
index.html文件
<!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>
<div>
<h2>{{ name }}</h2>
<h2>{{ age }}</h2>
<h2>{{ gender }}</h2>
</div>
</body>
</html>
main.js文件
const http = require('http');
const url = require('url');
const fs = require('fs');
class httpApp {
constructor() {
this.server = http.createServer();
this.requestList = {};
this.handler();
}
on(requestWay, requestFn) {
this.requestList[requestWay] = requestFn;
}
handler() {
this.server.on('request', (request, response) => {
let urlObj = url.parse(request.url);
let regexp = /(.*?)(\..*?)?$/;
regexp.exec(urlObj.pathname)
if(RegExp.$1 in this.requestList) {
this.requestList[RegExp.$1](request, response)
}else if(RegExp.$1.indexOf('/static') >= 0 ) {
let path = '.' + RegExp.$1 + RegExp.$2;
response.setHeader('Content-type', getContentType(RegExp.$2))
let rs = fs.createReadStream(path);
rs.pipe(response)
}else {
response.setHeader('Content-type', 'text/plain; charset= utf-8')
response.end('路径不存在');
}
})
}
run(port, fn) {
this.server.listen(port, fn)
}
}
function getContentType(extName) { // 此函数目的是:根据请求的资源返回该资源的MIME格式
switch(extName) {
case ".jpg":
return "image/jpeg";
case ".html":
return "text/html;charset=utf-8";
case ".js":
return "text/javascript;charset=utf-8";
case ".json":
return "text/json;charset=utf-8";
case ".gif":
return "image/gif";
case ".css":
return "text/css"
}
}
module.exports = {
httpApp
}
utils.js文件
const fs = require('fs');
function render(options, target) { // 渲染页面的函数
return new Promise(async (resolve, reject) => {
let finalData = '';
let rs = await fs.createReadStream(target, {
encoding: 'utf-8',
flags: 'r'
});
rs.on('data', (data) => {
let regexp = /\{\{(.*?)\}\}/igs;
finalData = data;
let res = [];
while(res = regexp.exec(data)) {
if(res[1].trim() in options) {
finalData = finalData.replace(res[0], options[res[1].trim()])
}else {
console.log('数据错误');
}
}
resolve(finalData);
})
rs.on('close', () => {
console.log('关闭');
})
rs.on('error', () => {
reject('错误')
})
})
}
module.exports = {
render
}
三、npm的上传包
1. 创建文件夹
把需要上传的文件放在刚创建的文件夹内
2. npm包的初始化
在控制台输入:
npm init
3. npm包信息的设置
{
"name": "packageName", // npm包的名字
"version": "0.1.0", // 包的版本
"description": "将原生的fs模块进行promise封装,可以快速的使用async_await模式", // 包的描述
"main": "index.js", // 包的入口文件(路径)
// "test commed" 为测试命令
// "git repository" 为git的包
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [ // 包的关键词
"promise封装"
],
"author": "李老板", // 作者名
"license": "ISC" // 许可证
}
4. 注册NPM官网账号并邮箱验证
5. 本机登陆NPM
npm login
输入用户名、邮箱与密码即可
6. 发布NPM包
npm publish
四、在公网上部署服务器
需要使用花生壳,它可以将私网的IP与端口和公网的IP与端口映射起来,不过内网的电脑必须一直在线,不然链接会掉
1、账号的注册并实名认证
2、在控制台点击花生壳
里面有个免费版本的,再点进去
然后会跳出来一个购买免费服务,不用说买它
进入会出现以下界面,点击加号
3、添加
出现以下界面,并依次填写
4、下载花生壳
5、在花生壳软件里面进行其他操作
五、MySQL的安装与使用
1、同意协议
2、选择Server only
3、过程可能需要安装C的包(因为环境需要),一路确定即可
4、下一步
5、选择Standard
6、下一步
7、端口可以修改,但没有必要
8、选择Use legacy
9、设置密码
10、下一步
11、执行
12、在开始里面找到MySQL文件
点击Command Line测试MySQL,输入密码即可,不过也可以安装navicat工具,来可视化操作数据库,navicat的安装一路下一步即可
本文只用于个人学习与记录