node.js服务器静态资源处理

前言:node.js服务器动态资源处理见 http://t.csdnimg.cn/9D8WN

一、什么是node.js服务器静态资源?

静态资源服务器指的是不会被服务器的动态运行所改变或者生成的文件. 它最初在服务器运行之前是什么样子, 到服务器结束运行时, 它还是那个样子. 比如平时写的 js, css, html文件, 都可以算是静态资源。

我的静态服务器需要使用json文件作为数据存储。并进行json数据的读取与写入。

下面,我将以在服务器中实现注册、登录为例并将我已注册的用户数据写到我的user.json中。

二、服务器处理静态资源执行思路:

(1)将所有静态资源统一放入一个文件夹中做统一处理

(2)在服务器端来处理pathname从而判断url是否是我们请求的路径

如何解析和格式化url查询字符串?

 Node.js 的 querystring 模块:

1. 将字符串参数解析成对象

querystring.parse(url)

2. 将对象参数解析成字符串

 querystring.stringify(urlObject)

三、静态资源处理的判断方法:

startWith(以什么开头)、indexOf、search、includes
 

四、执行要求:

静态资源要求:完成注册、登录功能

动态资源要求:完成注册、登录、已注册的用户列表展示功能

五、执行代码:

执行结果见视频:

20240415_142226

node.js服务器静态资源处理:

(1)我们将首页、登录、注册三个html静态页面和用户列表users.html写在views这个大文件夹下。css样式和images图片放入public这个大文件夹下。创建一个data大文件夹,data下面建一个user.json文件来专门存储用户数据

简单写一下首页、注册、登录页面的html静态页面的样式。

1》index.html 首页

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>首页</title>
  <link rel="stylesheet" href="../public/css/main.css">
</head>
<body>
  <h1>首页</h1>
  <img src="../public/images/01.png" alt=""><br>
  <a href="/login">登录</a>|<a href="/regist">注册</a>|<a href="/list">用户列表</a>
</body>
</html>

2》regist.html  注册

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>注册</title>
  <link rel="stylesheet" href="../public/css/main.css">
</head>
<body>
  <h1>注册</h1>
  <img src="../public/images/01.png" alt=""><br>
  <form method="get" action="/doRegist">
    <input type="text" name="username" placeholder="用户名"><br>
    <input type="password" name="password" placeholder="密码"><br>
    <input type="submit" value="注册"><br>
  </form>
</body>
</html>

3》login.html 登录

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>登录</title>
  <link rel="stylesheet" href="../public/css/main.css">
</head>
<body>
  <h1>登录</h1>
  <img src="../public/images/01.png" alt=""><br>
  <form method="get" action="/doLogin">
    <input type="text" name="username" placeholder="用户名"><br>
    <input type="password" name="password" placeholder="密码"><br>
    <input type="submit" value="登录"><br>
  </form>
</body>
</html>

index.html 首页显示如下:

(2)测试代码:

创建一个服务器,使服务器做出响应的请求与响应(重点:对解析后的url的pathname来做出不同的if判断处理)

const http = require('http');
const fs = require('fs');
const path = require('path');
const url = require('url');
// 声明一个专门存放所有用户的变量
var users;
// 导入查询参数的模块
const querystring = require('querystring')
//创建服务器
const server = http.createServer();
//读取文件。读取user.json存放用户数据的文件
fs.readFile(path.join(__dirname, 'data/users.json'), (err, data) => {
    if (err) {
        users = {};
    } else {
        users = JSON.parse(data.toString()); //如果读取正确就将读到的内容转换为一个对象存到users里
    }
})
//服务器做出请求响应
// 设置服务器的监听器来响应'request'事件。当有人向服务器发送请求时,这个事件就会被触发
server.on('request', (req, res) => {
    let objurl = url.parse(req.url); //将包含了客户端请求的完整URL(req.url)转为一个对象才能获取到它的pathname
    let pathname = objurl.pathname;  //从解析后的URL对象objurl中提取出路径名
    // 对pathname做处理
    if (pathname.startsWith('/public')) {
        // 找到当前项目文件夹,再将相对路径转为绝对路径
        let p = path.join(__dirname, pathname);
        fs.readFile(p, (err, data) => {
            if (err) {
                res.writeHead(404, { 'Content-Type': 'text/html;charset=utf-8' });
                res.end('404 Not Found');
            } else {
                res.end(data);
            }
        })
    } else if (pathname == '/' || pathname == '/home') {
        let p = path.join(__dirname, 'views/index.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.writeHead(404, { 'Content-Type': 'text/html;charset=utf-8' });
                res.end('404 Not Found');
            } else {
                res.end(data);
            }
        })
    } else if (pathname == '/regist') {
        let p = path.join(__dirname, 'views/regist.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.writeHead(404, { 'Content-Type': 'text/html;charset=utf-8' });
                res.end('404 Not Found');
            } else {
                res.end(data);
            }
        })

    } else if (pathname == '/login') {
        let p = path.join(__dirname, 'views/login.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.writeHead(404, { 'Content-Type': 'text/html;charset=utf-8' });
                res.end('404 Not Found');
            } else {
                res.end(data);
            }
        })
