25-基于NodeJS打造Web架构中间层¶
统计信息:字数 5633 阅读12分钟
中间层与中间件¶
这两个概念完全不一样
中间层¶
在传统的BS架构中(vrowser+server),中间增加一个层(Middle),来处理信息传递转发(类似于传纸条的例子)。官方解释:Middle Tier 应用程序服务器层或者应用服务层,是用户接口或者Web客户端与数据库之间的逻辑层。
传统的架构是:BS,浏览器和服务器直接通信。加入中间层后,是BMS架构,浏览器和服务器的请求需要经过中间层。
中间件¶
中间层是一个web框架的逻辑层,中间件是一个函数或者插件(业务用途)。官方解释:MiddleWare 是一个对用户请求进行过滤和预处理的函数,一般不会对客户端进行相应,而是把处理后的结果传递下去。
Express是一个自身功能极简,完全由路由和中间件构成的一个web开发框架。express应用就是在调用各种中间件。express = 自身功能极简+路由+中间件。中间件类似于插件,可以扩展功能,是实现某种功能的函数。封装了一些复杂但是通用的功能,可以通过npm-yarn进行安装。
中间层的意义¶
1、大前端:传统的后端提供不同接口,现在后端提供不同服务(商品网站,提供商品服务,购物车服务,支付服务,仓储服务),此时需要中间层将不同的服务转换成前端使用的接口(后端专注于服务器数据库)。Docker 出现使得后端各种服务分离。所以前端变成了大前端。
2、安全方面:避免了服务器直接暴露在用户前(用户不知道真实的IP)在中间层中使用 pm2 + nginx 反向代理进程守护,基本安全。
3、性能问题:传统的单页应用中全部需要在初始化阶段请求JS,网络问题可能造成延迟,加入中间层后,中间层和后端在同一个服务器运行,请求速度加快,避免了首屏白屏和闪动。
4、开发效率问题:中间层可以使用NodeJS或者PHP等实现。如果使用NodeJS实现中间层,那么和前端的很多方法可以共用(避免进行两次表单验证)。NodeJS使用单进程单线程,可以使用其他异步技术模拟多线程提高开发效率问题。
中间层的实现¶
例子使用 Koa 框架
yarn init -y
yarn add -D koa koa-router koa-body-parserer koa-ejs
nodemon app.js
模拟一个登陆界面,后端使用PHP实现
<?php
require_once 'inc/conn.php';
$db = new DB();
$status = array();
if (empty($_POST['username'])) {
$status['code'] = 3;
echo json_encode($status);
exit;
}
$username = $_POST['username'];
$password = md5($_POST['password']);
$sql = "SELECT user, password FROM admin WHERE user = '$username' AND password = '$password'";
$db->query($sql);
$conn = $db->conn();
if ($conn->affected_rows >= 1) {
$status['code'] = 1;
} else {
$status['code'] = 0;
}
echo json_encode($status);
$db->close();
?>
app.js 中间层
const Koa = require('koa');
const path = require('path');
const Router = require('koa-router');
const ejs = require('koa-ejs');
const body = require('koa-bodyparserer');
// 路由+模板引擎+解析数据
// 处理静态资源
const static = require('koa-static');
const app = new Koa();
ejs(app, {
root: path.resolve(__dirname, 'template'),
layout: false,
viewExt: 'ejs',
cache: false,
debug: false
});
const router = new Router();
app.use(body());
router.get("/", ctx => {
ctx.body = 'main page';
});
router.use('/admin', require('./router/admin'));
app.use(static('./static'));
app.use(router.routes());
app.listen(3000);
Admin.js
const Router = require('koa-router');
const router = new Router();
router.get('/', async ctx => {
await ctx.render('admin/admin');
});
router.post('/login', ctx => {
const { username, password } = ctx.request.body;
// 中间件中,通过axios把数据发给后端服务器
const { data } = await axios({
url: 'http://localhost/login/check.php',
method: 'post',
data: {
username,
password
},
// 需要把JSON转换成查询字符串(a=1&b=2)
transformRequest: [
data => {
return querystring.stringify(data)
}
],
});
if (data.code !== 1) {
return ctx.body = {
code: 401,
message: 'not allowed'
}
}
ctx.body = {
code: 200,
message: 'check success'
};
});
module.exports = router.routes();
admin.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./js/jquery.min.js"></script>
</head>
<body>
<p>
用户名:<input type="text"/>
</p>
<p>
密码:<input type="password" name="password"/>
</p>
<button type="submit">提交</button>
<script>
$(function() {
$('button').click(function() {
var username = $(':text').val();
var password = $('password').val();
$.ajax({
url: '/admin/login',
method: 'post',
data: {
username,
password
},
success(data) {
console.log(data);
}
});
});
});
</script>
</body>
</html>
现在 dtable-server 就相当于中间件,基于express框架,把这部分的代码写三次。
Query.js
const querystring = require('querystring');
const str = 'username=admin&password=123456';
const obj = {
'username': 'admin',
'password': '123456';
}
console.log(quertstring.parse(str));
console.log(querystring.stringify(obj));