node+express+mysql开发后台接口

 

一、express生成一个应用生成器

1、express + ‘项目名称’

2、cd + ‘项目名称’

3、npm install

4、项目文件一览

5、控制器相关

6、模型相关

7、二级路由相关

二、mySql数据库

1、安装数据库

2、连接数据库

3、navicat 可视化工具

三、postman接口调试工具

1、安装postman软件

2、创建这个api接口开发的项目

 

3、创建该项目下的一些分类,news,user……

4、测试接口

5、测试成功的接口保存到相应的分类里。

三、sequelize

1、sequelize介绍:官网:https://sequelize.readthedocs.io/en/v3  

2.github中文:https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/querying.md

Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用JavaScript开发并且能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect),。它当前支持MySQL,、MariaDB、SQLite、PostgreSQL、Sql Server 数据库。

2、安装sequelize

1npm install --save sequelize

 

四、项目中安装MySQL

1 npm install --save mysql   (如果报错安装mysql2)

2配置db.js (如果利用自动生成数据库里边的模块,则可以直接放到index.js)

 
  1. var Sequelize = require('sequelize');

  2. // database数据库名称 name 用户 password密码

  3. var sequelize = new Sequelize('database', 'name', 'password', {

  4. host: 'localhost', //数据库域名

  5. dialect: 'mysql',

  6. pool: {

  7. max: 5,

  8. min: 0,

  9. idle: 10000

  10. }

  11. });

  12. module.exports=sequelize

