npm 是随处可见的 Node 开发包管理器
npm install -g grunt-cli实现了全局安装
npm install -g express-generator
exports和modules.exports的区别
作用都是将文件模块的方法和属性暴露出来,但是两者存在本质的区别,exports的属性和方法都可以被module.exports替代,但是exports则不能替代modules.exports
modules.exports可以返回一个数组,字符串、数字等,而exports只能返回一个对象
NPM简介
node Packaged Modules的概述,是node.js的包的管理器。node.js本身提供一些基本的API模块,但是这些模块可能不够开发者使用。因此node.js需要使用NPM来管理开发者自我研发的一些模块,并能够适用于其它的开发者
NPM比较有用的模块
Node.js的项目框架 express、
socket.io模块:使用socket协议处理连接多请求的问题
forever模块:实现项目的运营,监控
jade模板:处理node.js无法内嵌html的问题
request模块:解决node发起的http请求
Express
安装
npm install -g express或者添加了安装的版本npm install -g express@3.0
在当前目录下创建一个app应用 express app
初始化app cd app&&npm install
运行app node app.js
可能会发生没有找到modules express解决的办法是在app文件夹下 npm install express
jade模板
node.js和java以及php都不相同,后两者可以内嵌到html代码中,但是node.js是不支持直接内嵌到html中
所以在视图层需要一个html的模板
jade的安装 npm install jade
jade基本语法
1、if条件语句
if ${name}=='admin'
p this is an admin
else
p this is not an admin
2、for循环语法
1、each
var items=[“one”,”two”,”three”];
each item in items
li=item
2、for循环
for user in users
for role in user.roles
li=role
forever模块
Node.js作为http服务器,需要确保项目的正常运行,要注意两点:
1、后台服务运行,监控日志以及http请求日志
2、确保项目的正常安全运行。Node.js的启动命令node,很大程度上无法满足运行需求
Node.js的forever模块在这点上起到了很大的作用,同时拥有监控文件修改、自动重启等其他功能
forever有两种方法:
1、在命令行中执行
2、在node.js的编码中通过require forever模块使用
forever安装
npm install forever -g
检查是否安装成功 npm install forever -g
借助express 的框架的app例子,接下来使用forever运行express项目运行指令如下
forever start -l forever.log -o out.log -e err.log app.js
在app目录下会生成out.log和err.log文件
socket.io模块
主要作用将WebSocket协议应用到所有的浏览器,该模块主要用于实时的长连接多请求项目中,例如在线联网游戏、实时聊天,二维码扫描登陆
安装socket.io
npm install socket.io
socket协议首先要了解其存在服务器端和客户端,因此要实现一个socket服务时,根据服务器端和客户端API分别实现其逻辑。服务器端启动进程等待客户端的来连接,首先创建一个服务器端的node.js脚本index_server.js的连接
index_server.js
//设置监听端口为80端口
var io=require('socket.io').listen(80);
//调用socket API中的socket.on接口,当客户端connection时,执行回调函数function(socket){}
io.sockets.on('connection',function(socket){
//来按揭成功后发送一个news消息,消息内容为一个json对象{hello:'world'}
socket.emit('news',{hello:'world'});
//客户端发送my other event消息时,服务器接受该消息。成功后获取该消息后执行回调函数function(data){}
socket.on('my other event',function(data){
console.log(data);
});
})
index_client.html
<script src="socket.js">
</script>
<script>
//创建本地socket socket服务器,默认为80端口,因此无需填写端口号
/* var socket=io.connect('https://localhost');*/
//修改服务器端的监听端口
var socket=io.connect('https://localhost:8080');
//socket接受news消息时执行回调函数function(data){}
socket.on('news',function(data){
console.log(data);
//客户端接受news消息成功后,发送my other event消息到服务器,发送的内容为json对象{my:'data'}
socket.emit('my other event',{my:'data'});
})
</script>
socket.io模块的使用
创建一个socket服务器端,监听本地3000端口,客户连接成功时,输出success信息,并将{state:’success’}发送给服务器。服务器消息后,判断state状态是否为success,是success就发送{me:’very good’}否则返回其他信息{other:’that is all’},客户端收到very good 后返回 {connection:good}
request模块
request模块为node.js开发者提供了一种简单的访问http请求的方法。
安装request模块
npm install request
request模块上基本上覆盖了所有http的请求方法get post head del等,两个最基本的方法是post和get
http中post和get的区别
get用于信息获取,post表示可能修改服务器上的资源的请求
get请求的数据会负在url后,以?分割和传输数据,参数之间用&来连接
post请求比get请求安全
post传输的数据没有限制,get传输的数据不能超过1024kb
服务器端处理get请求
app_get.js
//扮演的是服务器端
//创建http服务器
var http=require('http');
http.createServer(function(req,res){
res.writeHead(200,{'Content-Type':'text/plain'});
//在页面上显示hello World和http请求的方式
res.end('Hello World\n'+req.method);
}).listen(3000);
request_get.js
//扮演的客户端的角色
var request=require('request');
//应用request模块的get方法来发起一个http请求,两个参数分别是请求的url,回调函数
request.post('https://localhost:3000',function(error,response,result){
console.log(result);
})
服务器处理post请求
app_post.js 服务器的角色
//扮演的是服务器端
//创建http服务器
var http=require('http'),querystring=require('querystring');
http.createServer(function(req,res){
var postData="";
//开始异步的接受客户端post的数据
req.addListener("data",function(postDataChunk){
postDataChunk+=postDataChunk;
});
/* 异步post数据接受完成后执行匿名回调函数*/
req.addListener('end',function(){
var postStr=JSON.stringify(querystring.parse(postData));
res.writeHead(200,{'Content-Type':'text/plain'});
//在页面上显示hello World和http请求的方式
res.end(postStr+'\n'+req.method);
})
}).listen(3000);
request_post.js
//扮演的是服务器端
//创建http服务器
var http=require('http'),querystring=require('querystring');
http.createServer(function(req,res){
var postData="";
//开始异步的接受客户端post的数据
req.addListener("data",function(postDataChunk){
postDataChunk+=postDataChunk;
});
/* 异步post数据接受完成后执行匿名回调函数*/
req.addListener('end',function(){
var postStr=JSON.stringify(querystring.parse(postData));
res.writeHead(200,{'Content-Type':'text/plain'});
//在页面上显示hello World和http请求的方式
res.end(postStr+'\n'+req.method);
})
}).listen(3000);
Formidable模块
该模块主要是为了解决文件上传的目的
安装 npm install formidable
上传文件显示
var formidable=require('formidable'),http=require('http'),util=require('util');
http.createServer(function(req,res){
//判断路径是否为upload,如果是则执行文件上传,判断http请求是否为post
if(req.url=='/upload'&&req.method.toLowerCase()=='post'){
//new一个form对象
var form=new formidable.IncomingForm();
//解析POST数据
form.parse(req,function(err,fileds,files){
//应用form对象解析并获取http的参数
res.writeHead(200,{'Content-type':'text/plain'});
res.write('received upload:\n\n');
//将json对象转化为字符串
res.end(util.inspect({fields:fileds,files:files}));
});
return ;
}
res.end('
'); }).listen(3000);
Node.js设计模式
模块和类
node.js将一个模块理解为一个类
定义一个模块(类) 也就是一个简单的对象
//暴露给外边的
exports.name='danhuang';
//私有的
var myName='idanhuang';
exports.init=function(itName){
if(!itName){
setName(myName)
}
else{
setName(itName);
}
}
exports.show=function(){
console.log(name);
}
function setName(myName){
name=myName;
}
show.js使用刚才定义的简单的对象
var person=require('./class');
console.log(person.name);
person.init('zhao');
person.show();
console.log(person.myName);
node.js中的继承
继承的主要方式是通过util模块的inheritsAPI来实现继承,将一个构造函数的原型方法继承到另一个构造函数中。继承的例子:
var util=require('util');
var events=require('events');
function MyStream(){
}
//使用MyStream来继承events.EventEmitter的方法属性
util.inherits(MyStream,events.EventEmitter);
MyStream.prototype.write=function(data){
this.emit('data',data);
};
//创建MyStream对象
var stream=new MyStream();
//判断是否继承events.EventEmitter这个类
console.log(stream instanceof events.EventEmitter); //true
//判断MyStream类的对象MyStream.super_
console.log(MyStream.super_==events.EventEmitter); //true
//调用来自=events.EventEmitter的方法
stream.on('data',function(data){
console.log(data);
});
stream.write("IT works");
举例:学生、老师、程序员继承人这个类
person.js(基类)
//为什么使用module.exports而不是exports?exports返回的是一个json对象,而这里需要返回的是一个对象。所以在使用的时候必须得new出来才能使用
module.exports=function(){
this.name='person';
this.sleep=function(){
console.log('sleep in night');
}
this.eat=function(){
console.log('eat food');
}
}
继承person类的student类
var util=require('util');
var person=require('./person');
function student(){
person.call(this);
}
//student类继承Person
util.inherits(student,person);
student.prototype.study=function(){
console.log("i like study");
};
//暴露出student类
module.exports=student;
继承person类的teacher类
var util=require('util');
var person=require('./person');
function teacher(){
person.call(this);
}
//student类继承Person
util.inherits(teacher,person);
teacher.prototype.teach=function(){
console.log("i like teach");
};
//暴露出teacher类
module.exports=teacher;
继承person类的corder类
var util=require('util');
var person=require('./person');
function corder(){
person.call(this);
}
//student类继承Person
util.inherits(corder,person);
corder.prototype.code=function(){
console.log("i like code");
};
//暴露出student类
module.exports=corder;
显示各个类的showinherit类
var person=require('./person');
var student=require('./student');
var teacher=require('./teacher');
var corder=require('./corder');
//创建4个对象
var personobj=new person();
var studentobj=new student();
var teacherobj=new teacher();
var corderobj=new corder();
console.log("------------------person----------------------");
personobj.sleep();
console.log("------------------student----------------------");
studentobj.sleep();
studentobj.study();
console.log("------------------teacher----------------------");
teacherobj.sleep();
teacherobj.teach();
console.log("------------------coder----------------------");
corderobj.sleep();
corderobj.code();
node showinherit.js
------------------person----------------------
sleep in night
------------------student----------------------
sleep in night
i like study
------------------teacher----------------------
sleep in night
i like teach
------------------coder----------------------
sleep in night
i like code
如何实现重定义父类函数的方法
var util=require('util');
var person=require('./person');
function Overload(){
//先让this指针指向person
person.call(this);
this.eat=function(){
console.log('eat by overload function');
}
}
util.inherits(overload,person);
module.exports=overload;
使用静态调用(不用new对象)student中的方法和属性,
person.js基类
//为什么使用module.exports而不是exports?exports返回的是一个json对象,而这里需要返回的是一个对象
module.exports=function(){
this.name='person';
this.sleep=function(){
console.log('sleep in night');
}
this.eat=function(){
console.log('eat food');
}
}
student.js student类
var util=require('util');
var person=require('./person');
function student(){
person.call(this);
//student类继承Person
util.inherits(student,person);
this.aa=function(){
console.log("i like study");
}
}
var personobj=new person();
var ss=new student();
exports.aa=ss.aa;
exports.sleep=personobj.sleep;
showinherits.js
var student=require('./student');
//无需再创建对象
console.log("------------------student----------------------");
student.sleep();
student.aa();
node showinherits.js
------------------student----------------------
sleep in night
i like study
node.js中设计模式
对于一种服务器语言来说,设计模式的应用将决定该项目的可维护性和可扩展性。
single_class.js
单例设计模式
单例设计模式只有一个类只有一个实例,实现的方法一般是先判断实例是否存在,在的话就直接返回,如果不存在就会创建该对象
单例设计模式例子
single_class.js
//定义初始化_instance 存储Class对象
var _instance=null;
module.exports=function(time){
//定义单利类de属性
function Class(time){
this,name='danhuang';
this.book='Node.js';
this.time=time;
}
//利用原型来定义函数
Class.prototype={
constructor:Class,
show:function(){
console.log(this.book+this.name+this.time);
}
}
//获取单利类的接口
this.getInstance=function(){
if(_instance===null){
_instance=new Class(time);
}
return _instance;
}
}
siangle_app.js
var single=require('./single_class');
var singleobj1=new single('2012-11-10');
var singleClass1=singleobj1.getInstance('2012-11-10');
singleClass1.show();
var singleobj2=new single('2012-11-20');
var singleClass2=singleobj2.getInstance('2012-11-20');
singleClass2.show();
node siangle_app.js
Node.jsundefined2012-11-10
Node.jsundefined2012-11-10
适配器模式
将一个类的接口转换成客户希望的另外一个接口。adaptor设计模式使得原本由于接口不兼容而不能一工作的那些类可以一起工作
适配器工作模式
创建3个类target、adapter、adaptee
adapter继承target,adapter调用adaptee中的方法来实现
target.js
module.exports=function(){
this.request=function(){
console.log('target::request');
}
}
adapter.js 继承了target并且重写了
var util=require('util');
var target=require('./target');
var adaptee=require('./adaptee');
function adapter(){
target.call(this);
//重定义 父类的方法
this.request=function(){
var adapteeObj=new adaptee();
//利用的是adaptee中的specialRequest()方法
adapteeObj.specialRequest();
}
}
util.inherits(adapter,target);
module.exports=adapter;
adaptee.js定义了adapter需要使用的方法
module.exports=function(){
this.specialRequest=function(){
console.log('Adapter::specialRequest');
}
}
client.js
var Adapter=require('./adapter');
var target=new Adapter();
target.request();
node client.js Adapter::specialRequest
输出了 Adapter::specialRequest
装饰模式
动态地给一个对象添加一些额外的职责,就扩展功能而言,它比生成子类更为灵活。
会创建compontent类和其继承类DecZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcmF0b3KjrLzMs9DX1ERlY29yYXRvcsDgtcRjb25jcmV0ZURlY29yYXRvckG6zWNvbmNyZXRlRGVjb3JhdG9yQtewys7A4KOsPGJyIC8+DQq0tL2ou/nA4GNvbXBvbmVudKOszqrM7bzTb3BlcmF0aW9ut723qDwvcD4NCjxwcmUgY2xhc3M9"brush:java;">
module.exports=function(){
this.operation=function(){
console.log('compontent::operation');
}
}
创建原生继承类ConcreteCompontent,主要作用是展示Compontent装饰类中的属性和方法
var util=require('util');
var compontent=require('./compontent');
function ConcreteCompontent(){
compontent,call(this);
//覆盖了父类的operation方法
this.operation=function(){
console.log('output by the concrete compontent');
}
}
util.inherits(ConcreteCompontent,compontent);
module.exports=ConcreteCompontent;
创建了Decorator类来修饰Compontent类
var util=require('util');
var compontent=require('./compontent');
function Decorator(){
compontent.call(this);
}
//继承自基类compontent
util.inherits(Decorator,compontent);
module.exports=Decorator;
ConcreteDecoratorA装饰类,该类的目的是为了Compontent类的operation方法提供一些额外的操作
var util=require('util');
var Decorator=require('./Decorator');
function ConcreteDecoratorA(){
Decorator.call(this);
//重定义Comontent中的operation方法
this.operation=function(){
//调用被装饰类的方法
Decorator.operation();
//新添加的方法
console.log('add amethod a');
}
}
util.inherits(ConcreteDecoratorA,Decorator);
module.exports=ConcreteDecoratorA;
ConcreteDecoratorB装饰类,该类的目的是为了Compontent类的operation方法提供一些额外的操作B
var util=require('util');
var Decorator=require('./Decorator');
function ConcreteDecoratorB(){
Decorator.call(this);
//重定义Comontent中的operation方法
this.operation=function(){
//调用被装饰类的方法b
Decorator.operation();
//新添加的方法
console.log('add amethod b');
}
}
util.inherits(ConcreteDecoratorB,Decorator);
module.exports=ConcreteDecoratorB;
工厂模式
定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂模式就是将一个类的实例化延迟到其子类
创建一个product类同时添加getproduct方法
module.exports=function(){
this.getProduct=function(){
console.log('product is get form class factor')
}
}
A种产品 productA.js
var product=require('./product');
var util=require('util');
function productA(){
product.call(this);
this.getProduct=function(){
console.log('product is get form class factorA')
}
}
util.inherits(productA,product);
module.exports=productA;
B种产品 productB.js
var product=require('./product');
var util=require('util');
function productB(){
product.call(this);
this.getProduct=function(){
console.log('product is get form class factorB');
}
}
util.inherits(productB,product);
module.exports=productB;
产品工厂 productFactor
var productA=require('./productA');
var productB=require('./productB');
exports.createProduct=function(type){
switch(type){
case 'productA':return new productA();
break;
case 'productB':return new productB();
break;
}
}
client.js
var productFactory=require('./productFactor');
var pa=productFactory.createProduct('productA');
pa.getProduct();
var pb=productFactory.createProduct('productB');
pb.getProduct();
node client.js
product is get form class factorA
product is get form class factorB
编程">Node.js事件驱动编程
程序员必须知道有哪些事件,以及如何处理这些事件。最大的特点是异步回调函数
路由
是指向客户端提供它所发出的请求内容的机制。对于Web的客户端/服务器程序而言,客户端在URL中指明它想要的内容
才能使用express命令
express在出初始化一个项目的时候需要指定模板引擎,默认支持Jade和ejs
**
创建About和404的路由
var http=require('http');
http.createServer(function(req,res){
//规范化url、去掉查询字符串、可选的反斜杠、并把他们变成小写
var path=req.url.replace(/\/?(?:\?.*)?$/,'').toLowerCase();
switch (path){
case '':
res.writeHead(200,{'Content-Type':'text-plain'});
res.end('Homepage');
break;
case '/about':
res.writeHead(200,{'Content-Type':'text-plain'});
res.end('About');
break;
default :
res.writeHead(404,{'Content-Type':'text-plain'});
res.end('Not Found');
break;
}
}).listen(3000);
使用了一个函数动态的为服务器创建了多个路由
var http=require('http'),fs=require('fs');
function serveStaticFile(res,path,ContentType,responseCode){
if(!responseCode)
{
responseCode=200;
}
//console.log(__dirname)会输出当前helloWorld.js的所在的位置
//fs的readFile这个函数有两个参数1、文件的路径、2、读取完要执行的函数
fs.readFile(__dirname+path,function(err,data){
if(err){
res.writeHead(500,{'Content-Type':'text/plain'});
res.end('500-Internal Err');
}else{
res.writeHead(responseCode,{'Content-Type':ContentType});
res.end(data);
}
});
}
/*fs.readFile()这是一个异步读取文件的函数,调用这个函数读取指定文件中的内容,读取完之后会执行回调函数function(),
如果文件不存在,或者读取文件时遇到许可权限,或许文件不成功,文件会带着响应码和内容类型发送给客户端*/
http.createServer(function(req,res){
var path=req.url.replace(/\/?(?:\?.*)?$/,'').toLowerCase();
switch (path){
case '':
serveStaticFile(res,'/public/home.html','text/html');
break;
case '/about':
serveStaticFile(res,'/public/about.html','text/html');
break;
default :
serveStaticFile(res,'/public/about.html','text/html',404);
break;
}
}).listen(3000);
app.use方法和app.get
app.use方法和app.get是两个不同的方法:
app.use(只有一个函数作为参数)是express添加中间件的一种方法;
在express中添加中间件和路由的添加顺序十分重要,如果把处理404页面的代码放在最前边,那么首页和关于页面就不能用了
var express=require('express');
var app=express();
//指定程序的端口的方式
app.set('port',process.env.PORT||3000);
//app添加路由,使用的是get函数,
/*get函数有两个参数,一个路径和一个函数*/
app.get('/',function(req,res){
res.type('text/plain');
res.send('Meadowlark Travel');
});
app.get('/About',function(req,res){
res.type('text/plain');
res.send('About Meadowlark Travel');
});
//定制404页面
app.use(function(req,res){
res.type('text/plain');
res.status(404);
res.send('404-not Found');
});
//定制500页面
app.use(function(err,req,res,next){
console.log(err.stack);
res.type('text/plain');
res.status(500);
res.send('500-Server Error');
});
app.listen(app.get('port'),function(){
console.log('Express started on https://localhost'+app.get('port'));
})
视图和布局
模型-视图-控制器
一般的视图是html,express偏好的视图引擎是jade,但是jade非常简洁,对html有些抽抽象。所以建议使用Handlebars,对html不是太抽象
安装Handlebars
npm install -save express3-handlebars
//设置handlebars视图引擎
var handlebars=require('express-handlebars').create({defaultLayout:'main'});
app.engine('handlebars',handlebars.engine);
app.set('view engine','handlebars');
这段代码创建了一个视图引擎,并对Express进行了配置,将其作为默认的视图引擎
app.get('/',function(req,res){
//为首页设置视图模板
res.render('home');
});
其中的home这个默认视图引擎在views目录下的一个home.handlebars文件
视图和静态文件
Express靠中间件处理静态文件和视图
static中间件可以将一个或多个目录指派为静态资源的目录,其中的资源不经过任何特殊处理直接发送到客户端
应该把static中间件加在所有路由之前
“`
app.use(express.static(__dirname+’/public’));
package.json文件
这个文件是和meadowlark.js在同一个层次
文件的作用:1、列出这个项目所有的依赖项
{
"dependencies":{
"express":"^4.0.0",
"express3-handlebars":"^0.5.0"
}
}
2、存放项目的元数据 比如项目名称、作者、授权信息
Node模块
Node和npm包是两个互相关联又彼此不同的概念。
Node模块就像它的名字一样,提供了一个模块化和封装的机制。
npm包提供了一种存储、版本化和引用项目
var express=require('express');
require是一个用来引入模块的Node的函数。node的默认的目录在node_modules中寻找这些目录
页面测试
测试框架 Mocha
安装这个框架 npm install –save-dev mocha
测试通常需要一个assert函数。Node框架中有这个函数,但是浏览器中没有所以我们要使用Chai断言库
npm install --save-dev chai
请求和响应对象
url的组成部分:协议,主机名,端口,路径,查询字符串,信息片段
HTTP请求方法
get和post方法
请求的过程中包括请求报头和请求体
请求报头
浏览网页时,发送到服务器的并不只是URL。当你访问一个网站时,浏览器会发送很多隐形的信息
//测试请求报头 用户访问网站可以传递过来什么信息
app.get('/header',function(req,res){
res.set('Content-Type','text/plain');
var s="";
for(var name in req.headers){
s+=name+':'+req.headers[name]+'\n';
}
console.log(s);
res.send(s);
})
在页面上会输出
host:localhost:3000
connection:keep-alive
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36
accept-encoding:gzip, deflate, sdch
accept-language:zh-CN,zh;q=0.8
请求体
请求的主体:一般GET请求没有主体内容,但是post请求是有的
请求对象
请求对象req的生命周期始于Node的一个核心对象http.IncomingMessage的实例
响应对象
响应对象res的生命周期始于http.ServerResponse
响应报头
服务器进行响应时,同样会回传一些浏览器没必要渲染和显示的信息。
这些信息包括:响应状态码,响应的时间,内容类型(text/html;charset=UTF-8)
处理表单的不同方式
处理表单需要考虑两个方面的信息:1、处理的表单是哪个路径2、向浏览器发出怎样的响应
Express处理表单
1、如果使用get进行表单处理,表单域在req.query一个email的html输入的字段会存储在req.query.email
2、使用post需要中间件来进行URL编码体
安装body-paser
npm install –save body-parser
互联网媒体信息
我们常见的content type、Intent media type和MIME type是可以互换的。MIME是互联网的媒体类型的前身
创建一个Express命令创建一个网站的基本结构*
*
Express就像是一个脚手架
npm install –save express
安装express
npm install会把指定名称的包安装到node_modules目录下。如果使用了–save选项,还会更新package.json文件
express -t ejs microblog
用express实现的实际上就是一个node.js程序
express的目录结构
seo8YnIgLz4NCmFwcC51c2UoZmF2aWNvbihfX2Rpcm5hbWUgKyAmbHNxdW87L3B1YmxpYy9mYXZpY29uLmljbyZyc3F1bzspKTs8YnIgLz4NCmFwcC51c2UoYm9keVBhcnNlci51cmxlbmNvZGVkKHsgZXh0ZW5kZWQ6IGZhbHNlIH0pKTs8YnIgLz4NCi8vILao0uVjb29raWW94s72xvc8YnIgLz4NCmFwcC51c2UoY29va2llUGFyc2VyKCkpOzxiciAvPg0KLy8gtqjS5b6yzKzOxLz+xL/CvDxiciAvPg0KYXBwLnVzZShleHByZXNzLnN0YXRpYyhwYXRoLmpvaW4oX19kaXJuYW1lLCAmbHNxdW87cHVibGljJnJzcXVvOykpKTs8YnIgLz4NCi8vIMalxeTCt762us3Ct9PJPGJyIC8+DQphcHAudXNlKCZsc3F1bzsvJnJzcXVvOywgcm91dGVzKTs8YnIgLz4NCmFwcC51c2UoJmxzcXVvOy91c2VycyZyc3F1bzssIHVzZXJzKTs8YnIgLz4NCmFwcC51c2UoJmxzcXVvOy9oZWxsbyZyc3F1bzssaGVsbG8pOzwvcD4NCjxwPi8vIGNhdGNoIDQwNCBhbmQgZm9yd2FyZCB0byBlcnJvciBoYW5kbGVyPGJyIC8+DQphcHAudXNlKGZ1bmN0aW9uKHJlcSwgcmVzLCBuZXh0KSB7PGJyIC8+DQp2YXIgZXJyID0gbmV3IEVycm9yKCZsc3F1bztOb3QgRm91bmQmcnNxdW87KTs8YnIgLz4NCi8vIDQwNLTtzvO0psDtPGJyIC8+DQplcnIuc3RhdHVzID0gNDA0OzxiciAvPg0KbmV4dChlcnIpOzxiciAvPg0KfSk7PC9wPg0KPHA+Ly8gZXJyb3IgaGFuZGxlcnM8YnIgLz4NCi8vIGRldmVsb3BtZW50IGVycm9yIGhhbmRsZXI8YnIgLz4NCi8vIHdpbGwgcHJpbnQgc3RhY2t0cmFjZTxiciAvPg0KLy8gv6q3oru3vrOjrDUwMLTtzvO0psDtus207c7zttHVu7j619k8YnIgLz4NCmlmIChhcHAuZ2V0KCZsc3F1bztlbnYmcnNxdW87KSA9PT0gJmxzcXVvO2RldmVsb3BtZW50JnJzcXVvOykgezxiciAvPg0KYXBwLnVzZShmdW5jdGlvbihlcnIsIHJlcSwgcmVzLCBuZXh0KSB7PGJyIC8+DQpyZXMuc3RhdHVzKGVyci5zdGF0dXMg"| 500);
res.render(‘error’, {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
// 生产环境,500错误处理
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render(‘error’, {
message: err.message,
error: {}
});
});
/*app.listen(3000,function(){
console.log(‘server start …’);
});*/
// 输出模型app
app.listen(3000,function(){
console.log(‘server start …’);
});
module.exports = app;
模板引擎
模板引擎:是一个从页面模板根据一定的规矩生成HTML的工具
模板引擎的功能是将页面模板和要显示的数据结合起来生成HTML页面,既可以被运行在服务器端又可以运行在客户端,大多数的时候都在服务器端被解析为html。之后再传给客户端
使用模板引擎
app.set(‘views’, __dirname + ‘/views’)
app.set(‘view engine’, ‘jade’);
表明要使用的模板引擎是jade,页面在view子目录下。
res.render(‘index’,{title:’Express’})
res.render()的功能就是调用模板引擎,并将产生的页面直接返回给客户端。接受两个参数,
1、模板的名称
2、传递给模板的数据
用户注册和登陆
数据库">1、访问数据库
2、MongoDB
它是一个对象数据库,没有表和行的概念,也没有固定的模式和结构,所有的数据以文档的形式存储。所谓的文档就是一个关联数组式的对象,内部由属性组成,一个属性可能是一个数、字符串、日期、数组、甚至是一个文档
这些格式看起来好像json,没错,MongoDB的数据格式就是json,在MongoDB中对数据的操作都是以文档为单位的,为了加快查询,MongoDB页对文档实现了索引
3、连接数据库
开启mongodb
D:\software\monogodb\mongodb\bin>mongod -config D:\software\monogodb\mongodb.config
4、会话的概念
会话是一种持久的网络协议,用于完成服务器和客户端之间的一些交互行为。会话是一个比连接粒度大的概念,一次会话可能有多次连接,每次连接都被认为是会话的一次操作。在网络应用开发中,有必要实现会话以帮助用户交互。例如网上购物的场景,用户浏览了多个页面,购买了一些物品,这些请求在多次连接中完成。许多应用层的协议都是由会话支持的,如ftp、Telent,而http协议是无状态的,本身不支持会话,在额外手段的支持下,
为了无状态的http协议之上实现会话,cookie诞生了。cookie是存储在客户端的信息,每次连接的时候由浏览器向服务器递交,服务器也向浏览器发起存储cookie的请求,依靠这样的手段卡哇伊识别客户端