初识NodeJS服务端开发入门(Express+MySQL)


Posted in NodeJs onApril 07, 2017

NodeJS对前端来说无疑具有里程碑意义,在其越来越流行的今天,掌握NodeJS已经不再是加分项,而是前端攻城师们必须要掌握的技能。本文将与同志们一起完成一个基于Express+MySQL的入门级服务端应用,即可以对数据库中的一张表进行简单的CRUD操作。但本人还是斗胆认为,通过这个应用,可以让没怎么接触后端开发的同志对使用Node进行后端开发有一个大致了解。

Express工程环境准备

1. 安装express,和express项目种子生成器(什么?你问第1步为什么不是安装NodeJS,我也只能呵呵..)

安装express

npm install express -g

安装express

npm install express-generator -g

2. 创建工程。进入工程目录,运行命令

express projectName

expresst项目种子生成器会帮我们生成express相应的工程结构,如下

初识NodeJS服务端开发入门(Express+MySQL)

/bin: 用于应用启动

/public: 静态资源目录

/routes:可以认为是controller(控制器)目录

/views: jade模板目录,可以认为是view(视图)目录

app.js 程序main文件

3. 进入工程,安装依赖,然后启动应用在工程根目录,使用npm install安装依赖,使用npm start启动应用。完成后,你在命令行工具里会看出如下界面,在浏览器中访问会得到我们应用的默认页面

初识NodeJS服务端开发入门(Express+MySQL)

初识NodeJS服务端开发入门(Express+MySQL)

MySQL环境准备

1. 当然,首先你要准备好MySQL环境。可以参看https://3water.com/article/39188.htm进行安装,同时也建议安装一个数据库管理工具,如navicat for mysql,方便操作

2. 创建表MySQL安装好了后,进入到数据库,创建要用到的表(如user), 结构如下

初识NodeJS服务端开发入门(Express+MySQL)

3. 安装Node的MySQL驱动(请允许装X一下…)在package.json的dependencies中新增, “mysql” : “latest”, 并执行npm install安装依赖

编写相关代码,整合Express+MySQL

1. 首先,我们先建几个目录,简单分下层(看出我还是很用心木有?)

在工程根目录新增三个目录:

util ? 工具方法

conf ? 配置

dao ? 与数据库交互

完成后的工程结构

初识NodeJS服务端开发入门(Express+MySQL)

2.在conf目录中,编写mySQL数据库连接配置

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

2. 编写CRUD SQL语句

// 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;

3. 增加路由及实现数据库的CRUD

以C(新增)的具体实现举例,在/routes/users.js 中增加一个路由

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

在userDao中实现add方法

// dao/userDao.js
// 实现与MySQL交互
var mysql = require('mysql');
var $conf = require('../conf/conf');
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();
			});
		});
	}
};

4. 测试整合是否成功

因为前面实现的是一个get请求的add方法, 所以可以在浏览器中直接使用地址访问,进入路由, http://localhost:3000/users/addUser?name=xyz&age=18.如果你得到如下JSON返回或看到数据表中有上面的数据插入,表示整合成功了

初识NodeJS服务端开发入门(Express+MySQL)

初识NodeJS服务端开发入门(Express+MySQL)

5. 同理,实现CRUD其它的方法,最终完整的的routes/user.js为:

var express = require('express');
var router = express.Router();

var userDao = require('../dao/userDao');

/* GET users listing. */
router.get('/', function(req, res, next) {
 res.send('respond with a resource');
});

// 增加用户
//TODO 同时支持get,post
router.get('/addUser', function(req, res, next) {
	userDao.add(req, res, next);
});

router.get('/queryAll', function(req, res, next) {
	userDao.queryAll(req, res, next);
});

router.get('/query', function(req, res, next) {
	userDao.queryById(req, res, next);
});

router.get('/deleteUser', function(req, res, next) {
	userDao.delete(req, res, next);
});

router.post('/updateUser', function(req, res, next) {
	userDao.update(req, res, next);
});

module.exports = router;

完整的userDao.js为

// 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();
			});
		});
	},
	delete: function (req, res, next) {
		// delete by Id
		pool.getConnection(function(err, connection) {
			var id = +req.query.id;
			connection.query($sql.delete, id, function(err, result) {
				if(result.affectedRows > 0) {
					result = {
						code: 200,
						msg:'删除成功'
					};
				} else {
					result = void 0;
				}
				jsonWrite(res, result);
				connection.release();
			});
		});
	},
	update: function (req, res, next) {
		// update by id
		// 为了简单,要求同时传name和age两个参数
		var param = req.body;
		if(param.name == null || param.age == null || param.id == null) {
			jsonWrite(res, undefined);
			return;
		}

		pool.getConnection(function(err, connection) {
			connection.query($sql.update, [param.name, param.age, +param.id], function(err, result) {
				// 使用页面进行跳转提示
				if(result.affectedRows > 0) {
					res.render('suc', {
						result: result
					}); // 第二个参数可以直接在jade中使用
				} else {
					res.render('fail', {
						result: result
					});
				}

				connection.release();
			});
		});

	},
	queryById: function (req, res, next) {
		var id = +req.query.id; // 为了拼凑正确的sql语句,这里要转下整数
		pool.getConnection(function(err, connection) {
			connection.query($sql.queryById, id, function(err, result) {
				jsonWrite(res, result);
				connection.release();

			});
		});
	},
	queryAll: function (req, res, next) {
		pool.getConnection(function(err, connection) {
			connection.query($sql.queryAll, function(err, result) {
				jsonWrite(res, result);
				connection.release();
			});
		});
	}

};