//已注册或已登录的情况:
    } else if (pathname == '/doRegist') {
        let query = querystring.parse(objurl.query); //将字符串参数解析成对象
        let username = query.username;
        let password = query.password;
        if (users[username]) {
            res.writeHead(500, { 'Content-Type': 'text/html;charset=utf-8' });
            res.end('用户名已存在,不能注册!');
        } else {
            //因为users里面是一个对象。所以只能属性名=值的形式。故用户名 / 密码 为属性名 = 用户名的值 / 密码的值 为属性值
            users[username] = password;
            //利用JSON.stringify(users)将users对象转为字符串重新写到文件里去
            fs.writeFile(path.join(__dirname, 'data/users.json'), JSON.stringify(users), (err) => {
                if (err) {
                    res.writeHead(502, { 'Content-Type': 'text/html;charset=utf-8' });
                    res.end('注册失败');
                } else {
                    res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' });
                    res.end('注册成功')
                }
            })

        }

    } else if (pathname == '/doLogin') {
        let query = querystring.parse(objurl.query);
        let username = query.username;
        let password = query.password;
        // 判断users的用户名和密码有无
        if (users[username] && users[username] == password) { //用户名 && 密码
            res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' });
            res.end('登录成功');
        } else {
            res.writeHead(502, { 'Content-Type': 'text/html;charset=utf-8' });
            res.end('用户名或密码错误,登录失败');
        }
    } else if (pathname == '/list') {
//显示list用户列表是动态资源处理的内容。见我的下一篇博客 
    }
});
//启动服务器
server.listen(3000, '127.0.0.1', () => {
    console.log('Server is running at http://127.0.0.1:3000');
})

(3)结果显示

此时我的用户数据就显示在了我的data文件夹下的user.json上了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/546766.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mockito单元测试

文章目录 Mockito单元测试 为什么要使用Mock?导入依赖import导入包使用Mock模拟测试某个类中的某个方法是否可以成功执行使用Mock模拟某个类的方法&#xff0c;自己给这个方法返回我们指定的值使用Mock模拟某个方法调用后会抛出指定的异常使用Mock模拟测试某个类中的某个方法(…

语音智能客服机器人有什么优势?ai机器人部署

人工智能技术的进步&#xff0c;在不断的革新我们的工作和生活&#xff0c;同时&#xff0c;拥有人工智能技术的语音智能客服机器人在销售行业的工作熟悉程度也越来越好&#xff0c;那语音智能客服机器人有什么优势&#xff1f;我们一起来看看。 1、ASR语音文本转换 客户可通过…

微服务之分布式链路追踪

一、概述 1.1背景 在微服务框架中&#xff0c;一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果&#xff0c;每一个前段请求都会形成一条复杂的分布式服务调用链路&#xff0c;链路中的任何一环出现高延时或错误都会引起整个请求最…

k8s高可用集群部署介绍 -- 理论

部署官网参考文档 负载均衡参考 官网两种部署模式拓扑图和介绍 介绍两种高可用模式 堆叠 拓扑图如下&#xff08;图片来自k8s官网&#xff09;&#xff1a; 特点&#xff1a;将etcd数据库作为控制平台的一员&#xff0c;由于etcd的共识算法&#xff0c;所以集群最少为3个&…

【算法】快速排序的基本思想、优化 | 挖坑填补法和区间分割法

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法分析与设计知识专栏&#xff1a;算法分析&#x1f525; 给大家跳…

Spire.PDF for .NET【文档操作】演示:合并 PDF 文档

需要合并 PDF 的原因有很多。例如&#xff0c;合并 PDF 文件允许您打印单个文件&#xff0c;而不是为打印机排队多个文档&#xff0c;组合相关文件通过减少要搜索和组织的文件数量来简化管理和存储多个文档的过程。在本文中&#xff0c;您将学习如何使用Spire.PDF for .NET将多…

STM32移植嵌入式开源按键框架

目录 STM32移植嵌入式开源按键框架 MultiButton简介 multi_button.c文件 multi_button.h文件 按键事件 案例使用方法 学习剖析 STM32移植嵌入式开源按键框架 今天移植了一款嵌入式按键框架工程MultiButton&#xff0c;MultiButton是一个小巧简单易用的事件驱动型按键驱动…

