简单学了下nodejs web开发框架express,以及一些相关的技术…
关于express的部分主要参考:Node.js开发框架Express4.x、Node.js + Express 构建网站简单示例
需要注意的是,express 4.x 构建器独立成了一个模块,如果要使用系统中的express命令,就必须安装独立的generator:
npm install -g express express-generator bower supervisor
express -e bower-express
使用-g(global)安装后默认安装到用户目录下,需要添加环境变量才能被应用识别:
export NODE_PATH=$HOME/AppData/Roaming/npm/node_modules
supervisor 是个好东西,代码变更可以热加载,自动重启:supervisor app.js
(一).首先来看主文件,app.js:
var express = require('express'), ejs = require('ejs'), routes = require('./routes/index'), users = require('./routes/users'), session = require('express-session'), RDBStore = require('express-mysql-session');
var app = express();
// 定义视图路径及修改ejs模板后缀名
app.set('views', 'views');
app.engine('.html', ejs.__express);
app.set('view engine', 'html');
app.use(require('body-parser').urlencoded({ extended: false }));
// 定义静态文件路径
app.use(express.static('public'));
app.use(express.static('bower_components'));
// session保存
const options = {
host : '1.1.1.1',
user : 'test',
port : 5029,
password : 'test',
database : 'test'
};
app.use(session({
secret : 'test',
store : new RDBStore(options),
cookie : { maxAge: 10000 },
resave : true,
saveUninitialized : true
}));
// URL路由
app.get('/', routes.index).post('/', routes.index);
// 显示404错误及输出
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// 生产环境异常打印
if (app.get('env') === 'development')
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
// 启动及端口
//require('http').createServer(app).listen(3000);
app.listen(3000, function() {
console.log('Express server listening on 3000');
});
由于没装No-SQL数据库,因此就用mysql来缓存session,
进入express生成的项目后使用npm安装即可:npm install express-mysql-session
用法很简单,启动项目后会在目标库自动新建一张innodb表,可以将其改为memory引擎:
ALTER TABLE sessions MODIFY data VARCHAR(5000),ENGINE=MEMORY;
当然,使用mongos或者rethinkdb会更方便,问题是node模块太多了有点眼花缭乱不知道用哪个好(bug少)……譬如:
npm install express-session-rethinkdb connect-rethinkdb session-rethinkdb
(二).好吧,接下来看“action”,routes/index.js:
var router = require('express').Router(), mysql = require('mysql');
const options = [{ host : '1.1.1.1', user : 'test', port : 5029, password : 'test', database : 'test', dateStrings : true }, {
{ host : '1.1.1.2', user : 'test', port : 3306, password : 'test', database : 'test', dateStrings : true }, {
{ host : '1.1.1.3', user : 'test', port : 3307, password : 'test', database : 'test', dateStrings : true//, multipleStatements : true
}];
module.exports.index = function(req, res) {
var connection, sql;
if (req.method == 'POST' && req.body && req.body.host && /^[1-3]$/.test(req.body.host) && req.body.title && req.body.sql) {
//var pool = mysql.createPool(options[2]);
connection = mysql.createConnection(options[req.body.host - 1]);
sql = req.body.sql;
} else {
res.render('index', {
'params' : { title : '', sql : '', host : ''}, 'x' : '[]', 'y' : '[]'
});
return;
}
connection.query(sql, function(err, rows, fields) {
if (err) throw err;
var x = [], y = [];
for (var i in rows) {
//if (rows[i].x instanceof Date) x[i] = require('moment')(rows[i].x).format('YYYY-MM-DD');
x[i] = rows[i].x;
y[i] = rows[i].y;
}
res.json({ 'x' : x, 'y' : y });
});
connection.end();
};
代码很简单,GET请求直接返回页面(当然也可以处理queryString),POST请求返回JSON数据。
一开始不知道node-mysql有个 dateStrings的参数,所以用 moment.js来转换日期格式,也很方便。
在开发页面前先使用 bower下载好所需的jQuery、Bootstrap、ACE、ECharts等库:
bower install ace echarts bootstrap jquery
(三).最后来上展示页面,views/index.html:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title><%-params.title%></title>
<link rel="stylesheet" href="bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
<div id="editor" style="height:60px;font-size:16px"><%-params.sql%></div>
<form style="width:60%;height:90px;padding:10px 40px">
<div class="form-group col-xs-4" style="padding-left:0px">
<select class="form-control" name="host">
<option value="">Select Host</option>
<option value="1">1.1.1.1:5029</option>
<option value="2">1.1.1.2:3306</option>
<option value="3">1.1.1.3:3306</option>
</select>
</div>
<div class="form-group col-xs-4" style="padding-left:0px">
<input type="text" name="title" class="form-control" placeholder="title" value="<%-params.title%>" />
</div>
<button type="button" onclick="query()" class="btn btn-primary">Query</button>
</form>
<hr />
<div id="main" style="height:400px"></div>
<script src="echarts/build/dist/echarts.js"></script>
<script type="text/javascript" src="jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="javascripts/ace/src-min-noconflict/ace.js"></script>
<script type="text/javascript">
// js在下面 ↓↓↓↓↓
</script>
</body>
以上的JS代码如下:
$('select').val(<%-params.host%>);
var editor = ace.edit('editor'), myChart, options = {
tooltip: { show: true },
legend: { data : ['<%-params.title%>'] },
xAxis : [{ type : 'category', data : <%-x%> }],
yAxis : [{ type : 'value' }],
series : [{ 'name' : '<%-params.title%>', 'type' : 'bar', 'data' : <%-y%> }]
};
editor.setTheme('ace/theme/sql');
editor.getSession().setUseWrapMode(true);
editor.getSession().setMode('ace/mode/sql');
// 路径配置
require.config({ paths: { echarts: 'echarts/build/dist' } });
// 使用
require(
[ 'echarts', 'echarts/chart/bar' ],
function (ec) {
myChart = ec.init($('#main').get(0));
myChart.setOption(options);
}
);
function query() {
myChart.showLoading();
$.ajax({
url : window.location.pathname,
cache : false,
type : 'POST',
dataType : 'json',
data : $('form').serialize() + '&sql=' + editor.getValue(),
success : function(obj) {
var title = $(':text').val();
options.legend.data[0] = title;
options.xAxis[0].data = obj.x;
options.series[0].data = obj.y;
options.series[0].name = title;
myChart.clear();
myChart.hideLoading();
myChart.setOption(options);
}
});
}
注意:
- echarts的 setOption 方法是更新操作,因此要先clear图表后重新绘图;
- ACE是一个源码编辑器,同大名鼎鼎的 CodeMirror 类似,API也是大同小异;
- 如果bower 下载的ACE没有编译,前往 ace-builds 页面下载。
至此,一个简单的web应用就诞生了,就像 ChartSQL做的那样,可以再完善ajax异常处理、node-mysql的连接池等。
好久没碰过前端相关的技术,写起来各种生疏,代码拙劣、欢迎指教。最后来一张效果图:
(其他):
关于http代理设置,NPM如下:
npm config set proxy=http://127.0.0.1:8080
bower需要在用户目录下新建文件:.bowerrc
{
"proxy": "http://127.0.0.1:8080",
"https-proxy": "http://127.0.0.1:8080",
"strict-ssl": false
}