node.js開發網站
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來管理開發者自我研發的一些模塊,並能夠適用於其它的開發者
Advertisements
NPM比較有用的模塊
Node.js的項目框架 express、
socket.io模塊:使用socket協議處理連接多請求的問題
forever模塊:實現項目的運營,監控
jade模板:處理node.js無法內嵌html的問題
request模塊:解決node發起的http請求
Express
安裝
npm install -g express或者添加了安裝的版本npm install -g [email protected]
在當前目錄下創建一個app應用 express app
初始化app cd app&&npm install
運行app node app.js
可能會發生沒有找到modules express解決的辦法是在app文件夾下 npm install express
Advertisements
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('http://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('http://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;
});
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;
});
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類和其繼承類Decorator,繼承自Decorator類的concreteDecoratorA和concreteDecoratorB裝飾類,
創建基類component,為添加operation方法
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);
}
});
}
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函數,
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 http://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的目錄結構
`
對app.js文件的解析
/載入依賴庫,原來這個類庫都封裝在connect中,現在需地注單獨載入/
//導入Express模塊
var express = require(『express』);
//文件夾形式的本地模塊,功能是為指定的路徑組織返回內容,相當於mvc開發中的框架中的控制器
// 載入路由控制
var routes = require(『./routes/index』);
var users = require(『./routes/users』);
var hello = require(『./routes/hello』);
var http=require(『http』);
//用於處理目錄的對象
var path = require(『path』);
var favicon = require(『serve-favicon』);
var logger = require(『morgan』);
var cookieParser = require(『cookie-parser』);
var bodyParser = require(『body-parser』);
// 創建項目實例
var app = express();
// view engine setup
// 設置views路徑和模板
//__dirname是node.js裡面的全局變數,即取得執行的js所在的路徑,另外__dirname是目前執行的js文件名。所以,app.set(『views』, __dirname + 『/views』);是設置views的文件//夾。
app.set(『views』, __dirname + 『/views』)
//設置express.js所使用的render engine。除了Jade之外,express.js還支持EJS(embedded javascript)、Haml、CoffeScript和jQuery template等js模板
app.set(『view engine』, 『jade』);
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 『public』, 『favicon.ico』)));
/是Connect內建的middleware,設置此處可以將client提交過來的post請求放入request.body中。/
/app.use 載入用於處理http請求的middleware(中間件),當一個請求來的時候,會依次被這些 middlewares處理。/
//express.bodyParser()是Connect內建的middleware,設置此處可以將client提交過來的post請求放入request.body中 並以json格式作為參數。
// 定義數據解析器
app.use(bodyParser.json());
// 定義日誌和輸出級別
app.use(logger(『dev』));
// 定義icon圖標
app.use(favicon(__dirname + 『/public/favicon.ico』));
app.use(bodyParser.urlencoded({ extended: false }));
// 定義cookie解析器
app.use(cookieParser());
// 定義靜態文件目錄
app.use(express.static(path.join(__dirname, 『public』)));
// 匹配路徑和路由
app.use(『/』, routes);
app.use(『/users』, users);
app.use(『/hello』,hello);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error(『Not Found』);
// 404錯誤處理
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
// 開發環境,500錯誤處理和錯誤堆棧跟蹤
if (app.get(『env』) === 『development』) {
app.use(function(err, req, res, next) {
res.status(err.status || 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
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的請求,依靠這樣的手段卡哇伊識別客戶端