基于nuxt+express+mysql+redis+nginx的全栈实践

1 篇文章 0 订阅

写在前面

nuxt-bnhcp是我写的一个全栈商城系统,从前端ui切图到后台mysql以及redis缓存,是一个相对完整且系统的项目,nuxt-bnhcp开源至今,收到了大量的反馈和朋友们遇到的问题以及nuxt-bnhcp后台源码问题,因为后台配置和项目庞大没有时间腾出手写一篇文章去详细的介绍一下自己项目,今天,所有的后台代码以及前端代码已经提交至github。 我非常期待大家可以给我提出建议和优化。 下面介绍下我的nuxt-bnhcp:

GitHub地址:https://github.com/github1586/nuxt-bnhcp

流程图

后台目录介绍

├── api                        ##请求api目录
│   ├── controller             ##处理业务逻辑
│   │   ├── cart               ##购物车
│   │   │   └── index.js       
│   │   ├── course             ##课程列表
│   │   │   └── index.js
│   │   ├── home               ##首页加载
│   │   │   └── index.js
│   │   ├── interface.js
│   │   ├── login              ##登录注册
│   │   │   └── index.js
│   │   ├── order              ##订单中心
│   │   │   └── index.js
│   │   ├── paramsFilter.js    ##sql参数过滤器
│   │   └── router.js          ##路由
│   ├── index.js               ##导出路由
│   ├── model                  ##mysql数据库相关
│   │   ├── db.js              ##数据库增删改查封装
│   │   ├── settings.js        ##数据库配置用户
│   │   └── sql.js             ##sql语句
│   └── redis                  ##redis设置
│       └── redis.js            
└── index.js                   ##后台服务入口       

后台源码分析

interface.js

import { Router } from 'express'
const myrouter = require('./router.js')
var router = Router()
// index router
router.get('/', myrouter.indexShow)
// 页面初始化加载一级分类第一个
router.get('/listhome', myrouter.gradeOne)
// 点击对应一级 给出三级响应
router.get('/listhome/:id', myrouter.gradeOne)
// 点击筛选请求展示内容
router.get('/listhome/filter/data', myrouter.filter)
// 课程列表
router.get('/courselist', myrouter.getCourseList)
// 课程详情
router.get('/courseDetail/index/:id', myrouter.getDetail)
// 课程模糊查询
router.get('/getleckCourse', myrouter.getleckCourse)
// 购物车存储id
router.get('/postCourseId', myrouter.postCourseId)
// 是否存在购物车
router.get('/isexistCart/:id', myrouter.isCart)
// 购物车列表
router.get('/cartList', myrouter.cartList)
// 删除购物车列表
router.get('/deleteCart', myrouter.deleteCart)
// 批量提交购物车
router.get('/mostAddClass', myrouter.mostAddClass)
// 登录
router.post('/longin', myrouter.longin)
// 提交订单
router.get('/submitOrder', myrouter.submitOrder)
// 支付成功 更改订单状态
router.get('/paySuccess', myrouter.paySuccess)
// 请求订单列表
router.get('/getOrderList', myrouter.getOrderList)

export default router

匹配路由调用处理对应业务逻辑

/**
 * Created by bobo on 2017/06/10 21.31
 */

var indexshowController = require('./home') // 主页
var courseController = require('./course') // 课程
var cartController = require('./cart') // 购物车
var loginController = require('./login') // 登录
var orderController = require('./order') // 订单

exports.indexShow = indexshowController.indexShow // 首页展示
exports.gradeOne = courseController.gradeOne // 默认一级分类
exports.filter = courseController.filter // 筛选条件
exports.getCourseList = courseController.getCourseList // 课程列表
exports.getDetail = courseController.getDetail // 课程详情
exports.getleckCourse = courseController.getleckCourse // 课程模糊查询
exports.postCourseId = cartController.postCourseId // 购物车 商品id
exports.isCart = cartController.isCart // 是否存在购物车
exports.cartList = cartController.cartList // 购物车列表
exports.deleteCart = cartController.deleteCart // 删除购物车
exports.mostAddClass = cartController.mostAddClass // 批量提交购物车
exports.longin = loginController.longin // 登录
exports.submitOrder = orderController.submitOrder // 订单
exports.paySuccess = orderController.paySuccess // 支付成功
exports.getOrderList = orderController.getOrderList // 获取订单列表