3配置和数据库映射的模型

 
  1. var Sequelize = require('sequelize') //引入sequelize模块

  2. var db = require('./../db') //引入数据库

  3. /*

  4. * 定义表的映射模型

  5. * https://sequelize.readthedocs.io/en/v3/docs/models-definition/

  6. * */

  7. module.exports = db.define('tb_user',

  8. {

  9. id: {

  10. type: Sequelize.INTEGER(11),

  11. allowNull: false,

  12. primaryKey: true,

  13. autoIncrement: true

  14. },

  15. username: {

  16. type: Sequelize.STRING(50),

  17. allowNull: false

  18. },

  19. password: {

  20. type: Sequelize.STRING(50),

  21. allowNull: false

  22. },

  23. id_card: {

  24. type: Sequelize.STRING(50),

  25. allowNull: false

  26. }

  27. }

4使用上面定义的那个user模型,进行增删改查操作。若根据查询条件在数据库中查询到数据库,则返回查询到的数据,否则返回null。

 
  1. var User=require('./models/user')

  2. /* 查询单个*/

  3. User2.find({where:{id:1}})

  4. .then(function (res) {

  5. console.log(JSON.stringify(res))

  6. })

  7. .catch(function (ex) {

  8. console.log(ex)

  9. })

  10.  
  11. /*查询所有*/

  12. User.findAll({where:{sex:1},attributes:['id','username']}) //包含id和username

  13. .then(function (res) {

  14. console.log(JSON.stringify(res))

  15. })

  16. .catch(function (ex) {

  17. console.log(ex)

  18. })

  19.  
  20. /*分页查询所有,有条件 注意offset,linit数据类型必须为number */

  21. var param = {

  22. 'offset': 1, // 从第几个开始查询 Number(pageSize*pageNow)

  23. 'limit': 10, //每次查询多少个 size

  24. attributes:{exclude:['password']},//exclude不包含

  25. where: { sex:1 }

  26. }

  27. User.findAndCountAll(param)

  28. .then(function (res) {

  29. console.log(JSON.stringify(res))

  30. })

  31. .catch(function (ex) {

  32. console.log(ex)

  33. })

  34.  
  35. /*添加*/

  36. var user={

  37. username:'wo shi 1111111',

  38. password:'12312321321312312321313',

  39. id_card:'11011011101110110'}

  40. User.create(user)

  41. .then(function (res) {

  42. console.log(JSON.stringify(res))

  43. })

  44. .catch(function (ex) {

  45. console.log(ex)

  46. })

  47.  
  48. /*修改*/

  49. User.update({username:'abcdefg'},{where:{id:1}})

  50. .then(function (res) {

  51. console.log(JSON.stringify(res)) //更改成功返回 [1],失败返回[0]

  52. })

  53. .catch(function (ex) {

  54. //如果数据库里没有id这个属性名,才会进入到catch

  55. console.log(ex)

  56. })

  57.  
  58. /*删除*/

  59. User.destroy({where:{id:102}})

  60. .then(function (res) {

  61. console.log(JSON.stringify(res))

  62. })

  63. .catch(function (ex) {

  64. console.log(ex)

  65. })

五、sequelize-auto

上面的模型如果很多的话,一个一个操作会很麻烦。利用插件可以减少工作量。

1、官网:https://github.com/sequelize/sequelize-auto  利用sequelize-auto对照数据库自动生成相应的models,使用sequelize-auto对照数据库自动生成相应的models减少了对数据库进行增删改查时的sql语句的编写。

2、安装

1 npm install  sequelize-auto

2编写自动生成模型的auto.js

 
  1. var SequelizeAuto = require('sequelize-auto')

  2. // database数据库名称 name 用户 password密码

  3. var auto = new SequelizeAuto('database', 'name', 'password', {

  4. host: 'localhost', //数据库地址

  5. dialect: 'mysql',

  6. directory: './moduels', //生成的模块放到的目录

  7. port: '3306', //数据库端口

  8. additional: {

  9. timestamps: false

  10. }

  11. })

  12. auto.run(function (err) {

  13. if (err) throw err;

  14. console.log(auto.tables); // table list

  15. console.log(auto.foreignKeys); // foreign key list

  16. });

3在生成的moduels文件夹下,创建一个index.js将这些自动生成的数据库模型输入:

 
  1. var Sequelize = require('sequelize');

  2. /* 创建数据库连接 */

  3. var sequelize = new Sequelize("hhdj","root","root",{

  4. host:"127.0.0.1",

  5. dialect:"mysql",

  6. underscored:true

  7. })

  8. /* 数据库模型名称配置及路径 */

  9. const models=[

  10. {

  11. "name": "ApplyInfo",

  12. "path": "./tb_apply_info.js"

  13. },

  14. {

  15. "name": "Branch",

  16. "path": "./tb_branch.js"

  17. },

  18. {

  19. "name": "Carousel",

  20. "path": "./tb_carousel.js"

  21. }

  22.  
  23. ]

  24. /* 数据库模型输出 */

  25. models.forEach(item=>{

  26. module.exports[item.name]=require(item.path)(sequelize,Sequelize);

  27. })

4这样自己写比较麻烦,可以写一个自动生成index.js的createdModelsExport.js

代码里边直接将数据库链接的db.js的代码也放里边。

 
  1. var fs=require('fs') //引入文件读写模块

  2. let files=fs.readdirSync('./moduels') //读取所有的生成模块文件

  3. let models = []

  4. files.forEach(item=>{

  5. if(item!='index.js') { //除了这个index.js

  6. /**下面这段代码结果是将: tb_user.js 转换为name为 User **/

  7. let names = item.split('.')[0].split('_')

  8. let name = ''

  9. for(let i=1;i<names.length;i++) {

  10. name+=names[i].substring(0,1).toUpperCase() + names[i].substring(1)

  11. }

  12. models.push({name: name, path:"./"+item})

  13. }

  14. })

  15. /**视情况未定**/

  16. const template=`

  17. var Sequelize = require('sequelize');

  18. /* 创建数据库连接 */

  19. var sequelize = new Sequelize("hhdj","root","root",{

  20. host:"127.0.0.1",

  21. dialect:"mysql",

  22. underscored:true

  23. })

  24. /* 数据库模型名称配置及路径 */

  25. const models=${JSON.stringify(models,null,4)}

  26. /* 数据库模型输出 */

  27. models.forEach(item=>{

  28. module.exports[item.name]=require(item.path)(sequelize,Sequelize);

  29. })

  30. `

  31. fs.writeFile('./index.js',template,function(){

  32. console.log('success')

  33. })

六、apidoc的使用

1、介绍  官网:http://apidocjs.com/  ,apidoc根据可以注释的代码生成web api文档。

2、项目中使用:(更多详细配置看官网)

1全局安装: npm install apidoc –g

2创建apidoc.json

 
  1. {

  2. "name": " api文档", // name

  3. "version": "0.0.0", //版本号

  4. "description": "黄淮党建api文档,版本号:0.0.0", //描述

  5. "title": "黄淮党建api文档", // 标题

  6. "url" : "localhost://3000/api" //url前缀地址

  7. }

3编写需要导出的注释代码:

 
  1. module.exports = [

  2. /**

  3. * @api {get} /login 登录

  4. * @apiName GetUser

  5. * @apiGroup User

  6. *

  7. * @apiParam {string} phone 用户的手机号码.

  8. * @apiParam {string} password 用户的登录密码.

  9. *

  10. * @apiSuccess {String} code 登录成功返回信息.

  11. *

  12. * @apiSuccessExample Success-Response:

  13. * HTTP/1.1 200 OK

  14. * {

  15. * "phone": "17638583859",

  16. * "password": "1234565"

  17. * }

  18. *

  19. * @apiErrorExample Error-Response:

  20. * HTTP/1.1 500 server error

  21. * {

  22. * "error": "server error"

  23. * }

  24. */

  25. ]

4运行生成api网页

  命令: apidoc –i  ./myapp  -o  ./apidoc

  说明:-i myapp   myapp 注释文件所在的父文件夹

        -o apidoc   apidoc导出到哪个文件夹(自动生成)

  5打开生成的apidoc里边的index.html看一下效果

七、jwt

1、介绍:Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

2、项目中使用:

1安装 : npm install jwt-simple

2使用:在controllers/until.js编写导出设置token、验证token、以及统一返回格式方法。

普通写法:

 
  1. var jwt = require('jwt-simple') //引入jwt模块

  2. var User = require('../models').User //引入User数据库模型

  3.  
  4. module.exports={

  5. setToken:function(obj) { //设置Token

  6. return jwt.encode(obj, 'hhdj') //返回加密结果 jwt.encode('加密的对象','加密的秘钥')

  7. },

  8. checkToken:function(req,res,next) { //检查token

  9. var t = req.headers['token']

  10. if(!t) { //如果请求头中不存在token,返回"no token"信息

  11. res.send(this.setResult(500,'no token'))

  12. return

  13. }

  14. var token = jwt.decode(t,'hhdj') //token存在,进行解密

  15. if(!token) {

  16. res.send(this.setResult(500,'token error')) //解密不成功

  17. return

  18. }

  19. //解密成功,查询

  20. User.find({where:{id:token.id}}).then(r=>{

  21. req.TOKEN_USER = r

  22. //将在数据里边查询的信息,保存到req. TOKEN_USER里边

  23. next()

  24. }).catch(r=>{

  25. res.send(this.setResult(0,'token验证失败'))

  26. })

  27. },

  28. /* 接口统一返回格式 */

  29. setResult:function(code,message='success',data=null)=>{

  30. return{

  31. code:code,

  32. message:message,

  33. data:data

  34. }

  35. }

  36. }

3用户登录控制器里调用上面定义的加密方法,给用户返回token

 
  1. var User = require('../models').User

  2. var Until = require('./until') //同级目录下

  3. module.exports = {

  4. login: function(req, res, next) {

  5. var username = req.body.username; //统一接收前端的电话号,用户名,或者其他(多方式登录)

  6. var password = req.body.password;

  7. var param={

  8. $or:{ //$or sequelize提供的 或者查询

  9. phone:username,

  10. id_card:username

  11. },

  12. password:password

  13. }

  14. User.findOne({where:param}).then(r=>{

  15. res.send(Until.setResult(200,'success', Until.setToken(r)))

  16. }).catch(err=>{

  17. res.send(Until.setResult(500,'error',err))

  18. })

  19. }

  20. }

3需要验证是否登陆的路由里,判断用户是否登录(即是请求头里是否包含token信息)比如,user分组里,对userlist的查询请求。

Routes/index.js对路由的设置:

 
  1. var express = require('express');

  2. var router = express.Router();

  3. var ctrls = require('../../controllers')

  4. router.post('/user/login', ctrls.User.login);

  5. //当进入’user/userlist’这个路由是,先调用‘ctrls.Until.checkToken’判断

  6. //是否用户登录,如果已经登录,会在请求req里加上查询到数据,并放行。

  7. /next() 放行后执行后面的用户列表查询方法。

  8. router.get('/user/userlist', ctrls.Until.checkToken, ctrls.User.userlist);

  9. module.exports = router;

如果需要导出一个web api,就把注释加上:

 
  1. router.post(

  2. '/user/login',

  3. ctrls.User.login,

  4. /**

  5. * @api {post} /upload 上传文件

  6. * @apiVersion 1.0.0

  7. * @apiName upload

  8. * @apiGroup Common

  9. * @apiHeader {String} acces-token 用户token

  10. * @apiParam {Binary} file 上传文件

  11. * @apiSuccess {Number} code 结果标识

  12. * @apiSuccess {String} message 结果说明

  13. * @apiSuccess {Object} data 结果数据

  14. * @apiSuccessExample Success-Response:

  15. * HTTP/11 200 OK

  16. * {

  17. * "code": 1,

  18. * "mess": "成功",

  19. * "data": {}

  20. * }

  21. */);

在controllers/user.js里设置user/userlist路由的处理器

 
  1. var User = require('../models').User

  2. var Until = require('./until') //同级目录下

  3. module.exports = {

  4. userlist: function(req,res,next) {

  5. User.findOne({where:{id:req.TOKEN_USER.id}})

  6. .then(r=> {

  7. res.send(Until.setResult(200,'success', r))

  8. })

  9. .catch(ex=>{

  10. res.send(Until.setResult(500,'error'))

  11. })

  12. }

  13. }

八、crypto

1、介绍:crypto模块的目的是为了提供通用的加密和哈希算法。用纯JavaScript代码实现这些功能不是不可能,但速度会非常慢。Nodejs用C/C++实现这些算法后,通过cypto这个模块暴露为JavaScript接口,这样用起来方便,运行速度也快。

九、控制器部分原型写法

controllers/until.js代码:

 
  1. var jwt = require('jwt-simple')

  2. var User = require('../models').User

  3. var md5=require('md5')

  4. module.exports = function () {

  5. /* 设置token */

  6. this.setToken = (obj) => {

  7. return jwt.encode(obj, 'hhdjsystem')

  8. }

  9. /* 接口统一返回格式 */

  10. this.setResult=(code,message='success',data=null)=>{

  11. return{

  12. code:code,

  13. message:message,

  14. data:data

  15. }

  16. }

  17. }

controllers/user.js代码:

 
  1. var User = require('../models').User

  2. var Until = require('./Until’)

  3. function UserController() {

  4. this.userList = (req, res, next) => {

  5. var page = Number(req.query.page),

  6. size = Number(req.query.size)

  7. if (isNaN(page)) {

  8. page = 1

  9. }

  10. if (isNaN(size)) {

  11. size = 10

  12. }

  13. }

  14. UserController.prototype = new Until ()

  15. module.exports = new UserController()

十、二级路由模块化写法

按照上面那种写法,所有的二级路由全放到router/index里边,不便于维护,代码量也会很多。可以分开去写他们。

1router/index/user.js导出所有user分组下的路由控制和注释

 
  1. var ctrl =require('../../controllers/UserController')

  2. module.exports=[

  3. /**

  4. * @api {post} /user/userLogin 用户登录

  5. * @apiVersion 1.0.0

  6. * @apiName userLogin

  7. * @apiGroup User

  8. * @apiParam {String} account 用户的用户名或者手机号

  9. * @apiParam {String} password 用户的密码

  10. * @apiSuccess {Number} code 结果标识

  11. * @apiSuccess {String} message 结果说明

  12. * @apiSuccess {Object} data 用户token

  13. * @apiSuccessExample Success-Response:

  14. * HTTP/11 200 OK

  15. * {

  16. * "code": 1,

  17. * "mess": "成功",

  18. * "data": {}

  19. * }

  20. */

  21. {

  22. router:"/user/userLogin",

  23. method:"post",

  24. ctrls:[ctrl.userLogin]

  25. },

  26.  
  27. /**

  28. * @api {get} /user/userList 用户列表

  29. * @apiVersion 1.0.0

  30. * @apiName userList

  31. * @apiGroup User

  32. * @apiParam {Number} page 用户的用户名或者手机号

  33. * @apiParam {Number} size 用户的密码

  34. * @apiSuccess {Number} code 结果标识

  35. * @apiSuccess {String} message 结果说明

  36. * @apiSuccess {Object} data 结果数据

  37. * @apiSuccessExample Success-Response:

  38. * HTTP/11 200 OK

  39. * {

  40. * "code": 1,

  41. * "mess": "成功",

  42. * "data": {}

  43. * }

  44. */

  45. {

  46. router:"/user/userList",

  47. method:"get",

  48. ctrls:[ctrl.userList]

  49. },]

十一、formidable

1、介绍:用于解析表单数据的Node.js模块,特别是文件上传。官网:https://www.npmjs.com/package/formidable

api:

1创建一个新的传入表单:var  form  = new formidable.IncomingForm()  

2设置表单字段编码:form.encoding = ‘utf-8’

3设置放置上传文件的目录(需要手动提前创建),可以通过fs.rename,修改文件默认名:form.uploadDir = “./upload”

4如果要将写入的文件form.uploadDir包含原始文件的扩展名,请将此属性设置为true  : form.keepExtensions = false

5form.type  取决于传入的请求,“multipart”或“urlencoded”

6将所有字段的内存数量限制一共可以分配的字节(文件除外),如果超过此值,“error”则会发出事件。默认大小为2MB: form.maxFieldsSize = 2*1024*1024

7 form.maxFields=1000 限制查询字符串解析器解码的字段数。默认1000(0为无限制)

8form.hash=false   如果想要为传入文件计算校验和,设置为“sha1”或“md5”

9form.multiples = false   启动此项,该files参数包含提交多个输入文件的数组。

10form.bytesReceived   接收到总字节数

11form.parse(req,function(err,filds,files))  解析请求req中包含的表单数据,fields是解析的表单的普通数据,files是所有文件数据,通过回调函数处理。

 

Event:

1 form.on(‘progress’,function(bytesReceived,bytesExpected){})   在每个传入的数据块已被解析后发出,可以用来设置进度条。

2form.on(‘field’,function(name,value){})   每当接收到字段/值时发出。

3form.on(‘fileBegin’,function(name,file){})  在上传流中检测到新文件的发出,如果要在文件系统缓存上传文件到其他位置,使用此事件。

4form.on(‘file’,function(name,file))  每当接收到一个字段/文件时发送。

5form.on(‘error’,function(err){})   当传入的表单出错时,遇到错误的请求会自动暂停。

6form.on(‘aborted’,function(){})  当请求被用户终止时

7

form.on(‘end’,function(){}) 当收到整个请求时发出,并且所有包含的文件已经完成刷新到磁盘,这里是发送回复的最好地方。

 

2、项目中使用

1安装:npm install formidable

2编写上传文件的控制器:controllers/upload.js

 
  1. var Until = require('./until') //同级目录下

  2. var formidable=require('formidable') //引入formidable对象

  3. module.exports={

  4. upload:function (req,res,next){

  5. var form=new formidable.IncomingForm() //创建一个新的传入表单

  6. form.uploadDir='../upload'//上传文件夹

  7. form.multiples=true//支持多文件

  8. form.keepExtensions=true //是否保存上传文件的扩展名

  9. form.parse(req,(err,fields,files)=>{

  10. var files=files.file//上传文件名称myfile和前端设置的name要一样 <input type="file" name="myfile">

  11. var paths=[]

  12. if(!files){

  13. res.send(Until.setResult(0,'没有文件'))

  14. return

  15. }

  16. if(files instanceof Array){

  17. for(var i=0;i<files.length;i++){

  18. paths.push(files[i].path)

  19. }

  20. }else{

  21. paths.push(files.path)

  22. }

  23. res.send(Until.setResult(1,'success',paths))

  24. //可以使用fs.renameSync()重命名文件

  25. })

  26. }

  27. }

 

十二、winston 和 express-winston

1、介绍:Winston是Node.js最流行的日志框架之一,设计为一个简单通用的日志库,支持多传输(在Winston中,一个传输实质上代表储存设备,也就是数据最终保存在哪里),每个Winston实例都可以对不同级别的日志配置不同的传输。官网:https://www.npmjs.com/package/winston

express-winston为您的express.js应用程序的请求和错误记录提供了中间件。官网:https://www.npmjs.com/package/express-winston

2、使用:

1安装:npm install winston express-winston --save-dev

2创建存放成功和失败日志的文件夹。

 

3在app.js引入这两个模块

 
  1. var winston =require('winston');

  2. var expressWinston =require('express-winston');

  3.  
  4. // 正常请求的日志

  5. app.use(expressWinston.logger({

  6. transports: [

  7. new (winston.transports.Console)({

  8. json: true,

  9. colorize: true

  10. }),

  11. new winston.transports.File({

  12. filename: 'logs/success.log' //成功的日志记录在log/success.log

  13. })

  14. ]

  15. }));

  16.  
  17. //路由

  18. app.use('/api', api);

  19.  
  20. //记录错误的日志信息

  21. app.use(expressWinston.errorLogger({

  22. transports: [

  23. new winston.transports.Console({

  24. json: true,

  25. colorize: true

  26. }),

  27. new winston.transports.File({

  28. filename: 'logs/error.log' //失败的日志记录在log/success.log

  29. })

  30. ]

  31. }));

  32. module.exports = app;

十三、跨域配置

在app.js里边添加允许跨域的代码:

 
  1. var app = express();

  2. //设置跨域访问

  3. app.all('*',function (req, res, next) {

  4. res.header('Access-Control-Allow-Origin', '*');

  5. res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');

  6. res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');

  7.  
  8. if (req.method == 'OPTIONS') {

  9. res.send(200);

  10. //让options请求快速返回

  11. }

  12. else {

  13. next();

  14. }

  15. });

 

十四、使用supervisor工具

实时监控我们服务端代码的变化,如果使用了这个工具,不需要每次修改完服端的代码之后的重启。我们使用全局安装即可:npm install supervisor -g

官网:https://www.npmjs.com/package/supervisor

安装完毕之后,可以使用如下命令来启动项目:

十五、使用pm2

1启动命令:pm2 start ./www

2停止命令:pm2 stop ./www

2重启运行:pm2 start ./www -f

 

十六、参数

Get:req.query.xx  

Post:req.body.xx

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值