OSCP靶场--Wombo

OSCP靶场–Wombo 考点(redis 主从复制RCE ) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC 192.168.153.69 -p- -Pn --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-13 07:33 EDT Nmap scan report for 192.168.153.69 Host is u…

代理IP服务商:选择、优势与未来趋势

目录 一、代理IP服务商的选择 二、代理IP的优势 三、代理IP的未来发展趋势 在网络爬虫、数据采集、SEO优化等网络应用中&#xff0c;代理IP扮演着不可或缺的角色。代理IP服务商则是提供这些代理IP资源的主体&#xff0c;如何选择合适的服务商&#xff0c;以及代理IP的优势和…

风速Weibull分布和光伏Beta分布的参数拟合方法(含matlab算例)

在风光场景生成、随机优化调度等研究中&#xff0c;常常假设风速服从Weibull分布&#xff0c;太阳辐照度服从Beta分布。那我们如何得到两个分布的参数呢&#xff1f;文本首先介绍了风速Weibull分布和辐照度Beta分布的基本概率模型及其性性质&#xff0c;之后以MATLAB代码为例阐…

【JAVA基础篇教学】第七篇:Java异常类型说明

博主打算从0-1讲解下java基础教学&#xff0c;今天教学第七篇&#xff1a;Java异常类型说明。 在Java中&#xff0c;错误&#xff08;Error&#xff09;是Throwable类及其子类的实例&#xff0c;它们通常表示严重的问题&#xff0c;无法通过程序来处理&#xff0c;而是需要进…

javaWeb项目-外面点餐系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、Spring Boot框架 …

vue3第十八节(diff算法)

引言&#xff1a; 上一节说了key的用途&#xff0c;而这个key属性&#xff0c;在vue的vnode 中至关重要&#xff0c;直接影响了虚拟DOM的更新机制&#xff1b; 什么场景中会用到diff算法 如&#xff1a;修改响应式属性需要重新渲染页面&#xff0c;会重新执行render渲染函数返…

AndroidStudio 导出aar包,并使用

打包 1、确认当前选项是否勾选&#xff0c;如未勾选请先勾选。 2、勾选完成后重启Android Studio。 3、重启完成后&#xff0c;选中要打包的module 4、打包完成 使用 1.在项目中新建libs,放入aar文件。 2.修改配置 添加如下代码 flatDir {dirs("libs")}3.修改app…

MongoDB 使用

1 引用依赖包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>2 配置文件配置mongodb资料 # MongoDB连接信息 spring.data.mongodb.host 192.168.23.…

ESP32_IDF前端命令开发全过程

ESP32 IDF前端命令开发全过程 开端1. 创建新工程(create-project)2. 创建新组件(create--component)目前文件结构 3. 设置目标芯片4. 配置项目5. 编译工程6. 烧录程序7. 打开监视器8. 一次性编译烧录并打开监视器9. 擦除设备flash10. 查询内存剩余11. 清除编译文件 仅供本人查阅…

【位运算】Leetcode 消失的两个数字

题目解析 面试题 17.19. 消失的两个数字 算法讲解 我们将这两个数组异或在一起&#xff0c;最后的结果就是a ^ b(缺失的两个数字)的结果&#xff0c;这两个缺失的数字一定是不相同的&#xff0c;所以我们就寻找他们第一个比特位是1的那个位置&#xff0c;异或的原理是&#xf…

为了执行SQL语句,MySQL的架构是怎样设计的

1. 把MySQL当个黑盒子一样执行SQL语句 上一讲我们已经说到&#xff0c;我们的系统采用数据库连接池的方式去并发访问数据库&#xff0c;然后数据库自己其实也会维护一个连 接池&#xff0c;其中管理了各种系统跟这台数据库服务器建立的所有连接 我们先看下图回顾一下 当我们的…

WordPress用户福音:Elementor Pro国产版替代方案,全新中文界面更懂你

如果你正在考虑创建自己的网站&#xff0c;那么在第一次谷歌搜索时&#xff0c;你可能已经看到了WordPress、Elementor和网站构建器这些专业名称。WordPress是最受欢迎的网站平台之一&#xff0c;这不难理解&#xff1a;它高度可定制&#xff0c;易于学习&#xff0c;而且是免费…

第十五届蓝桥杯 javaB组第三题

测试通过了90% 剩下10%不知道哪错了 思路&#xff1a;我想的是用map&#xff0c;k存第几个队列&#xff0c;value存每个子队列的长度&#xff0c;最后给value排序 第一个就最小的也就是是有效元素数量 考试只对了个案例&#xff0c;其它情况没测试。 复盘 回来后经过修改改…