Node开箱即用的服务端基本配置

本文采用Express作为服务端框架,通过配置Token、七牛云对象存储(存储图片、视频等)、后端跨域、MySQL持久化存储等实现一个完整的服务端流程

并将异步抽离MySQL查询,实现代码的Promise化

详见GitHub: https://github.com/cgq001/express-token

1.Token

//生成Token
npm install jsonwebtoken -S

// 登陆并生成token
Routers.get('/load', (req,res) => {
    let tokenObj={   //携带参数
            id: 1,
            username: '小明'
        }
        let tokenKey = "123456455"  //加密内容,随便写,但是最好存储在一个公共文件内,因为解密的时候也需要用
    
        let token = jwt.sign(tokenObj,tokenKey,{
            expiresIn: 60*60*24   // token时长
        })
    
        res.json({  //返回前端
            code: 0,
            msg: '查询成功',
            token:token,
            data:{
                username: '12456'
    
            }
        })
})

//验证Token
npm install express-jwt -S

//token/index.js
const expressJwt = require('express-jwt');
const { secretKey } = require('./constant');  //存在 公共文件里的 加密内容即为生成Token时的加密内容(如上:tokenKey="123456455" )

const jwtAuth = expressJwt({secret: secretKey}).unless({path:['/index/load']})
//unless 为排除那些接口,排除的接口将不再进行Token 验证

module.exports = jwtAuth;


//验证
// 全局验证Token是否合法
const tokens = require('../token/index')

Routers.use(tokens)

//注意 这里可以配置在特定的路由文件内,不要配置到app.js(全局入口文件),毕竟不需要验证Token 的文件如果很多的话,不能一个一个去排除吧?

前端携带Token

Authorization: "Bearer xczsxssdshsd.zxjjdjsjdsjdsjsd.djjsjsjsdj"

2.七牛云对象存储

七牛云为常用的对象存储空间,每个人都有10G的免费使用空间,这点还是很良心的,一般个人使用的话,也够用了,自行注册,配置

插件支持

npm install formidable -S   # 获取上传文件
npm install qiniu -S        # 七牛云SDK
const moment = require('moment');  // 获取格式化时间
var path = require('path')
const fs = require('fs')
//获取图片等文件
var formidable = require('formidable');

//七牛云配置
const qiniu = require('qiniu')

const accessKey = '*********'   //AK 注册后 可在后台获取
const secretKey = '*********'  //SK  祖册后 可在后台获取
const bucket = 'book'  // 上传到的对象存储名称(创建对象存储的时候起的名字)


// 七牛云 上传
Routers.post('/upload', (req,res) => {
    let form = new formidable.IncomingForm();
        form.parse(req, function (err, fields, filesa){
                console.log(filesa.file);  //获取上传后的文件  filesa.file(file是上传时的Name名字)
                let MathRoundNumber = Math.round(Math.random()*100000)
                 let MathRound = moment().format("YYYY_MM_DD_hh_mm_ss")
                let key = MathRound+MathRoundNumber+filesa.file.type //上传 后文件的名字(相当于对上传后文件进行重命名)
                let  path= filesa.file.path  //上传文件路径


               let mac = new qiniu.auth.digest.Mac(accessKey,secretKey)
               let options = {
                    scope: bucket,
                    expires: 3600 * 24  //凭据过期时间
               }

                let putPolicy = new qiniu.rs.PutPolicy(options)
                let uploadToken = putPolicy.uploadToken(mac)

                uploadFile(uploadToken, key, path).then(idea=>{
                    console.log('上传成功');
                    res.json({
                        code: 0,
                        msg: '上传成功',
                        data:{
                            url: "http://img.abc.com/"+idea.key   
                            //上传返回的是文件名称,需要搭配上自己在对象存储内绑定的域名(七牛云赠送的域名只能使用一个月)
                        }
                    })
                })
                .catch(err=>{
                    //其实这种情况 也上传了图片,为了严禁起见
                    if(err.key){
                        res.json({
                            code: 4,
                            msg: '上传失败',
                            data:{
                                 url: "http://img.abc.com"+err.key
                            }
                        })
                    }else{
                        res.json({
                            code: 4,
                            msg: '上传失败',
                            data:{
                                 url: ''
                            }
                        })
                    }          
                    
                })
                

             
            //构造上传函数
              async  function uploadFile(uptoken, key, localFile) {
             
                     var config = new qiniu.conf.Config();
                        // 空间对应的机房
                        config.zone = qiniu.zone.Zone_z0;
                    var formUploader = new qiniu.form_up.FormUploader(config);
                    var putExtra = new qiniu.form_up.PutExtra();
                    return  new Promise((resolve,reject)=>{
                        // 文件上传
                            formUploader.putFile(uptoken, key, localFile, putExtra, function(respErr,
                              respBody, respInfo) {
                              if (respErr) {
                                throw respErr;
                              }
                              if (respInfo.statusCode == 200) {
                                resolve(respBody)
                              } else {
                                reject(respBody)   //其实这种情况 也上传了图片,为了严禁起见
                              }
                            })
                     })
                }  
        })
})

