摸着石头过河---nodejs的express框架

[url=http://yuezaixz.logdown.com/posts/168553-the-stones-nodejs-express-frame][color=red][b][size=xx-large]logdown博文链接[/size][/b][/color][/url]
今天博文比较长,就没重新排版了,欢迎各位戳logdown博文的地址。

今天家里有事没上班,终于可以好好写一篇关于总结的博文了。
转眼,作为团队项目管理的工作已经2个月了,这期间团队每两周也都会做一次总结,但是我觉得我也该自己独自总结下这两个月工作了,这两个月中团队是存在很多问题,毕竟接触项目管理方面的都是通过书本和敏捷大会、沙龙获得的理论知识,付诸于实践后肯定会有一些问题,还好之前所在的团队很善于总结,所以对于一些问题我还是会有一些想法要怎么处理,确实是有一些作用的。
比如我们开展敏捷开始采取的是逐步增加的方式进行,然后让问题出现,然后根据问题引入相应的措施,让团队成员感觉到敏捷的各个实践的真实作用:

1. 像任务分解过于主观,而且不到位,因此对于有些人无法接受,所以引入了任务分解会议和任务分解卡牌;
2. 像团队总体进展无法把握,无法感觉到这个sprint是否能按时完成,所以引入了燃尽图,而且因为我们有些需求会比较紧急要做,所以有时候会在一个sprint中加突发任务(按敏捷的最佳实践来说不能加,但是,我们情况比较特殊),所以我把燃尽图赶紧了下,每次增加任务都会产生一个锯齿,每个锯齿都要记录原因,并且在总结会讨论要如何对影响sprint进度的根源施加影响;
3. 像sprint中,团队成员对于需求和设计都不是很了解,所以之后采取的是设计不在是我一个人来做,也变成一个sprint任务,每个人都可以接手这个任务,从草图到原型图到原型图设计。不过这样又带来问题就是因为不熟悉如何做设计带来的进度变慢,返工变多。


这些都是过程中根据出现的问题想出的解决办法,还有一些问题暂时依旧未解决,而且很让人头疼。

1. 首先就是不信任感的问题:经常有一些工作,因为进度的原因,让他们来做会拖慢进度,所以我经常把这些工作在加班中完成,这样的印象就是我把难的全都做完了,剩下简单的给他们做,这是对他们的不信任,所以现在也尽量把一些设计工作让他们做,但是确实影响到了进度;还有就是有时候他们遇到问题时候会向我寻求帮助,但是我个人的习惯是番茄工作法,所以现在我的番茄钟会经常被打断,最高的时候我一天可以完成19个番茄钟,现在一天只有2-3个番茄钟。导致有时候忙比较重要的事情的时候,我会让他们等一等,这样没有立马得到响应就导致满意度、信任感下降,这个问题我暂时采取的办法就是尽量在允诺的时间范围内去解决他们刚刚提出的问题;
2. 还有就是态度、积极性、责任感的问题。有时候明知道自己的任务没完成,但是却依旧低效率、而且低效率后抵触加班。这个问题我觉得比较严重,技术的问题还都是可以弥补的,但是态度上的就比较麻烦。我现在想到的方法就是向组织寻求帮助,让一些比较有资历来通过威信稍微施加一些强制性的要求;
3. 再还有就是工作认真的问题,我是比较希望团队能做好单元测试、自测、交叉测试、代码走查工作的,但是现在团队貌似很难执行,或许这就是做项目和做产品的区别。这个问题感觉没那么好解决,只能先从自测开始,至少保证自己做的基本功能不会有问题,不要这个功能完全不能用,还让测试告诉你。

上周五也和领导交流了很久,他说的话我表示很赞同。毕竟我才刚工作2年,对于管理这块完全是没有经验的,所以组织上可以允许我犯错,但是犯错后一定要总结,总结后也一定要落地。这是一个摸着石头过河的阶段,一步踏错如果不纠正,就会走向死路。

----分割线----
之后会补一篇博文介绍http模块,那块是比较底层的接口,就像servlet一样,有了一些成熟的框架后不用再那么麻烦的去做项目了,但是还是要理解底层是如何操作的。
# [size=large][b]为什么使用express[/b][/size]
nodeJs的http模块的操作相对来说比较麻烦,因为它其实是底层的接口。就像java的servlet就是底层接口,struts2+spring+hibernate就是通过框架的封装,提高了高层接口。
# [b][size=large]Express的功能[/size][/b]
Express除了为 http 模块提供了更高层的接口外,还实现了许多功能,其中包括:

1. 路由控制;
2. 模板解析支持;
3. 动态视图;
4.用户会话;
5.CSRF 保护;
6.静态文件服务;
7.错误控制器;
8.访问日志;
9.缓存;
10.插件支持。

# [size=large][b]Express不具有的功能[/b][/size]
Express不像ruby的Rails那样,具有模板引擎和ORM的相关功能,express只是对http进行了封装,一定要比较,我觉得他更像java的struts。
# [size=large][b]Express的安装[/b][/size]
全局模式安装:npm install -g express
查看帮助:express --help
```
[David@localhost mircoblog]$ express --help

Usage: express [options] [dir]

Options:

-h, --help output usage information
-V, --version output the version number
-s, --sessions add session support
-e, --ejs add ejs engine support (defaults to jade)
-J, --jshtml add jshtml engine support (defaults to jade)
-H, --hogan add hogan.js engine support
-c, --css <engine> add stylesheet <engine> support (less|stylus) (defaults to plain css)
-f, --force force on non-empty directory
```
# [size=large][b]开始Express[/b][/size]
## [b][size=medium]建立Express项目[/size][/b]
注意,express3.x后的版本,不能使用express –t ejs mircoblog简历ejs的项目了,根据帮助信息可知,要使用express -e mircoblog,操作如下所示:
``` 控制台信息
[David@localhost studyDir]$ express -e mircoblog
create : mircoblog
create : mircoblog/package.json
create : mircoblog/app.js
create : mircoblog/public
create : mircoblog/public/javascripts
create : mircoblog/public/images
create : mircoblog/public/stylesheets
create : mircoblog/public/stylesheets/style.css
create : mircoblog/routes
create : mircoblog/routes/index.js
create : mircoblog/routes/user.js
create : mircoblog/views
create : mircoblog/views/index.ejs

install dependencies:
$ cd mircoblog && npm install
run the app:
$ node app
```
## [size=medium][b]插入依赖并运行[/b][/size]
看提示信息可以知道安装了哪些目录和文件,然后还提示我们去导入依赖,然后运行应用,按照提示继续操作。
```
[David@localhost studyDir]$ cd mircoblog && npm install
```
提示信息比较多,就不列举了。
无参数的 npm install 的功能就是检查当前目录下的 package.json,并自动安装所有dependencies 属性中所指定的依赖。
```
[David@localhost mircoblog]$ node app.js
Express server listening on port 3000
```
##[size=medium][b]成果[/b][/size]
[img]http://user-image.logdown.io/user/3769/blog/3827/post/168553/OsqH8gGbTKKcV5L3Whxz_1.jpg[/img]

# [b][size=large]目录结构[/size][/b]
Express3.0将原来很多默认的设置都通过插件来使用了,所以很多地方需要注意。
比如,要使用partials需要另外插入该插件,操作如下:
```
[David@localhost mircoblog]$ npm install express-partials
npm WARN package.json application-name@0.0.1 No README.md file found!
npm http GET https://registry.npmjs.org/express-partials
npm http 200 https://registry.npmjs.org/express-partials
npm http GET https://registry.npmjs.org/express-partials/-/express-partials-0.1.1.tgz
npm http 200 https://registry.npmjs.org/express-partials/-/express-partials-0.1.1.tgz
express-partials@0.1.1 node_modules/express-partials
```

## [b][size=medium]app.js,工程的入口[/size][/b]
注意,express中需要开启partials。app.use(partials())。
```nodejs app.js
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var partials = require('express-partials');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(partials());
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
```
### app.set
Express 的参数设置工具,接受一个键(key)和一个值(value),可用的参
数如下所示。

1. port :服务的端口。
2. view engine:视图模板引擎。
3. view cache:启用视图缓存。

### app.use
Express 依赖于 connect,提供了大量的中间件,可以通过 app.use 启用。app.configure中启用了4个中间件:methodOverride、router、static 以及 errorHandler。
methodOverride用于支持定制的 HTTP 方法。router 是项目的路由支持。static 提供了静态文件支持。errorHandler 是错误控制器。
### app.get('/', routes.index)
这是一个路由控制器,用户如果访问“ / ”路径,则由 routes.index 来控制。
### routes/index.js
routes/index.js 是路由文件,相当于控制器,用于组织展示的内容:
```nodejs routes/index.js
exports.index = function(req, res){
res.render('index', { title: 'Express' });
};
```
app.js 中通过 app.get('/', routes.index); 将“ / ”路径映射到 exports.index函数下。其中只有一个语句 res.render('index', { title: 'Express' }),功能是调用模板解析引擎,翻译名为 index 的模板,并传入一个对象作为参数,这个对象只一个属性,即 title: 'Express'。
### index.ejs
这部分需要自己修改index.ejs和添加layout.ejs,express3.x默认是不会用这种模式的。
index.ejs 是模板文件,即 routes/index.js 中调用的模板,内容是:
…ejs routes/index.js
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>

它的基础是 HTML 语言,其中包含了形如 <%= title %> 的标签,功能是显示引用的变量,即 res.render 函数第二个参数传入的对象的属性。
### layout.ejs
模板文件不是孤立展示的,默认情况下所有的模板都继承自 layout.ejs,即 <%- body %>部分才是独特的内容,其他部分是共有的,可以看作是页面框架。
这方式就很像java的decorators,也就是装饰模式。
```ejs layout.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<%- body %>
</body>
</html>
```
# [size=large][b]路由控制器[/b][/size]
顾名思义,就像路由器有路由表,可以根据访问的IP地址找到目标主机,当输入路径的时候,就是通过路由控制器来找到实际的处理代码。app.get(‘/’,routes.index)就是一个路由规则。

[img]http://user-image.logdown.io/user/3769/blog/3827/post/168553/BzZmZQwhQBSVbWp4LzXQ_1.jpg[/img]
[align=center]*图7-1 Express创建的网站的架构*[/align]
## [size=medium][b]创建新的路由规则[/b][/size]
在app.js中添加一个新的规则,app.get('/hello', routes.hello);。
index.js改为
```nodejs routes.index.js
exports.index = function(req, res){
res.render('index', { title: 'Express' });
};
exports.hello = function(req, res) {
res.send('The time is ' + new Date().toString()+',My name is David!');
};
```
这时候可以查看结果:

[img]http://user-image.logdown.io/user/3769/blog/3827/post/168553/ohjn8o3TjG2n5h6mSUUS_2.jpg[/img]
[size=medium][b]Rest-ful风格的匹配规则[/b][/size]
app.js中添加
app.get('/user/:username', routes.index);


index.js修改为
```nodejs routes/index.js
exports.index = function(req, res){
res.render('index', { title: 'Express' });
};
exports.hello = function(req, res) {
res.send('The time is ' + new Date().toString()+',My name is David!');
};
exports.user = function(req, res) {
res.send('Hello my old sports , I am Ur ' + req.params.username);
};
```
访问的结果:

[img]http://user-image.logdown.io/user/3769/blog/3827/post/168553/V7o7vvMpQEK4tzG3fw71_3.jpg[/img]
路径规则同样支持 JavaScript 正则表达式,例如 app.get(\/user\/([^\/]+)\/?,callback)。这样的好处在于可以定义更加复杂的路径规则,而不同之处是匹配的参数是匿名的,因此需要通过 req.params[0]、req.params[1] 这样的形式访问。
具体什么是REST-FUL(表现层状态转移)风格,请戳这里。
我们经常用到的是 GET、POST、PUT 和 DELETE 方法。根据 REST 设计模式,这4种方法通常分别用于实现以下功能。

1. GET:获取
2. POST:新增
3. PUT:更新
4. DELETE:删除

| Tables | 请求方式 | 安全 | 幂等 | 绑定函数 |
| ------------- |:-------------:| -----:|:-------------:| -----:|
| col 1 | GET | 是 | 是 | app.get(path,callback)|
| col 2 | POST | 否 | 否 | app.post(path,callback) |
| col 3 | PUT | 否 | 是 | app.put(path,callback) |
| col 3 | DELETE | 否 | 是 | app.delete(path,callback) |
[align=center]*表7-2 REST风格HTTP请求特点*[/align]
注意:
1. 所有方法的绑定函数是app.all(path,callback);
2. 幂等指的是重复请求多次与一次请求的效果是一样;
3. 安全是指没有副作用,即请求不会对资源产生变动,连续访问多次所获得的结果不受访问者的影响。

## [size=medium][b]多路由规则[/b][/size]
当同一个地址有多个路由规则的时候,会相应最先配置的路由规则。例如,修改app.js为
```nodejs app.js片段
app.get('/', routes.index);
app.get('/hello', routes.hello);
app.all('/user/:username', function(req, res) {
res.send('all methods captured');
});
app.get('/user/:username',routes.user);
```
结果为:
[img]http://user-image.logdown.io/user/3769/blog/3827/post/168553/ek3NzgCKS72zGUs4dIJ4_4.jpg[/img]

根据结果可知,后面的路由规则没有被调用。那如何让两个路由规则都被调用呢?
要实现这功能,就必须在response关闭前,调用next(),注意,在3.x中需要在回调函数的参数列表中列出next来,如下为app.js片段:
```nodejs app.js片段

app.get('/', routes.index);
app.get('/hello', routes.hello);
app.all('/user/:username', function(req, res,next) {
console.log('all methods captured');
next();
});
app.get('/user/:username',routes.user);
```
直接看结果吧:
[img]http://user-image.logdown.io/user/3769/blog/3827/post/168553/BWw55okARn6fKmss2SVk_5.jpg[/img]

又可以输出get方式的输出了。

同时控制台也打印出了all方式的打印信息。

这种方式经常可以用在输入信息的验证,比如先验证表单的有效性,不合法则直接关闭response并提示,否则next。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值