//使用supervisor
Connect是基于HTTP米快创建的;Express则是基于Connect上创建的;
绝大多数web服务器和浏览器之间的任务是通过url和method完成的,两者的组合称为路由;
使用express:
- 引入:
var express = require('express'); var app = express.createServer();
//express 4.x修改:
var express = require('express'); var app = express();
- 配置: app.set();
app.set('view engine', 'ejs'); //模版引擎 app.set('views', __dirname + '/views'); //目录
//console.log(app.set('views')) //查询某一配置 - 定义路由:
- 加载视图render:
- 初始化模版引擎
- 读取视图文件并将其传递给模版引擎
- 获取解析后的HTML页面并作为响应发送给客户端
app.get('/', function(req, res) { res.render('index'); //由于之前在app.set()中配置视图引擎,所以不需要显示指明index.ejs });
- 使用 superagent //ajax api
例子:
- package.json:
{ "name": "express-tweet", "version": "0.0.1", "dependencies": { "express": "2.5.9", "ejs": "0.4.2", "superagent": "0.3.0" } }
- 为避免将HTML代码嵌入到应用逻辑中,使用模版语言来处理:EJS(embedded js);
//这里将他们放到views文件夹中 ---------------index.ejs------------------ <h1>Twitter app</h1> <p>Please enter your search term:</p> <form action='/search' method='GET'> <input type='text' name='q'/> <button>Search</button> </form> -----------------serach.ejs----------------- <h1>Tweet results for <%= search %></h1> <% if(results.length) { %> <ul> <% for(var i = 0; i < results.length; i++) { %> <li><%= results[i].text %>- <em><%= results[i].form_user %></li> <% } %> </ul> <% else %> <p>No results</p> <% } %>
- js代码:
------------search.js------------------ var request = require('superagent'); //ajax api module.exports = function search(query, fn) { request.get('https://twitter.com/search') .send({q:query}) .end(function(res) { if(res.body && Array.isArray(res.body.results)) { return fn(null, res.body.results); } fn(new Error('Bad twitter response')); }) } -------------------------server.js-------------------------- var express = require('express'); var search = require('./search'); var app = express.createServer(); app.set('view engine', 'ejs'); app.set('views', __dirname + '/views'); app.set('view options', {layout: false}); app.get('/', function(req, res) { res.render('index'); }); app.get('/search', function(req, res, next) { search(req.query.q, function(err, tweets) { if(err) return next(err); res.render('search', {results: tweets, search: req.query.q}); }) }); app.listen(3000);
设置://express具有对环境设置的管理能力;比如在生产环境下,为了提高性能可以让express将模版缓存起来加快响应速度;而在开发环境下这样会使每次模版改动都要重启服务器;所以可以通过改变当前环境设置的方法解决问题;
- 设置环境://默认为’development'
- process.env.NODE_ENV = 'production';
- app.set('env', 'production');
- NODE_ENV=production node app.js; //window下不行
- app.configure:
//全局 app.configure(function(){ app.set('title', 'My Application'); }); //仅在production下 app.configure(’production',function(){ app.set('title', 'My Application'); });
//对于布尔值类型的设置可以直接用 app.disable('view cache'); app.enable('view cache');
//app.configure可以用条件判断语法取代。 if ('development' == app.get('env')) { //--- } if ('production' == app.get('env')) { //--- }
-
一些其他设置:
-
case sensitive routing 路由的大小写敏感, 默认是关闭状态;
-
strict routing 路由的严格格式, 默认情况下 "/foo" 和 "/foo/" 是被同样对待的;
-
模板引擎:
- 在开头的时候全部配置:
app.set('view engines','ejs'); ---使用时可以直接省略后缀--- app.get('/', function(req, res) { res.render('index'); });
- 直接使用
app.get('/', function(req, res) { res.render('index.html'); });
- app.register:将扩展名匹配到指定的模版引擎: app.register('.html',require('jade'));
错误处理:
- app.error:
app.error(function(err, req, res, next) { if('Bad twitter response' == err.message){ res.render('twitter-error'); } else { next(); } });
- 设置多个:如当调用next并且对应的处理器无法找到时,默认的express错误处理器就会触发
app.error(function(err, req, res) { res.render('error', {status: 500}); })
路由:
- 自定义参数:
app.get('/', function(req, res) { }); app.get('/post/:name', function(req, res) { //req.params.name }); app.get('/post/:name?', function(req, res) { //表示:name是可选的,即可以匹配/post,也可以匹配/post/.. });
- 可以直接使用RegExp对象设置路由;
- 在路由处理程序中使用next; //即当一个路由匹配,还是可以强制express继续匹配其他路由
app.get('/post/:name', function(req, res, next) { if('h' != req.params.name[0]) return next(); //........... });
中间件:由于express是构建与connect之上的,当创建服务器时可以直接使用connect兼容的中间件;
app.use(express.static(__dirname + '/img')); app.use(express.cookieParser()); app.use(express.session());
- express还允许中在特定匹配到的路由器中使用中间层;
function secure(req, res, next) { if(!req.session.logged_in) { return res.send(403); } next(); }; app.get('/home', function() { //accessible to everyone }); app.get('/financials',secure, function() { //secure }); app.get('/about', function() { //accessible to everyone }); app.get('/roadmap', secure, function() { //secure }); ---------------------------为路由定义多个中间件 app.post('/route',a,b,c,function(){}); --------------------------中间件中调用next function secure(req, res, next) { if(!req.session.logged_in) { return next('route'); } next(); };
代码组织://第一准则:模块化;
好的代码组织当是维护一个server.js文件,该文件中包含了路由表,同时将每一部分的路由处理器通过模块化的方式来引入;
- 首先定义依赖的模块并初始化app,引入中间件:
var express = require('express'), blog = require('./blog'); pages = require('/pages'); var app = express.createServer();
- 接着定义路由表:
app.get('/blog', blog.home); app.get('blog/serach',blog.search); app.get('pages', pages.home); app.get('pages/list', pages.list);
- 然后设置每个模块需要的exports函数:
//blog.js exports.home = function(req, res, next){....}; exports.search = function(req, res, next){....};