Express中的middleware是极其强大的工具。有时候不经意间都是在使用中间件,就像呼吸一样的轻松自然。
下面列举几种常见的使用中间件场景:
身份验证:
我们往往会在程序中使用身份验证,确定用户是否登录,获取账号名和密码等等。这是一个业务逻辑而非组件,但是很常用,有必要把它和一般的业务员逻辑抽离开来。要实现功能很简单,例如:
router.use(function(req, res, next){
var authService = require(APP_APTH + '/services/auth');
authService.hasLogin(req, res, next)
.then(authHandler);
function authHandler(isLogin){
if(isLogin === true){
next();
}else{
res.redirect('/login');
}
}
})
上面的代码已经足够简单地达到目的了。但是对于一个复杂的业务系统,存在大量的router情况下,这必然不是一个很好的选择,因为不是所有的请求都需要身份验证,不同模块往往需要独立的验证。这样一来,我们可能需要不断地copy上面的代码,对于懒惰的程序员而言,这不是什么好事。
于是我们需要封装身份验证,但是总不能把它作为一个组件或者服务来封装吧。middleware恰好方便解决了这个问题。上面的代码只需要稍微修改一下即可:
function authMiddleware(){
return authentication;
}
function authentication(req, res, next){
var authService = req.getService('auth');
authService.hasLogin(req, res, next)
.then(authHandler);
function authHandler(isLogin){
if(isLogin === true){
next();
}else{
res.redirect('/login');
}
}
}
module.exports = authMiddleware;
使用方式如下:
var authMiddleware = require(APP_PATH + '/middleware/auth');
router.use(authMiddleware);
//对于单独的请求
router.get('/admin', authMiddleware, adminController);
表单验证
一个严谨的程序需要对客户端传来的数据做验证,否则很容易出现大问题。
很多人把表单数据验证放到controller里面,例如:
var reqData = req.getData();
var userData = {};
if(reqData.userName){
userData.userName = reqData.userName;
}
if(reqData.password){
userData.password = reqData.password;
}
......
一个更好的方式是增加validate中间件,修改后代码更加优雅:
router.post('/auth',
validate({
oldPassword: {
required: true
},
newPassword: {
required: true
}
}),
function(){
....
}
);
中间件这种思维在很多框架设计中都会体现,例如PHP的明星框架laravel就可以通过中间件帮助处理业务逻辑。我觉得中间件只是业务的一种包装方式,未必会让执行效率更高,但是一定可以让代码变得更加容易维护。