Express.js 应用-路由与路由中间件

 2016年03月10日    1126     声明


在定义HTTP请求的监听处理函数或请求处理中间件时,针对每个请求我们需要调用相应的代码块。根据用户请求路径和请求方式的不同,需要触发不同的服务器形为,如:GET请求和POST请求应该区别处理、不同的URL也应该有不同的响应。 在Express应用中,通过路由实现不同请求路径和请求方式的触发不同的服务器响应。


  1. Express中的路由
  2. 路由处理
  3. 路由中间件

1. Express中的路由

Express 应用中,在app.js中引入路由处理:

app.use('/', routes);  // 主页
app.use('/users', users);	// 用户

在上面示例中,引入了两个路由处理文件。分别用于处理主页显示,和显示用户列表。两个路路文件代码分别如下。

主页文件routes/index.js

/* GET 请求主页 */
router.get('/', function(req, res) {
  res.render('index', { title: 'Express' });
});

GET访问/路径时,则调用routes/index.js中的方法处理。

用户相关处理文件routes/users.js

/* GET 请求用户列表 */
router.get('/', function(req, res) {
  res.send('响应请求资源');
});

GET访问/users路径时,高调用routes/users.js中的方法处理。


2. 路由处理

在实际应用中,我们需要对应用功能进行扩展。如,在用户模块中,可能会需要以下功能:

  • GET请求/users,返回用户列表
  • GET请求/users/:username,返回指定用户的用户信息
  • POST请求/users,创建新用户
  • PUT请求/users/:username,按用户名更新用户信息

实现这些功能,要将routes/users.js文件修改如下:

/* GET 请求,查询用户列表 */
router.get('/', function(req, res) {
  /* 查询用户列表的操作 */
  res.send('响应查询的用户列表');
});

/* GET 请求,按用户名获取用户信息 */
router.get('/:username', function(req, res) {
  /* 查询用户信息处理 */
  res.send('响应指定用户名的用户信息');
});

/* POST 请求,创建用户信息 */
router.post('/', function(req, res) {
  /* 创建用户的操作 */
  res.send('响应创建用户的结果');
});

/* PUT 请求,按用户名更新用户信息 */
router.put('/:username', function(req, res) {
  /* 更新用户信息处理 */
  res.send('响应更新用户信息的操作结果');
});

app.js中,通过app.use('/users', users)设置的模块路径,所以模块中的路相当于:/users+下级路径,如,更新用户信息的路径/:username的实际路径是/users/:username


3. 路由中间件

在上一篇Express的介绍(Express.js 应用-中间件的使用)中,通过在app.js添加中间件实现了一些如:数据解析、通用处理等操作。在路由中同样可以添加中件间,与app.js中添加的中间件不同,路由中添加的中间是针对一个或一类请求的处理。

3.1 添加通用中间件

对所有用户模块中的所有类型的请求添加一个检查用户是否登录的中间件:

/* 所有请求,检查用户是否登录中间件 */
router.all('/*', _checkUserLogin, function(req, res) {
  // 可以访问上一个中间件中添加的信息
  console.log(res.locals.user);
  next();
});

function _checkUserLogin(req, res, next) {
  /* 用户登录的检查 */
  if(/* 用户已登录 */) {
    // 将已登录的用户添加至res.locals中,这样可能
  	res.locals.user = user;
  }
  // 通过next回调进入下一步处理
  next();
}


3.2 添加单个中间件

也可以对某一个路由添加单独的中间件,在用户信息前,一般需要首先检查用户是否存在:

/* PUT 请求,按用户名更新用户信息 */
router.put('/:username', _checkUser, function(req, res, next) {
  /* 更新用户信息处理 */
  if(res.locals.user) {
  	/* 更新用户信息 */
  } else {
  	/* 用户不存在时 */
  	// 可以通过next,传递404状态
  	next(404);
  	// 或直接提示用户不存在
  	res.send('修改用户不存在');
  }
});

function _checkUser(req, res, next) {
  /* 检查用户是否存在 */
  if(/* 如查用户存在 */) {
  	res.locals.user = user;
  }
  next()
}


3.3 中间件的组合

中间件可以不止一个,当某一个或一类操作需要多种中间处理时,这时可以添加一组中间件。添加多个中间件是,可以依次添加或是以数组的形式添加:

/* PUT 请求,按用户名更新用户信息 */
// 依次添加处理中间件
// router.put('/:username', _checkUser, _checkUsername, function(req, res, next) {
// 以数组的形式添加处理中间件
router.put('/:username', [_checkUser, _checkUsername], function(req, res, next) {
  /* 更新用户信息处理 */
  if(res.locals.user) {
  	/* 更新用户信息 */
  	if(req.username){
      /* 更新用户名可用时的处理 */
  	} else {
  	  /* 更新用户名不可用时的处理 */
  	}
  } else {
  	/* 用户不存在时的处理 */
  }
});

// 检查用户是否存在
function _checkUser(req, res, next) {
  /* 检查用户是否存在 */
  if(/* 如查用户存在 */) {
  	res.locals.user = user;
  }
  next()
}

// 检查所更新的用户名是否可用
function _checkUsername(req, res, next) {
  var username = req.body.username;
  /* 检查用户名是否可用 */

  if(true){
  	// 除可以用res传递数据外,req同样也可以用于传递数据
  	req.username = true;
  }
  next()
}