引入对应业务模块 导出对应业务方法

const db = require('../../model/db.js')
const sql = require('../../model/sql.js')
// 引入redis
var dbs = require('../../redis/redis.js')

/**
 *  index show
 */
exports.indexShow = (req, res, next) => {
  db.query(sql.index, function (err, rows, fields) {
    if (err) {
      throw err
    }
    // 检查是否存在获取值(redis)
    dbs.exists('indexshow', function (err, results) {
      if (err) {
        throw err
      }
      if (results) {
        dbs.get('indexshow', function (err, result) {
          if (err) {
            return
          }
          res.json(JSON.parse(result))
        })
      } else {
        var allparentinfo = []
        var indexClass = []
        for (var i = 0; i < rows.length; i++) {
          // 两个大分类
          var classList = []
          // 四个小分类
          var classMoreList = []
          // 两个大分类
          var classImg = rows[i].showMainName.split('&')
          for (var j = 0; j < classImg.length; j++) {
            // 每次得到的对象push进数组
            classList.push({ classname: classImg[j].split('@')[0], imgurl: classImg[j].split('@')[1], coueseGradeId: rows[i].coueseGradeId })
          }
          // 四个小分类 课程名称
          var classSmall = rows[i].showSmallName.split('&')
          for (var x = 0; x < classSmall.length; x++) {
            classMoreList.push({classname: classSmall[x].split('@')[0], imgurl: classSmall[x].split('@')[1], coueseGradeId: rows[i].coueseGradeId})
          }
          // 把整块 push 到数据数组
          allparentinfo.push({headinfo: {before: rows[i].showCourseMore, after: rows[i].showCourseName, imgurl: rows[i].showCourseIcon},
            course: {
              classList: classList,
              classMoreList: classMoreList
            }})
        }
        // 查找分类
        db.query(sql.showClass, function (err, rows, fields) {
          if (err) {
            throw err
          }
          // 循环查找数据
          for (var i = 0; i < rows.length; i++) {
            var classObj = {}
            classObj.showClassImg = rows[i].showClassImg
            classObj.showClassName = rows[i].showClassName
            classObj.classPid = rows[i].classPid
            indexClass.push(classObj)
          }
          // 专成json格式
          var data = {allparentinfo: allparentinfo, indexClass: indexClass}
          // 设置值
          dbs.set('indexshow', JSON.stringify(data), 300, function (err, result) {
            if (err) {
              res.json(err)
            }
          })
          res.json(data)
        })
      }
    })
  })
}

首页业务处理,接收请求->是否走缓存->是否命中缓存->正常业务处理

mysql部分

MySQL是一种DBMS(数据库管理系统),也是一个关系数据库。其中My是MySQL的联合创始人 - Monty Widenius 的女儿的名字。MySQL是My和SQL的组合,这就是MySQL命名的由来。它是由Oracle支持的开源软件。这意味着任何一个人都可以免费使用MySQL。 另外,如果需要,还可以更改其源代码或进行二次开发以满足您的需要。

MySQL可以在各种平台上运行UNIX,Linux,Windows等。可以将其安装在服务器甚至桌面系统上。 此外,MySQL是可靠,可扩展和快速的。

/**
 * 数据库操作 @bobo
 * 2017/06/10
 */
const mysql = require('mysql')
const setting = require('./settings.js')

// 填写数据库连接信息,
const option = {
  host: setting.host,
  port: setting.port,
  user: setting.username,
  password: setting.password,
  database: setting.name
}

// 建立连接池
const pool = mysql.createPool(option)

/**
 * select和delete操作
 * @param  {string}   sql      sql语句
 * @param  {Function} callback 回调函数
 * @return {none}
 * */
const __selsctDelete = (sql, callback) => {
  pool.getConnection(function (err, conn) {
    if (err) {
      console.log('CONNECT ERROR:', err.message)
      callback(err, null, null)
    } else {
      conn.query(sql, function (err, rows, fields) {
        // 释放连接
        conn.release()
        // 事件驱动回调
        callback(err, rows, fields)
      })
    }
  })
}

/**
 * update和insert操作
 * @param  {string}   sql      sql语句
 * @param  {array}    params   参数数组
 * @param  {Function} callback 回调函数
 * @return {none}
 */
