目录
一.服务器
1.定义:
服务器就是提供服务的,有web服务器、数据库服务器等。
2.web服务端保存的资源
- 静态资源
html、css、js、图片、.json、字体等在前端使用的文件,这些文件的内容每次打开时,都是一样的,因此叫做静态资源。
- 动态资源(接口)
后端的程序。
3.web服务器(软件)的作用
- 接收前端的请求
- 查找文件
- 执行服务器端代码
- 响应
二.nodeJS
1.定义:
后端编程语言,还可以搭建服务器。nodeJS就是ECMAScript,在原来学习的ES的基础上增加了后端相关的API。如:HTTP、fs、URL等,让javascript也可以做后端开发,即一门语言搞定前后端(全栈)。
2.目标:
数据服务:连接数据库;
文件服务:文件上传;
web服务:web服务器。
3.优势:
性能高,方便,对于前端人员入门难度低;
处理并发的场景,较为明显。
4.劣势:
服务器提供的相对较少;
相对其他语言,能用的上的学习资料少;
对程序员的要求高。
5.特点:
单线程:nodeJS是单线程的,依靠事件循环处理并发。
非阻塞:NodeJS在访问IO操作后不会等待其完成,而是立即去执行其他代码,操作完成后会使用回调函数返回,保证高效的利用当前线程的cpu,不造成硬件浪费。
事件驱动:通过事件来驱动整个程序的进行,由于是单线程,所以把高IO的操作会移动到事件队列中等待完成,完成后通过回调函数的方式返回给线程来进行处理。循环处理的过程称为事件循环。
接下来该进入正题了~
三.环境安装
1.官网:
[英文] [中文] 也可参考上个blog
2.测试环境:
win+r-->命令行(运行cmd)-->node -V
3.运行:
在vscode的终端:node 文件名
接下来普及一丢丢版本号的小常识
版本:
Vx(主).x(子).x(修正)
主版本:变化了,1/3的API发生巨变,使用方式变化了;
子版本:API没有删减,使用方式没变化,内部实现发生了变化。
修正版:什么都没变,处理一下bug。
子版本号为偶数,则是稳定版;子版本号是奇数,则是非稳定版。
beta测试版
rc、alpha测试稳定
注:
nodeJS使用的ECMA语法,不可使用DOM、BOM,因为后端开发没有浏览器。即:前端js代码在浏览器上运行;后端js代码在node环境里运行。
四. web服务器的开发
(一)搭建服务器(http模块)
1.搭建服务器需要使用http模块,http模块,可以创建服务器对象,同时可以处理请求和响应。
2.步骤
1)引入http模块
let http=require("http");
//let var const根据需要,const一般后期不在修改
2)创建web服务,返回http对象
let app=http.createServer((req,res)=>{
//req 请求体(请求对象) 浏览器->服务器,服务器端把浏览器发送来的信息整理到req对象
//req.url 地址 提取地址栏数据
//req.on('data') 提取非地址栏数据,所有的http[s]都会触发end事件
//req.on('end')
//res 响应体(响应对象) 服务器->浏览器,服务器端给浏览器端发送的信息都整理在res里。
//res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});响应头设置
//res.write(字符/数据)
//res.end() 结束响应,必须
})
3)监听服务器
app.listen(端口,[地址],[回调])
端口:1-65535 1024以下系统占用
地址:localhost 真实域名xx.duapp.com,ip地址也行
回调:监听成功,回调一次。
4)启动服务器的命令
node 文件名
eg:搭建服务器的实例代码
// 1、引入http模块(nodeJS官方的模块,是个对象)
const http = require("http");
// 2、创建服务器对象
let server = http.createServer((req,res)=>{
// req:请求对象(包含所有前端请求的信息,如:url,method,)
console.log("req.url",req.url);
console.log("req.method",req.method);
// res:响应对象(包括响应所使用的函数等等,如:res.write() )
res.writeHeader(200,{"Content-type":"text/html;charset=utf-8"})
// res.setHeader("Content-type","text/html;charset=utf-8")
// res.write():给前端响应数据的,可以写多条
res.write("<h1>欢迎光临1!</h1>");
res.write("<h1>欢迎光临2!</h1>");
res.write("<h1>欢迎光临3!</h1>");
res.write("<h1>欢迎光临4!</h1>");
res.end();
});
// 3、启动服务器
server.listen(9000,"10.35.165.56",()=>{
console.log("启动成功,请访问……");
})
小伙伴有没有感受到每修改一次服务器端的代码,服务就得重启一次服务这样的麻烦~接下来给大家推荐几个工具,解决这样的麻烦。
推荐命令行工具:supervisor/nodemon
安装方式:npm install supervisor -g
npm install nodemo -g
启动服务器:nodemon 文件名,这样只需要重启一次服务器幺~,以后更改代码后,只要保存就可以了。
(二)静态资源托管
(fs模块)
1.fs:
fileSystem;这个模块可以读取文件的内容、给文件写内容、创建文件夹、删除文件夹等。一般来说,前端的如下代码都会请求静态资源。
<a href=".."></a>
<img src="..."/>
location.href="..."
body{
background:url(....)
}
后端资源读取静态资源文件就要使用fs模块
fs.readFile(文件名,[编码方式],回调(err,data));
2.fs模块
2.1磁盘操作、文件操作;
2.2读取
//异步的方式:
fs.readFile('文件路径',[编码方式],(err,data)=>{})
// err 错误 ,null没有错误
//data: 数据, 默认是buffer流;如果希望是unicode编码的结果,那么可以把编码方式使用 utf-8
//同步的方式:
let data = fs.readFileSync('文件路径')
//处理错误
try{
//要排错的代码,如果try分支里有错误,那么就会进入到catch分支。
}catch(e){
}
(path模块)
3.path模块
3.1操作系统磁盘路径
3.2API
3.2.1磁盘路径解析parse
path.parse('c:\\wamp\\xx.png') // string -> object
//返回
{
root: 'c:\\', 盘符
dir: 'c:\\wamp', 目录
base: 'xx.png', 文件名
ext: '.png', 扩展名
name: 'xx' 文件,不含扩展名
}
3.2.2片段合并join
path.join('磁盘路径1','磁盘路径2','磁盘路径n')
//__dirname 魔术变量 返回当前文件所在的磁盘路径
3.2.3片段合并resolve
path.resolve('磁盘路径1','磁盘路径n')
//合并磁盘片段,右到左找,如果找到了根,那就不再朝前找了;拼接时,是从左到右拼接,如果没有给根路径,以当前文件路径为根(即默认:加上 __dirname)。
静态资源的示例代码:
//一、在目录下建立 www 目录,写几个html文件
//二、服务器代码
// 1、引入http模块(nodeJS官方的模块,是个对象)
const http = require("http");
const fs = require("fs");
// 2、创建服务器对象
let server = http.createServer((req, res) => {
if (req.url != "/favicon.ico") {
try {
let filename = "./www" + req.url;
let data = fs.readFileSync(filename, "utf8");
res.write(data);
res.end();
} catch (error) {
res.write("服务器出错了");
res.end();
}
}
});
// 3、启动服务器
server.listen(9000, "10.35.165.56", () => {
console.log("启动成功,请访问……");
})
(三)动态资源(接口)
1.前端:
表单:get/post/put/delete/.. 请求方式
js:ajax/jsonp
2.后端
处理方式:http[s]
- 地址栏上的数据:req.url抓取get请求的数据,利用url模块切字符。
- 非地址栏的数据:req.on('data',(chunk)=>{chunk是每次收到的数据buffer'})
req.on('end',()=>{接收完毕,用querystring切字符})
可以利用postman工具测试各种请求,postman不用写前端。开心激动吧 下载
(四)url模块
1.作用:
处理url格式的字符串。
2.用法:
url.parse(str,true)
//返回 对象 true处理query为对象,如果不写true则返回的是整个地址的对象。
str -> obj 返回 对象 true
protocol: 'http:', 协议
slashes: true, 双斜杠
auth: null, 作者
host: 'localhost:8002', 主机
port: '8002', 端口
hostname: 'localhost', baidu
hash: '#title', 哈希(锚)
search: '?username=sdfsdf&content=234234', 查询字符串
query: 'username=sdfsdf&content=234234', 数据
pathname: '/aaa', 文件路径
path: '/aaa?username=sdfsdf&content=234234', 文件路径
href: 'http://localhost:8002/aaa?username=sdfsdf&content=234234#title'
url.format(obj) 返回字符
obj -> str 返回str
(五)querystring模块
1.作用:
处理查询字符串 如:?key=value&key2=value2
2.用法:
querystring.parse(str) 返回对象
querystring.stringify(obj) 返回字符串
(六)获取非地址栏的数据
eg:前端使用post发来的数据。
1.使用:
//用req.on绑定事件data:接收一次数据(一般来说:65536字节),触发一次data
req.on('data',(chunk)=>{
})
//用req.on绑定事件end:接收完毕。
req.on('end',(err)=>{
})
动态资源示例代码:
const http = require("http");
const url = require("url");
let server = http.createServer((req, res) => {
// 1、根据书籍编号获取书籍详情
// url: bookdetail
// method:get
// params:bookid (书籍的编号)
// 返回数据格式:
// {
// status:"success",
// data:{
// bookid:"01001",
// bookname:"论语",
// bookauthor:"敖东",
// }
// }
// console.log("req.url",req.url);
let urlObj = url.parse(req.url, true);
if (urlObj.pathname === "/bookdetail") {
// 1、接收前端的数据
let bookid = urlObj.query.bookid;
// 2、查询数据库
// 3、响应
res.setHeader("Conent-type","text/plain");
if (bookid == "01001") {
res.write(`{
status: "success",
data: {
bookid: "01001",
bookname: "论语",
bookauthor: "敖东",
}
}`)
}else if (bookid == "01002") {
res.write(`{
status: "success",
data: {
bookid: "01002",
bookname: "中庸",
bookauthor: "王冰芊"
}
}`)
}else{
res.write(`{
status: "fail"
}`)
}
res.end();
}
// 2、注册
// url: regSave
// method:post
// params:
// username:用户名
// userpass:密码
// 返回数据格式:
// {
// status:"success",//fail
// }
if (urlObj.pathname === "/regSave") {
// 1、接收前端发来的数据
//用req.on绑定事件data:接收一次数据(一般来说:65536字节),触发一次data
let str = "";
req.on("data",(chunk)=>{
console.log("chunk",chunk);
// chunk: 本次接收到一块的数据
str += chunk;
});
//用req.on绑定事件end:接收完毕。
req.on("end",(err)=>{
if(!err){
console.log("接到数据是:",str);
// 2、处理(连接数据库)
// 3、响应
let obj = JSON.parse(str);
if(obj.username=="敖东" && obj.userpass=="123"){
// res.write(`{
// status:"success",
// }`);
// res.end();
res.end(`{
status:"success",
}`);
}else{
res.end(`{
status:"fail",
}`);
}
}
});
}
});
server.listen(9000, "localhost", () => {
console.log("启动成功,请访问……");
})
将处理业务(即就是接口的处理逻辑)统一放置在专门的js文件中,需要学习commonJS规范哦,明天带大家一起学习~这样我们前端人员也可以实现接口(有没有一丝丝激动呢)