初识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如何搭建Web服务器
Mar 28 NodeJs
NodeJS与HTML5相结合实现拖拽多个文件上传到服务器的实现方法
Jul 26 NodeJs
nodejs实现发出蜂鸣声音(系统报警声)的方法
Jan 18 NodeJs
利用nodejs监控文件变化并使用sftp上传到服务器
Feb 18 NodeJs
深入解析nodejs HTTP服务
Jul 25 NodeJs
NodeJS爬虫实例之糗事百科
Dec 14 NodeJs
nodejs更改项目端口号的方法
May 13 NodeJs
nodejs 使用 js 模块的方法实例详解
Dec 04 NodeJs
nodeJS进程管理器pm2的使用
Jan 09 NodeJs
详解NodeJs项目 CentOs linux服务器线上部署
Sep 16 NodeJs
Nodejs 数组的队列以及forEach的应用详解
Feb 25 NodeJs
NodeJS和浏览器中this关键字的不同之处
Mar 03 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 Smarty date_format [格式化时间日期]
2010/03/15 PHP
5款适合PHP使用的HTML编辑器推荐
2015/07/03 PHP
Symfony2函数用法实例分析
2016/03/18 PHP
PHP isset()与empty()的使用区别详解
2017/02/10 PHP
JavaScript DOM 添加事件
2009/02/14 Javascript
js中的referrer返回上一页使用介绍
2013/09/26 Javascript
jQuery中:lt选择器用法实例
2014/12/29 Javascript
原生js结合html5制作简易的双色子游戏
2015/03/30 Javascript
jQuery $.each遍历对象、数组用法实例
2015/04/16 Javascript
JQuery简单实现锚点链接的平滑滚动
2015/05/03 Javascript
解析JavaScript中的字符串类型与字符编码支持
2016/06/24 Javascript
全面了解JavaScript对象进阶
2016/07/19 Javascript
浅析js的模块化编写 require.js
2016/12/07 Javascript
基于vue v-for 循环复选框-默认勾选第一个的实现方法
2018/03/03 Javascript
详解使用mpvue开发github小程序总结
2018/07/25 Javascript
jQuery实现点击旋转,再点击恢复初始状态动画效果示例
2018/12/11 jQuery
js实现ATM机存取款功能
2020/10/27 Javascript
vue子路由跳转实现tab选项卡
2019/07/24 Javascript
在Vue中创建可重用的 Transition的方法
2020/06/02 Javascript
在vue中使用Echarts画曲线图的示例
2020/10/03 Javascript
Python 命令行非阻塞输入的小例子
2013/09/27 Python
利用Python绘制数据的瀑布图的教程
2015/04/07 Python
python内存管理分析
2015/04/08 Python
python如何在列表、字典中筛选数据
2018/03/19 Python
Django中反向生成models.py的实例讲解
2018/05/30 Python
Python中文编码知识点
2019/02/18 Python
详解python中list的使用
2019/03/15 Python
python如何实现异步调用函数执行
2019/07/08 Python
Python 网络编程之TCP客户端/服务端功能示例【基于socket套接字】
2019/10/12 Python
解决python彩色螺旋线绘制引发的问题
2019/11/23 Python
python实现指定ip端口扫描方式
2019/12/17 Python
小学学校评估方案
2014/06/08 职场文书
工作失职检讨书(精华篇)
2014/10/15 职场文书
地道战观后感400字
2015/06/04 职场文书
成本低的5个创业项目:投资小、赚钱快
2019/08/20 职场文书
Redis 报错 error:NOAUTH Authentication required
2022/05/15 Redis