node+express+mysql增删改查小例子
最近尝试入门node,express,集成mysql,做了一个小例子,感觉node的后台的话,因为刚从java尝试入门的话,那个架构是比较混乱的,按我目前学到的来说,model层的定义不像java那样,如果用了sequelize的话,这个工具本身会有一个定义实体类的方法,像moongoose这样,一开始做的时候那个分层始终有点模糊,我看了别的源码,有些分出controller层,有些就直接用routers文件夹做controller的功能,并且model层是集成了dao层的,也有看到一些大型的项目会分出service层,总之有点乱,后来看到一个有意思的评论——'我觉得这个跟框架还是有很大关系,比如认知度比较高的express和koa框架本身没有推荐MVC结构,而是使用了中间件(middleware)。而对比JAVA世界的spring,其本身就提倡使用MVC结构。所以做JAVA开发,跟随spring的框架,自然就搞成了MVC。跟随express自然中间件的思想更多一些。还有就是,具体怎么写还是要看具体的开发人员。所以还是有一使用MVC的nodejs开发。'所以如果想应用好的话还是先得了解下中间件,不过本人以前写java后台的,所以这个小例子可能还是有mvc的味道。express快速入门
mysql的建表语句
CREATE TABLE `tb_student` (
`student_id` varchar(32) NOT ,
`name` varchar(32) NOT NULL ,
`subject` varchar(32) NOT NULL ,
`grade` varchar(10) NOT NULL ,
`sex` int(2) NOT NULL ,
UNIQUE KEY `student_id` (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
然后下载安装好node以后,在你的工作目录里面执行命令
npm install express --save
npm install express-generator --save
npm install mysql --save
这样就下载好所需的东西了,node的入门可以找廖雪峰的博客,真的是干货满满。然后可以在命令行里面输入express 项目名
这样就生成一个项目的大致目录:
大概是这样子的
其中dao是自己建的,modules我暂时把它看作工具类。。。routes则起到controller的作用,dao就是封装该类的一些方法。
jade和ejs都是一些模板引擎,可以用来渲染页面,然后basicConnection和dbconfig是封装查询语句和数据库的配置文件,sqlCommand则是存放语句操作的地方
config = {
host:'localhost',
user:'root',
password:'123456',
database:'student',
port:3306
}
module.exports = config
var student_sql={
insertOne:'insert into tb_student (student_id,name,subject,grade,sex) values (?,?,?,?,?)',
deleteOne:'delete from tb_student where student_id = ?',
updateOne:'update tb_student set name = ?,subject = ?,grade = ?,sex = ? where student_id = ?',
selectOne:'select * from tb_student where student_id = ?',
selectAll:'select * from tb_student',
}
module.exports=student_sql
var mysql = require('mysql');
var dbConfig = require('./dbconfig');
const pool=mysql.createPool(dbConfig);
function responseDoReturn(res, ret) {
if(typeof ret === 'undefined') {
res.json({
code:'1',
msg: '操作失败'
});
} else {
res.json(ret);
}
};
/**
* 封装query之sql带不占位符func
*/
function query(sql, callback) {
pool.getConnection(function (err, connection) {
if(err){
callback(err,null,null);
}else{
connection.query(sql, function (err, rows) {
connection.release();
callback(err, rows); //释放链接
});
}
});
}
/**
* 封装query之sql带占位符func
*/
function queryArgs(sql,args, callback) {
pool.getConnection(function (err, connection) {
if(err){
callback(err,null,null);
}else{
connection.query(sql, args,function (err, rows) {
connection.release();
callback(err, rows);
//释放链接
});
}
});
}
//exports
module.exports = {
query: query,
queryArgs: queryArgs,
doReturn: responseDoReturn
}
以上就是这三个文件,然后到编写dao层的代码
var studentSql=require('../modules/sqlCommand');
var mysql = require('mysql');
var config = require('../modules/dbconfig');
var db = require('../modules/basicConnection');
function addStudentAction(req,res,next){
var param = req.query || req.params;
//student_id,name,subject,grade,sex
db.queryArgs(studentSql.insertOne,[param.studentid,param.name,param.subject,param.grade,param.sex],function(err,result) {
if(!err){
result={
code:200,
msg:'success'
};
}else{
result={
code:201,
msg:'err:'+err
}
}
db.doReturn(res,result);
});
}
function deleteStudent(req,res,next){
var param = req.query;
db.queryArgs(studentSql.deleteOne,param.studentid,function(err,result){
if(!err){
result={
code:200,
msg:'success'
}
}else{
result={
code:201,
msg:'err:'+err
}
}
db.doReturn(res,result);
});
}
function queryAllStudent(req,res,callback){
var result={};
db.query(studentSql.selectAll,function(err,rows){
if(!err){
result={
code:200,
msg:'success',
studentlist:rows,
}
}else{
result={
code:201,
msg:'err:'+err,
}
}
callback(result);
});
}
function updateStudent(req,res,callback){
let find = true;
var param = req.query||req.params;
var result={};
db.queryArgs(studentSql.selectOne,param.studentid,function(err,rows){
if(rows!=null){
var student={};
var row = rows[0];
(typeof(param.name) == 'undefined')? student.name=row.name: student.name=param.name;
(typeof(param.subject)=='undefined')?student.subject=row.subject:student.subject=param.subject;
(typeof(param.grade)=='undefined')?student.grade=row.grade:student.grade=param.grade;
(typeof(param.sex)=='undefined')?student.sex=row.sex:student.sex=param.sex;
student.studentid=param.studentid;
console.log(student);
db.queryArgs(studentSql.updateOne,[student.name,student.subject,student.grade,student.sex,student.studentid],function(err,rows){
if(!err){
result={
code:200,
msg:'success',
}
}else{
result={
code:201,
msg:'err:'+err
}
}
callback(result);
});
}else{
console.log('null');
}
});
}
module.exports={
addStudentAction:addStudentAction,
deleteStudent:deleteStudent,
queryAllStudent:queryAllStudent,
updateStudent:updateStudent,
}
这里的更新方法暂时找不到像mybatis那样可以先判断时候属性为空的再更改那种,只能先查出来了再修改,不然把其他属性都改为空了。
controller层的:
var express = require('express');
var router = express.Router();
var studentDao = require('../dao/studentDao');
router.get('/addStudentAction',function(req,res,next){
studentDao.addStudentAction(req,res,next);
});
router.get('/deleteStudentAction',function(req,res,next){
studentDao.deleteStudent(req,res,next);
});
router.get('/queryStudentAction',function(req,res,next){
studentDao.queryAllStudent(req,res,function(result){
res.render('student',{'result':result});
});
});
router.post('/updateStudentAction',function(req,res,next){
studentDao.updateStudent(req,res,function(result){
res.json(result);
});
}) ;
module.exports = router;
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var studentRouter = require('./routes/studentcontroller');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/students',studentRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
这个文件的view试图那里我没有进行代码的编写,直接返回了json字符串,所以不管哪个模板了。要返回模板渲染的话,可以对result进行传递并在router层里进行渲染。
对了,js的回调、异步需要注意,个人感觉这是个大坑。然后在bin的www启动项目就行了,还有我的开发工具是Visual Studio Code,测试工具同样是postman
运行结果如下
增加:
修改
现在数据库有这三条
修改以后
删除以后
这个新手做的小例子介绍完毕,还是那句,那个回调异步那些要注意一下
然后再额外添加一些新的东西,在windows下用nginx做代理以及pm2作为项目管理,并且用ejs作为一个结果的渲染,
ejs:npm install ejs --save
需要知道views是需要有error页面的,不然就会报错渲染不了。下面是error.ejs和student.ejs
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>EJS模板</title>
</head>
<body>
<h3><%=message%></h3>
<h3><%=error.status%></h3>
<h3><%=error.stack%></h3>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test</title>
</head>
<body>
<h1>学生信息展示</h1>
<%if(result.code=='200'){%>
<%for (var i=0;i<result.studentlist.length;i++){%>
<p><%= '学号:'+result.studentlist[i].student_id%></p>
<p><%= '姓名:'+result.studentlist[i].name%></p>
<p><%= '专业:'+result.studentlist[i].subject%></p>
<p><%= '年级:'+result.studentlist[i].grade%></p>
<% if(result.studentlist[i].sex=='1'){%>
<p>性别:男</p>
<%}else{%>
<p>性别:女</p>
<%}%>
<%}%>
<%}else{%>
<h1>无数据</h1>
<%}%>
</body>
</html>
只需在app.js那里把试图渲染改为ejs并且把相应的中间件返回正确的路径即可
然后就是nginx的window版本下载下来,并且修改配置文件(nginx.conf),主要是修改server,具体的文档可以上网找
server {
listen 8080;//监听8080端口
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://localhost:3000; #把请求转发到3000
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
然后下载pm2来作为我们的程序管理nmp -install pm2 --save,pm2的用法网上也很多,这里只说最简单的
下载以后在命令行的www的具体路径上输入
pm2 start www就可以启动项目 pm2 stop www就关闭了
然后到nginx的安装目录下在命令行输入nginx -start,如果已经启动而修改了配置文件,可以用 nginx -s reload来更改配置,
关闭是 nginx -s quit
然后在8080端口输入我们的访问路径
结果如图:
这个简单的小例子就到这里啦,以上都是本人的拙见。。。
上一篇: Nodejs -- 网络编程
下一篇: 基于node.js的一个小爬虫