除了update测试外,其它get请求都可以直接在浏览器中使用地址+参数完成测试。为了模拟post请求,同时简单使用下jade模板(Express支持的一种模板引擎),我们在/views目录新建三个jade文件

updateUser.jade

extends layout
block content
	h1 更新用户资料
	form(method='post', action='/p/users/updateUser')
		div.form-row
			label
				span ID:
				input(type='text',name='id')
		div.form-row
			label
				span name:
				input(type='text',name='name')
		div.form-row
			label
				span age:
				input(type='text',name='age')
		div.form-row
			input(type='submit')

suc.jade

block content
 h1 操作成功!
 pre #{JSON.stringify(result)}

fail.jade

block content
 h1 操作失败!
 pre #{JSON.stringify(result)}

以下是更新测试结果

初识NodeJS服务端开发入门(Express+MySQL)

最后,如果你使用的是idea或webStrom这样的IDE,你就不需要安装express和express项目种子生成器了。这两个IDE是可以直接创建NodeJS项目

初识NodeJS服务端开发入门(Express+MySQL)

初识NodeJS服务端开发入门(Express+MySQL)

初识NodeJS服务端开发入门(Express+MySQL)

初识NodeJS服务端开发入门(Express+MySQL)

小结:

一个Express的helloWorld就差不多完成了, 可以通过这个链接下载此例子源代码http://pan.baidu.com/s/1jGvd4Bc。更多Express的功能(如日志,自动化测试等),等待大家去解锁,愿玩得愉快!

NodeJs 相关文章推荐
nodejs批量修改文件编码格式
Jan 22 NodeJs
Windows 系统下设置Nodejs NPM全局路径
Apr 26 NodeJs
用nodejs搭建websocket服务器
Jan 23 NodeJs
nodejs+express实现文件上传下载管理网站
Mar 15 NodeJs
NodeJS学习笔记之Module的简介
Mar 24 NodeJs
浅析 NodeJs 的几种文件路径
Jun 07 NodeJs
nodejs实现大文件(在线视频)的读取
Oct 16 NodeJs
NodeJs 模仿SIP话机注册的方法
Jun 21 NodeJs
使用nodejs实现JSON文件自动转Excel的工具(推荐)
Jun 24 NodeJs
如何利用nodejs实现命令行游戏
Nov 24 NodeJs
一文秒懂nodejs中的异步编程
Jan 28 NodeJs
Nodejs 数组的队列以及forEach的应用详解
Feb 25 NodeJs
nodejs服务搭建教程 nodejs访问本地站点文件
Apr 07 #NodeJs
nodejs爬虫遇到的乱码问题汇总
Apr 07 #NodeJs
详解nodejs爬虫程序解决gbk等中文编码问题
Apr 06 #NodeJs
NodeJS基础API搭建服务器详细过程记录
Apr 01 #NodeJs
Ajax异步文件上传与NodeJS express服务端处理
Apr 01 #NodeJs
3分钟快速搭建nodejs本地服务器方法运行测试html/js
Apr 01 #NodeJs
nodejs使用express创建一个简单web应用
Mar 31 #NodeJs
You might like
php模拟socket一次连接,多次发送数据的实现代码
2011/07/26 PHP
linux下使用ThinkPHP需要注意大小写导致的问题
2011/08/02 PHP
比较详细PHP生成静态页面教程
2012/01/10 PHP
php读取txt文件组成SQL并插入数据库的代码(原创自Zjmainstay)
2012/07/31 PHP
destoon切换城市后实现logo旁边显示地区名称的方法
2014/08/21 PHP
PHP快速生成各种信息提示框的方法
2016/02/03 PHP
PHP的垃圾回收机制代码实例讲解
2021/02/27 PHP
javascript Excel操作知识点
2009/04/24 Javascript
Mootools 1.2教程(2) DOM选择器
2009/09/14 Javascript
javascript转换字符串为dom对象(字符串动态创建dom)
2010/05/10 Javascript
JS模拟酷狗音乐播放器收缩折叠关闭效果代码
2015/10/29 Javascript
JavaScript实现简洁的俄罗斯方块完整实例
2016/03/01 Javascript
动态加载js、css的实例代码
2016/05/26 Javascript
省市联动效果的简单实现代码(推荐)
2016/06/06 Javascript
实例讲解JavaScript中call、apply、bind方法的异同
2016/09/13 Javascript
JavaScript数据结构之二叉树的查找算法示例
2017/04/13 Javascript
JS按条件 serialize() 对应标签的使用方法
2017/07/24 Javascript
angular1.x ui-route传参的三种写法小结
2018/08/31 Javascript
Element 默认勾选表格 toggleRowSelection的实现
2019/09/04 Javascript
js面向对象之实现淘宝放大镜
2020/01/15 Javascript
JavaScript实现简单计算器
2020/03/19 Javascript
原生js实现照片墙效果
2020/10/13 Javascript
[32:56]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第二场 12.11
2020/12/16 DOTA
浅谈对yield的初步理解
2017/05/29 Python
Python实现Linux的find命令实例分享
2017/06/04 Python
python批量读取文件名并写入txt文件中
2020/09/05 Python
浅析PyTorch中nn.Module的使用
2019/08/18 Python
在线服装零售商:SheIn
2016/07/22 全球购物
蛋白质世界:Protein World
2017/11/23 全球购物
香蕉共和国工厂店:Banana Republic Factory
2018/06/09 全球购物
成考报名单位证明范本
2014/01/16 职场文书
运动会解说词100字
2014/01/31 职场文书
售后服务质量承诺书
2015/04/29 职场文书
检讨书格式
2019/04/25 职场文书
ThinkPHP5和ThinkPHP6的区别
2021/03/31 PHP
详解Vue的sync修饰符
2021/05/15 Vue.js