Pinvon's Blog

所见, 所闻, 所思, 所想

项目记录

生成Express项目

Node.js的安装在此跳过. 本项目在Node.js的基础上开始.

# 安装express
npm install express-generator -g

# 查看express命令选项
express -h

# 创建项目
express --view=hbs healthy

# 安装依赖
cd myapp
npm install

# 运行
npm start
# 或者
DEBUG=healthy:* npm start  # Linux, MacOS
set DEBUG=healthy:* & npm start  # Windows

此时可在浏览器中输入 http://localhost:3000 访问该应用.

目录结构

/bin: 用于应用的启动. /public: 放置静态资源. /routes: 放置路由. /views: 放置模板文件(html). app.js: 程序的入口文件

模板引擎

本项目使用 handlebars 模板引擎, 该模板引擎默认使用的模板文件的后缀名是 hbs, 因此 views子目录 中的文件全是 hbs 结尾的. 这边我们进行修改, 使模板引擎使用后缀名为 html 的文件作为模板文件.

修改根目录下的 app.js 文件, 加入以下几句话:

// 在开头添加如下代码
var hbs = require('hbs');

// 将 app.set('view engine', 'hbs'); 改成如下代码
app.set('view engine', 'html');

// 紧接上面一句, 添加如下代码
app.engine('html', hbs.__express);

并将 views 目录下的文件后缀名直接改成 html.

MySQL

安装MySQL

以下通过一个简单的例子来说明如何将Express与MySQL整合起来.

创建表

创建一个简单的表, 表结构如下: 0.png

MySQL模块

package.jsondependencies 中新增以下配置:

"mysql":"latest"

执行 npm install.

目录结构

根据需要的功能, 在根目录再新建三个目录, 分别管理.

mkdir util  # 工具
mkdir conf  # 配置
mkdir dao  # 与数据库交互(Data Access Object)

conf目录

新建配置文件, 编定MySQL数据库连接配置. emacs conf/db.js:

// MySQL数据库联接配置
module.exports = {
    mysql: {
        host: '127.0.0.1', 
        user: 'root',
        password: '123456',
        database:'healthy', // 前面建的user表位于这个数据库中
        port: 3306
    }
};

dao目录

该目录下需要新建两个文件. 第一个(userSqlMapping.js)的内容是对数据库中某个表进行操作的SQL语句. 第二个(userDao.js)的内容是获取前端传过来的数据, 通过SQL语句存到MySQL中.

emacs dao/userSqlMapping.js:

// CRUD SQL语句
var user = {
    insert:'INSERT INTO user(id, name, age) VALUES(0,?,?)',
    update:'update user set name=?, age=? where id=?',
    delete: 'delete from user where id=?',
    queryById: 'select * from user where id=?',
    queryAll: 'select * from user'
};

module.exports = user;

emacs dao/userDao.js:

// 实现与MySQL交互
var mysql = require('mysql');
var $conf = require('../conf/db');
var $util = require('../util/util');
var $sql = require('./userSqlMapping');

// 使用连接池,提升性能
var pool  = mysql.createPool($util.extend({}, $conf.mysql));

// 向前台返回JSON方法的简单封装
var jsonWrite = function (res, ret) {
    if(typeof ret === 'undefined') {
        res.json({
            code:'1',
            msg: '操作失败'
        });
    } else {
        res.json(ret);
    }
};

module.exports = {
    add: function (req, res, next) {
        pool.getConnection(function(err, connection) {
            // 获取前台页面传过来的参数
            var param = req.query || req.params;

            // 建立连接,向表中插入值
            // 'INSERT INTO user(id, name, age) VALUES(0,?,?)',
            connection.query($sql.insert, [param.name, param.age], function(err, result) {
                if(result) {
                    result = {
                        code: 200,
                        msg:'增加成功'
                    };    
                }

                // 以json形式,把操作结果返回给前台页面
                jsonWrite(res, result);

                // 释放连接 
                connection.release();
            });
        });
    }
};

util目录

emacs util/util.js:

// 提升性能
module.exports = {
  extend: function(target, source, flag) {
    for(var key in source) {
      if(source.hasOwnProperty(key)){
        flag ? (target[key] = source[key]) : (target[key] === void 0 && (target[key] = source[key]));
      }
    }
    return target;
  }
};

添加路由

emacs routes/users.js:

// 在文件开头添加以下代码
var userDao = require('../dao/userDao');

// 添加以下路由
// 增加用户
router.get('/addUser', function(req, res, next) {
    userDao.add(req, res, next);
});

测试

为了方便, 前面实现的是get请求的add方法, 所以可以直接在浏览器中使用地址添加数据到数据库. http://localhost:3000/users/addUser?name=xyz&age=18

根据返回的内容, 判断是否成功. 如果成功, 在数据库中应该可以看到添加了一条新数据.

1.png

2.png

代码组织

路由都写在 routes 目录下, 然后通过 module.exports = router 将里面的处理方法导出.

在入口文件 app.js 中, 使用 var users = require('./routes/users') 这种语句, 将处理方法赋给 app.js 中的变量, 再使用 app.use('/path', middle) 将路径与处理方法绑定.

以后, 一级路径(如'/users'), 就在 app.js 中与相应的模块进行绑定, 而二级或者更高级的路径(如'/users/pinvon'), 就在路由 routes/users.js 中, 将具体的路径与相应的中间件进行绑定.

关于数据库, 对于数据库中的每一个表, 有一个相应的文件(如'dao/userSqlMapping.js')来编写所需要用到的SQL语句, 然后再有一个相应的文件(如'dao/userDao.js')来作为数据库和前端的中间处理程序. 即, 一个表会有两个对应的文件, 来实现对数据库的操作.

前后端数据传递

后端:

result = {
    code: 200,
    msg:'增加成功'
};
res.json(result);

前端:

success: function (data, status) {
                    if (status == 'success') {
                        console.log(data);
                        layer.msg('注册成功');
                        setTimeout(function () {
                            location.href = 'login';
                        }, 2000);
                    }
                },
error: function (data, err) {
                    console.log(data);
                    alert('fail');
                }

打印结果如下图所示: 3.png

可以根据 code 的值, 来判断下一步该怎么处理.

问题记录

  1. 注册时使用post方法提交数据, 在后台进入post对应的中间件处理, 将数据存储到数据库, 存储完成后回到post方法继续执行, 会进入到get方法, 而代码中没在post方法里面写明会渲染或重定向到get. 目前的方案是在get()中判断参数, 如果路径中带参数, 则不让渲染注册页面.
  2. Node.js的线程: 如果函数有回调函数, 该函数的返回值依赖于回调函数, 则函数的返回值一般不是我所预期的, 因为函数会先返回, 然后再去执行回调函数.

Comments

使用 Disqus 评论
comments powered by Disqus