時間過得很快,6月和7月忙的不可開交,糟心的事兒也是很多,杭州大連來回飛,也是呵呵。php
但願下個階段能沉浸下來,接着學本身想學的。記一下上幾周用了幾天時間寫的課設。由於課設的緣故,因此在短期裏瞭解下express+mongodb的組合,給APP端搭了個簡易的服務器,也開了後臺網站的web服務。簡單總結一下開發過程當中遇到的坑。html
1、關於express
瞭解node.js有半年多,第一次用node.js的框架來寫server,瞭解不是很深,簡單看了一下文檔以後就能夠上手了,開發入門難度低。
1.運行
express init以後覺得是node app.js命令運行項目,結果卻並非。app.js是項目入口文件不錯,可是自己也是一個module模塊,app.js的代碼裏面並無listenserver的操做,express的腳手架命令把項目啓動交給了bin/www文件,須要經過npm start啓動應用。
經過npm start的應用好像並不能實時重啓[?],因此能夠把www文件轉移至[new]start.js並運行node start.js,就可經過supervisor或者nodemon來自動監控&重啓應用了。java
2.中間件
express是基於中間件的。經過引入中間件執行處理函數,例如在處理一個get請求的時候會根據路由狀況在app.js裏順序執行函數,app.use('/admin', admin)就會處理全部localhost/admin下的請求,具體的第二級路由處理就交給了route/admin.js。這個課設裏我只本身定義了一箇中間件cookie-checker,用於登陸識別。在java或者php裏面能夠經過filter或者入口模塊檢測的方式來檢測cookie、判斷登陸,express裏面就剛簡化了,直接定義個cookie-checker中間件,放在了app.use('/api',api)和app.use('/admin', admin)中間,這樣全部的api請求(app端)無需cookie檢測,而admin下的請求所有須要通過登陸檢測操做,整個中間件的代碼以下:node
exports = module.exports = function(){ return function(req,res,next){ if( req.cookies.gid == undefined || req.cookies.gid == null ){ if( req.path != "/admin/login" ){ res.redirect("/admin/login"); } else{ next(); } } else{ next(); } } }
3.模塊引用
express裏面對模塊互相引用目測並無作什麼處理,固然產生互相引用確定是我本身代碼的緣由。
互相引用具體的位置忘了是哪裏了,可是大概是articleModule.js和favoriteModule.js形成的,在處理mongodb的連表查詢時候的問題。mongodb的連表也是糟心,後來也沒作連表,直接把favorite操做的記錄都add進一張大表裏了。以前兩年一直用的是mysql或者是sqlserver,在實際應用裏nosql的精神仍是沒有領會,設計表的時候以爲還挺簡單,實際應用起來就發現跟mysql、sqlserver徹底不是一個路數,連表、主鍵、外鍵都沒有。mysql
4.mvc的模式
如今寫個server不基於mvc都很差意思說本身是寫server的。express裏面作的仍是不錯的,route、view、modules。
route下是路由文件,用於處理路由請求,而且根據請求調用對應module的函數。全部的請求都是經過req、res、next來操做,內部函數大可能是基於回調的。view下全部的模板文件,課設裏面使用的是jade,感受和smarty等模板語言沒什麼功能區別,映射、分佈視圖、公共模塊、模板繼承、if-else等邏輯判斷,該有的都有,jade的語法卻是變了,寫的不是html標籤,節點名稱、縮進控制層級。modules下自定義的原型模塊,例如課設裏面大概有這麼幾個module:ad、article、word、user等,模塊內部引入mongoose文件完成增刪改查操做,增刪改查數據庫的函數都是異步的,因此在文件下大部分函數也都是基於回調的。
例如API路由下的api/wordItem?id=5x23434fa5sk4dhid7a,獲取的是某條句子的信息。在api.js裏:web
/* 單句(id) api/wordItem?id=5x23434fa5sk4dhid7a */ router.get('/wordItem', function(req, res, next) { var _id = req.query.id; var _user = req.query.uid || -1; word.findById(_id,function(err,data){ if( err ){ data._id = -1; } favorite.check({t_id:data._id,user_id:_user},function(_f){ data.flag = _f; res.send( data ); }); }); });
在word.js裏面:sql
//根據ID獲取word條目 var Word = mongodb.mongoose.model("word", wordSchema); var wordModel = function(){}; //... wordModel.prototype.findById = function(_id,callback){ var id = _id || 1; Word.findOne({'_id':id}, function(err, obj){ var itemdata = obj || {_id:-1} ; favorite.getCount({t_id:itemdata._id},function(err,count){ itemdata.favorite = count ; callback(err,itemdata); }); }); };
路由判斷---調用word原型的findById函數---函數內部執行mongoose封裝的WordModel的findOne操做,查詢結束後執行回調,將err參數和data參數做爲形參傳遞給回調函數。mongodb
5.文件上傳
用的是multer中間件,經過json配置直接處理了文件存儲位置、上傳回調。數據庫
app.use(multer({ dest: 'public/upload/', limits: { fieldNameSize: 100, files: 2, fields: 5 }, onFileUploadComplete: function (file, req, res) { res.flag = true; res.fname = file.name; }, onError: function (error, next) { res.flag = false; res.fname = ""; next(error); } }));
把public文件夾設置爲靜態路由:express
app.use(express.static(path.join(__dirname, 'public')));