Node.js入门笔记(6):web开发方法
使用node进行web开发
用户上网流程:
表面上看:打开浏览器——输入网址——跳转——上网。
背后的过程是什么呢?
http请求网址到指定的主机——服务器接收请求——服务器响应内容到用户浏览器——浏览器接收到数据,并根据接收到的信息进行处理,渲染出用户看到的界面。
名词解释:
客户端——用户浏览器;
服务端——服务端
现在再精简下描述:
由客户端发送一个http请求到服务端,服务端接收并处理请求,返回数据到客户端。
搭服务器
收发数据遵循一定的规则————一般是http规则。
搭建服务器,处理http请求,需要node.js提供一个http模块。
//加载一个http模块
var http=require('http');
//通过http模块下的creatServer方法创建并返回一个服务器对象
var server=http.createServer();
//开启服务器,接收四个参数
// 参数第一个是端口,第二个是ip,第三个是链接等待队列的最大长度,第四个成功开启之后的回调
server.listen();
这个时候输入console.log(server.address())
,结果返回:
{ address: '::', family: 'IPv6', port: 57379 }
port端口号每次都改变,所以一般要自己设置。端口号尽量设大点。
http - http模块 - require('http')
var http = require('http');
var server = http.createServer([requestListener])
–创建并返回一个HTTP服务器对象
–requestListener : 监听到客户端连接的回调函数
server.listen(port, [hostname], [backlog], [callback])
–监听客户端连接请求,只有当调用了listen方法以后,服务器才开始工作
–port : 监听的端口
–hostname : 主机名(IP/域名)
–backlog : 连接等待队列的最大长度
–callback : 调用listen方法并成功开启监听以后,会触发一个listening事件,callback将作为该事件的执行函数
listening事件:当server调用listen方法并成功开始监听以后触发的事件
error事件 : 当服务开启失败的时候触发的事件
–参数err : 具体的错误对象
全部代码如下,一个服务器就搭建完毕了。
//加载一个http模块
var http=require('http');
//通过http模块下的creatServer方法创建并返回一个服务器对象
var server=http.createServer();
//开启服务器,接收四个参数
// 参数第一个是端口,第二个是ip,第三个是链接等待队列的最大长度,第四个成功开启之后的回调
server.on('error',function (err) {//报错方法
console.log('错误信息:'+err);
});
server.on('listening',function () {
console.log('服务器正在运行...');
console.log(server.address());
});//运行提示
server.listen(8088,'localhost');//绑定8088端口
输出结果:
服务器正在运行...
{ address: '127.0.0.1', family: 'IPv4', port: 8088 }
request事件
在上面的代码插入一段
server.on('request',function () {
console.log('有客户端请求了!')
});
然后通过浏览器输入127.0.0.1:8088,这时弹出会弹出相应的信息。
注意:之前提到的createServer方法。它其实接收一个回调函数,也就是说二者其实是一样的。
request事件 : 当有客户端发送请求到该主机和端口的请求的时候触发
仅仅接收请求是没有多大意义的。还需要对客户端的请求进行分析。
- 参数request : http.IncomingMessage的一个实例,通过他我们可以获取到这次请求的一些信息,比如头信息,数据等。
server.on('request',function (req,res) {
console.log('有客户端请求了!')
console.log(req);
});
重新载入页面,发现第一个参数request是一大串的信息。
里面有许多常用的方法。
httpVersion : 使用的http协议的版本,通常是1.1
headers : 请求头信息中的数据
url : 请求的地址
method : 请求方式(GET/POST)
参数response : http.ServerResponse的一个实例,通过他我们可以向该次请求的客户端输出返回响应
比如说请求发过来了,但是客户端一直在等待,而服务器未向客户端发送任何数据。可以通过server.timout
方法设置最长等待时间。write(chunk, [encoding]) : 发送一个数据块到响应正文中,数据块,编码
end([chunk], [encoding]) : 当所有的正文和头信息发送完成以后调用该方法告诉服务器数据已经全部发送完成了,这个方法在每次完成信息发送以后必须调用,并且是最后调用.
server.on('request',function (req,res) {
console.log('有客户端请求了!');
res.write('朕知道你发请求了','utf-8');//光是写入还不行,必须告诉客户端写完了
res.end();
//console.log(res);
});
客户端再刷新的结果,厉害了:
你也可以在你的文档里写如一段html代码。还可以设置头信息。
- statusCode : 该属性用来设置返回的状态码
- setHeader(name, value) : 设置返回头信息
- writeHead(statusCode, [reasonPhrase], [headers])//状态码(200,404等),
状态码可以通过输入http.STATUS_CODES
点击进行查看
这个方法只能在当前请求中使用一次,并且必须在response.end()之前调用
res.writeHead(200,'SUNNY');//定义成功时的描述文字
请求参数req里的url处理
上面的服务器有重大的缺陷。url无论输入localhost/1....后面长度无论怎样,返回的都是一个信息。
以下我们用case来模拟首页('/'),个人中心('/user')和404('defult')的响应情况
新建一个服务器。
var http=require('http');
var server=http.createServer();
server.on('request',function (req,res) {
//通过req的url属性回应数据
//?后面的部分是query string查询字符串
console.log(req.url)
});
server.listen(8089,'localhost');
当访问localhost:8089/xxx
时,打印出来的url为/xxx
再分析下url对象这个东西。路径名有时候是非常1复杂的,包含?等等参数。对url进行预处理很有必要,这就涉及到url对象
var http=require('http');
//请求url模块,并把url序列化想要的格式
var url=require('url');
var server=http.createServer();
server.on('request',function (req,res) {
//通过req的url属性回应数据
//?后面的部分是query string查询字符串
//console.log(req.url)
var urlStr=url.parse('http://www.baidu.com/a/index.html?c=2');
console.log(urlStr);
});
server.listen(8089,'localhost');
得到的打印出来的是
分析上面的内容发现,我们需要urlStr.pathname
var http=require('http');
//请求url模块,并把url序列化想要的格式
var url=require('url');
var server=http.createServer();
server.on('request',function (req,res) {
//通过req的url属性回应数据
//?后面的部分是query string查询字符串
//console.log(req.url)
var urlStr=url.parse(req.url);
//console.log(urlStr);
switch(urlStr.pathname){
case '/':
//首页,没有什么后缀
res.writeHead(200,{
'content-type':'text/html;charset=utf-8'
});
res.end('<h1>首页</h1>');
break;
case '/user':
//用户首页
res.writeHead(200,{
'content-type':'text/html;charset=utf-8'
});
res.end('<h1>个人中心</h1>');
break;
default:
res.writeHead(404,{
'content-type':'text/html;charset=utf-8'
});
res.end('<h1>404</h1>');
//处理其他情况
break;
}
});
server.listen(8089,'localhost');
那么url处理就算成功了。
表现和行为的分离
上面的代码中,每次针对每个页面输入不一样的内容,看起来是非常麻烦的。
作为规则,把html写进代码也是不符合规范的。也不利于维护。
所以我们需要用res的方法把它读取出来,再放到页面上去。
可以在同目录下新建一个html文件夹,创建首页(index.html)、用户中心(user.html)、404.html并写上各自的内容。然后用fs对象来读它。
var http=require('http');
var url=require('url');
var fs=require('fs');
var server=http.createServer();
var htmlDir='./html/';
server.on('request',function (req,res) {
var urlStr=url.parse(req.url);
//console.log(urlStr);
switch (urlStr.pathname){
case '/':
sendData(htmlDir+'index.html',req,res);
break;
case '/user':
sendData(htmlDir+'user.html',req,res);
break;
default:
sendData(htmlDir+'404.html',req,res);
break;
}
});
//应该定义一个方法,当根据路径来读取页面,然后把所需要的页面返回出去。
//三个参数:file是文件路径
function sendData(file,req,res) {
//这个方法的核心是读取文件内容。
fs.readFile(file,function (err,data) {
if(err){//如果读取失败,也就是404
console.log(err);
res.writeHead(404,{
'content-type':'text/html;charset=utf-8'
});
res.end(data);
}else{
res.writeHead(200,{
'content-type':'text/html;charset=utf-8'
});
//console.log(data.toString());
res.end(data);
}
});
}
server.listen('8089','localhost');
效果就实现了。但实际上代码还存在很多不必要的case语句。尝试再修改:
var http=require('http');
var url=require('url');
var fs=require('fs');
var server=http.createServer();
var htmlDir='./html';
server.on('request',function (req,res) {
var urlStr=url.parse(req.url);
switch (urlStr.pathname){
case '/':
sendData(htmlDir+'/index.html',req,res);
break;
default:
var urlPath=htmlDir+urlStr.pathname+'.html';
sendData(urlPath,req,res);
}
});
//应该定义一个方法,当根据路径来读取页面,然后把所需要的页面返回出去。
//三个参数:file是文件路径,
function sendData(file,req,res) {
//这个方法的核心是读取文件内容。
fs.readFile(file,function (err,data) {
if(err){//如果读取失败,也就是404
console.log(file)
console.log(err);
fs.readFile('./html/404.html',function(err,data){
res.writeHead(404,{
'content-type':'text/html;charset=utf-8'
});
res.end(data);
});
}else{
res.writeHead(200,{
'content-type':'text/html;charset=utf-8'
});
//console.log(data.toString());
res.end(data);
}
});
}
server.listen('8089','localhost');
在这个代码下,尝试读取任何页面都有回应。我在html文件夹下创建了一个新的xxx.html读取也能正确。代码也简化了。这样基本效果就令人满意了。
遗憾的是当前还不支持css,js外链。
请求处理
为了说明原理,还是采用上面的例子代码。
- get请求的数据处理
在html文件夹下创建一个login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<h1>这是登陆页面</h1>
<form action="/login/validate" method="get">
请输入用户名:<input type="text" name="username"><br>
请输入密码:<input type="text" name="password"><br>
<button type="submit">提交!</button>
</form>
</body>
</html>
如何获取用户提交过来的内容呢?在之前声明过的urlStr里面就包含了这些数据。
var http=require('http');
var url=require('url');
var fs=require('fs');
var server=http.createServer();
var htmlDir='./html';
server.on('request',function (req,res) {
var urlStr=url.parse(req.url);
switch (urlStr.pathname){
case '/':
sendData(htmlDir+'/index.html',req,res);
break;
case '/login/validate':
//想得到用户提交过来的数据
//console.log(req.method)//提交方式get/post
console.log(urlStr);
break;
default:
var urlPath=htmlDir+urlStr.pathname+'.html';
sendData(urlPath,req,res);
}
});
function sendData(file,req,res) {
//这个方法的核心是读取文件内容。
fs.readFile(file,function (err,data) {
if(err){//如果读取失败,也就是404
console.log(file)
console.log(err);
fs.readFile('./html/404.html',function(err,data){
res.writeHead(404,{
'content-type':'text/html;charset=utf-8'
});
res.end(data);
});
}else{
res.writeHead(200,{
'content-type':'text/html;charset=utf-8'
});
//console.log(data.toString());
res.end(data);
}
});
}
server.listen('8089','localhost');
登陆locoalhost:8089/login
输入用户名密码,提交,发现打印出下列内容:
其中关键属性是query。
原来用户名是213,密码是231.
怎么实现自动化处理呢?node.js提供了必要的方法。
querystring模块
parse() : 将一个 query string 反序列化为一个对象
case '/login/validate':
//想得到用户提交过来的数据
//console.log(req.method)//提交方式get/post
var querystring=require('querystring');
console.log(querystring.parse(urlStr.query));
break;
结果打印出来一个json:{ username: '213', password: '231' }
实在是太方便了。有了它,就可以很方便的处理提交信息。
- post请求的数据处理:req的data和end事件
接下来把login.html页面的提交方式改为post
post发送的数据会被写入缓冲区中,需要通过resquest的data事件和end事件来进行数据拼接处理
if(req.method.toUpperCase()=='POST'){
var str='';
req.on('data',function (chunk) {
str+=chunk;
});
req.on('end',function () {
console.log(str);
})
}
打印出来的str为username=123&password=321
对于这样格式写成的数据自然想到了用querystring.parse()进行处理。处理完之后就是一个json对象了。
全部代码:
var http=require('http');
var url=require('url');
var fs=require('fs');
var server=http.createServer();
var htmlDir='./html';
server.on('request',function (req,res) {
var urlStr=url.parse(req.url);
switch (urlStr.pathname){
case '/':
sendData(htmlDir+'/index.html',req,res);
break;
case '/login/validate':
//想得到用户提交过来的数据
//console.log(req.method)//提交方式get/post
if(req.method.toUpperCase()=='POST'){
var str='';
req.on('data',function (chunk) {
str+=chunk;
});
req.on('end',function () {
console.log(str);
var querystring=require('querystring');
console.log(querystring.parse(str));
});
}else if(req.method.toUpperCase()=='GET'){
var querystring=require('querystring');
console.log(querystring.parse(urlStr.query));
}
break;
default:
var urlPath=htmlDir+urlStr.pathname+'.html';
sendData(urlPath,req,res);
}
});
function sendData(file,req,res) {
//这个方法的核心是读取文件内容。
fs.readFile(file,function (err,data) {
if(err){//如果读取失败,也就是404
console.log(file)
console.log(err);
fs.readFile('./html/404.html',function(err,data){
res.writeHead(404,{
'content-type':'text/html;charset=utf-8'
});
res.end(data);
});
}else{
res.writeHead(200,{
'content-type':'text/html;charset=utf-8'
});
//console.log(data.toString());
res.end(data);
}
});
}
server.listen('8089','localhost');
Node.js入门笔记(6):web开发方法的更多相关文章
- Node.js入门笔记(5):案例两则
案例分析:前端自动化 1. 实现一个自动创建前端项目文件的js 通过node.js自动创建前端项目目录,包括js目录,js目录css目录,index.html和对应的内容. 初步的代码如下: var ...
- Node.js入门笔记(1):基本概念
Node.js和JavaScript: 核心都是ECMAScrit,比如数据类型,语法结构,内置对象等等. 但是在js中顶层是window 在node中的不存在这个window(console.log ...
- Node.js入门笔记
第一步自然是安装了.我是用Webstorm这个ide,安装分2步: 1.安装nodejs,下载Windows下的安装版本号.注意是以msi为扩展名的,然后下一步.没啥好说的,下载地址例如以下: 32位 ...
- Node.js入门笔记(2):全局对象(1)
以下将以API文档为基础进行分析学习 global对象 这些对象在所有模块里都可用.有些对象不是在全局作用域而是在模块作用域里,这些情况下面文档都会标注出来. __filename--返回当前模块文件 ...
- Node.js入门笔记(4):文件系统(fs)
文件系统(FileSystem) 文件系统模块 对于文件无外乎创建修改添加. File System - 文件系统模块 - require('fs') fs模块是核心模块,需要使用require导入后 ...
- Node.js入门笔记(3):全局对象(2)
buffer 用于更好操作二进制数据,他是一个全局变量.类似数组. var a=new Buffer(); buffer类的三种实现 第一种创建方式 new Buffer(size);size[Num ...
- Node.js 入门资料
小毛驴的阿凡提的 Node.js 入门笔记 http://www.cnblogs.com/Afanty/category/1007304.html
- 《Node.js入门》CentOS 6.5下Node.js Web开发环境搭建笔记
近期想尝试一下英特尔的基于WebRTC协同通信开发套件,所以须要在本地搭建Node.js Web的开发測试环境. 这里讲的是CentOS 下的搭建方法.使用Windows的小伙伴请參考: <No ...
- Node.js 入门手册:那些最流行的 Web 开发框架
这篇文章与大家分享最流行的 Node.js Web 开发框架.Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用程序,编 ...
随机推荐
- Linux 服务器模型小结
当我们用socket进行编程的时候,细节上都是选择一个AF_LOCAL,AF_INET再根据相应的类型填充地址,其实根据通信需求,有几种简单的服务模型可供选用,掌握了这些框架再结合socket高度的抽 ...
- x01.TextProc: 两三分钟完成的一个小工具
在工作中,遇到这么个问题,需要将 Excel 表中类似 2134-1234-4456 的商品编号输入到单位的程序中,而程序只认 213412344456 这种没有 ‘-’ 的输入.数量比较多,一笔一笔 ...
- Linux一些经典书籍
一.linux之路 1.入门篇 <LINUX权威指南>书不错,写的很全面也比较广,涉及的不深,做为入门书籍不错,可以比较全面的了解linux .另外比较热门的也可以看看<鸟哥的私房菜 ...
- 【转载】Linux中常用操作命令
说明:开始学习linux系统,为了方便查看,特转载一篇Linux中常用操作命令,转载地址:http://www.cnblogs.com/laov/p/3541414.html 正文: Linux简介及 ...
- MMORPG大型游戏设计与开发(服务器 AI 概述)
游戏世界中我们拥有许多对象,常见的就是角色自身以及怪物和NPC,我们可以见到怪物和NPC拥有许多的行为,比如说怪物常常见到敌对的玩家就会攻击一样,又如一些NPC来游戏世界中走来走去,又有些怪物和NPC ...
- BZOJ 3112: [Zjoi2013]防守战线 [单纯形法]
题目描述 战线可以看作一个长度为n 的序列,现在需要在这个序列上建塔来防守敌兵,在序列第i 号位置上建一座塔有Ci 的花费,且一个位置可以建任意多的塔,费用累加计算.有m 个区间[L1, R1], [ ...
- java 移位运算符
java中有三种移位运算符 << : 左移运算符,num << 1,相当于num乘以2 >> : 右移运算符,num >& ...
- 使用spring方式来实现aop编程
1:什么是aop? Aspect Oriented Programming 面向切面编程 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译 ...
- IEnumerable,IQueryable之前世今生
来自于:http://www.cnblogs.com/chengxiaohui/articles/2088967.html IEnumerable<T>在.Net2.0中我们已经很熟悉了. ...
- JS截取字符串
使用 substring()或者slice() 函数:split() 功能:使用一个指定的分隔符把一个字符串分割存储到数组例子:str=”jpg|bmp|gif|ico|png”;arr=theStr ...