3.跨域

npm install cors -S

// 配置跨域 
app.use(cors());

4.MySQL

1.MySQL连接处

npm install mysql -S

// 引入 mysql 数据库连接依赖  
const mysql = require("mysql");

//config/db.js

// 创建 mysql 连接池并配置参数   
const pool = mysql.createPool({
    host: "127.0.0.1",    // 主机地址
    port: 3306,                 // 端口
    user: "root",               // 数据库访问账号
    password: "*****",         // 数据库访问密码
    database: "im",           // 要访问的数据库
    charset: "UTF8_GENERAL_CI", // 字符编码 ( 必须大写 )
    typeCast: true,             // 是否把结果值转换为原生的 javascript 类型
    supportBigNumbers: true,    // 处理大数字 (bigint, decimal), 需要开启 ( 结合 bigNumberStrings 使用 )
    bigNumberStrings: true,     // 大数字 (bigint, decimal) 值转换为javascript字符对象串
    multipleStatements: false,  // 允许每个mysql语句有多条查询, 未防止sql注入不开启
    //connectTimeout: 5000,     // 数据库连接超时时间, 默认无超时
});
// console.log(pool);

pool.connectionLimit = 10;      // 连接池中可以存放的最大连接数量
pool.waitForConnections = true; // 连接使用量超负荷是否等待, false 会报错
pool.queueLimit = 0;            // 每个连接可操作的 列数 上限, 0 为没有上限

// 对外暴漏从连接池中获取数据库连接的方法
exports.query = function(sql, arr, callback){
    //建立链接
    pool.getConnection(function(err,connection){
        if(err){throw err;return;}
        connection.query(sql,arr,function(error,results,fields){
            //将链接返回到连接池中,准备由其他人重复使用
            connection.release();
            if(error) throw error;
            //执行回调函数,将数据返回  callback &&
            callback && callback(results,fields);
        });
    });
};

4.2 异步查询

//user.js


//数据库配置
const db= require('../config/db')

const fn={
    // 登录
    loadUser:async function(data){
        let sql ="select * from user where email=?"
        let arr=[]
            arr.push(data)

        
        return new Promise((resolve,reject)=>{
           db.query(sql,arr,function(data,err){
                if(err){
                    reject(err)
                }
                resolve(data)
            })
        })
        // return await db.query(sql,arr)
    },
    // 获取好友列表
    getUserlist:async function(id){
        let sql ="select a.*, b.*,a.id as user_id from contacts a inner join user b on a.userlistid = b.id where userid=?"
        let arr=[]
            arr.push(id)
        return new Promise((resolve,reject)=>{
           db.query(sql,arr,function(data,err){
                if(err){
                    reject(err)
                }
                resolve(data)
            })
        })
    }
}

module.exports = fn;

1.3使用

const fn = require('../model/user')  //获取 异步查询方法

//获取好友列表
Routers.post('/getUserList', (req,res) => {
    console.log(req.user);
    fn.getUserlist(req.user.id)
        .then(ideas=>{
            res.json({
                code: 0,
                data: ideas
            })
        })
})

5.静态文件

// 配置静态目录
app.use(express.static(path.join(__dirname,'public')))
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,082评论 1 32
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,072评论 0 3
  • 就读于魔法学院的方衍拿到了令所有人都羡慕不已的魔法部推荐信,要知道那可是魔法特区最高级别的机构,唯有最优秀的人才有...
    爱豆花儿阅读 158评论 0 0
  • 鞭炮声在耳边此起彼伏,由于西安雾霾的影响,今年禁止燃放烟花炮竹,可是新年没有炮声太沉寂了,禁止燃放,却禁不住人们...
    悠然晨欣阅读 306评论 3 2
  • 6月22日上午,广西北海下暴雨。暴雨足足下了五个钟头。雨停后,水退了,出现满大街的鱼。 一群鱼 成百上千条鱼 被...
    蔚霐_d38f阅读 471评论 4 4