const __updateInsert = function (sql, params, callback) {
  pool.getConnection(function (err, conn) {
    if (err) {
      console.log('CONNECT ERROR:', err.message)
      callback(err, null, null)
    } else {
      conn.query(sql, params, function (err, rows, fields) {
        // 释放连接
        conn.release()
        // 事件驱动回调
        callback(err, rows, fields)
      })
    }
  })
}

/**
 * query函数重载
 * @return {none}
 */
exports.query = function () {
  var length = arguments.length
  var sql = ''
  var cb = ''
  if (length === 2) {
    sql = arguments[0]
    cb = arguments[1]
    __selsctDelete(sql, cb)
  } else if (length === 3) {
    sql = arguments[0]
    var params = arguments[1]
    cb = arguments[2]
    __updateInsert(sql, params, cb)
  } else {
    console.log('ERROR:', '参数不对呀?亲~~')
  }
}

利用重载对mysql的增删改查做一些封装操作

redis介绍

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API

var dbs = {}
var redis = require('redis')
var client = redis.createClient()
client.on('error', function (err) {
  console.log('Error :', err)
})

client.on('connect', function () {
  // console.log('Redis连接成功.')
})

/**
 * 添加string类型的数据
 * @param key 键
 * @params value 值
 * @params expire (过期时间,单位秒;可为空,为空表示不过期)
 * @param callBack(err,result)
 */
dbs.set = function (key, value, expire, callback) {
  client.set(key, value, function (err, result) {
    if (err) {
      console.log(err)
      callback(err, null)
      return
    }
    if (!isNaN(expire) && expire > 0) {
      client.expire(key, parseInt(expire))
    }
    callback(null, result)
  })
}
/**
 * 查询string类型的数据
 * @param key 键
 * @param callBack(err,result)
 */
dbs.get = function (key, callback) {
  client.get(key, function (err, result) {
    if (err) {
      console.log(err)
      callback(err, null)
      return
    }
    callback(null, result)
  })
}

/**
 * 查询是否存在
 * @param key 键
 * @param callBack(err,result)
 */
dbs.exists = function (key, callback) {
  client.exists(key, function (err, result) {
    if (err) {
      console.log(err)
      callback(err, null)
      return
    }
    callback(null, result)
  })
}

/**
 * 生成自增id
 * @param key 键
 * @param callBack(err,result)
 */
dbs.orderId = function (callback) {
  let time = new Date()
  let second = time.getTime()
  let year = time.getFullYear()
  let month = time.getMonth() + 1
  let date = time.getDate()
  client.exists('orders', function (err, result) {
    if (err) {
      throw err
    }
    if (!result) { // 第一次进入生成id
      client.set('orders', second, function (err, result) { // 设置id
        if (err) {
          throw err
        }
      })
    } else {
      client.INCR('orders') // 每次自增
      dbs.get('orders', function (err, results) { // 得到id 回调上传
        if (err) {
          throw err
        }
        results = results + '' + year + month + date
        callback(null, results)
      })
    }
  })
}
// 导出对象
module.exports = dbs

对redis的增删改查做封装,其中生成自增id方法是针对提交订单后生成唯一订单号

nginx介绍

5、 nginx 配置文件

    nginx.conf文件:
    
    worker_processes 1;
    error_log logs/error.log;
    error_log logs/error.log notice;
    error_log logs/error.log info;
    pid logs/nginx.pid;
    events {
       use epoll;
       worker_connections 1024;
     }
    http {
       include mime.types;
       default_type application/octet-stream;
      sendfile on;
      keepalive_timeout 65;
     #gzip on;
     include /usr/local/nginx/conf/conf_site/*.conf; // 单独 include conf文件
   }
   
   include的conf配置 :
   
    server{
       listen 80;
       location / {
         deny all;
        }
    }
   upstream maven_domain_com {
       server localhost:8000; // 自己的服务器ip
    }
   server{
        listen 80;  // 监听80端口
        server_name maven.domains.com; // 自己的二级域名
        location / {
           proxy_pass http://maven_domains_com/nexus/;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       } 
       location /nexus/ {
           proxy_pass http://maven_domain_com/nexus/;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       }
    }

centos服务器上的nginx配置。

END!!!

欢迎大家交流~

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值