Express+MySQL后端搭建

173 阅读5分钟

设置安装环境

进入项目文件夹,执行指令

npm i express-generator -g

image.png

初始化express

express server

image.png

进入项目,安装依赖

image.png

项目如下所示

image.png

  • bin/www:是整个项目的启动脚本,内部配置了很多和服务启动相关的选项。
  • public:公共资源,比如前端传给后端图片,后端拿到之后就放在public/images目录里面。
  • routes:路由模块,配置的就是你和前端相交互的接口。
  • views:视图模块,包括了一些基础的请求渲染视图。.jade文件是一种模板引擎文件,通常用于创建HTML文档。它以简洁、缩进层次分明的方式来表示HTML标记和结构,是一种被称为Jade的模板语言的源文件格式。当请求的接口不存在或者发生错误的时候,就会调用这些视图。
  • app.js:express的入口程序,也是整个express的核心模块。app的主要功能有:
  • 注册第三方的Node.js插件。在创建express项目的时候,肯定要用到很多第三方的库里面提供的方法,这时候就需要先通过npm进行下载,之后在app.js里面进行引入,再通过app.use()进行注册。
  • 注册路由模块。引入routes里面写好的路由接口文件,通过app.use()进行注册并指定请求的url

文件改动时重启服务器

nodemon是最简便的自动化工具之一。通常将其全局安装

npm install -g nodemon

这里还可以把它作为开发依赖将安装在本地,于是使用这个项目的开发人员只要安装这个应用就能自动获得。通过以下命令将其安装在骨架项目的根目录:

npm install --save-dev nodemon

项目的 package.json 文件将自动添加一个新的属性:

  "devDependencies": {
    "nodemon": "^1.18.9"
  }

如果没有全局安装该工具,就无法从命令行启动它(除非我们将其添加到路径中),但是可以在 NPM 脚本中调用它,因为 NPM 掌握所有已安装包的信息。找到 package.json 的 scripts 部分。在 "start" 一行的末尾添加逗号,并在新的一行中添加 "devstart",如下所示:

  "scripts": {
    "start": "node ./bin/www",
    "devstart": "nodemon ./bin/www"
  },

现在可以用新建的 devstart 命令启动服务器:

npm run devstart

下载依赖

请求解析

body-parser是一个中间件,用于解析http请求的请求体(就是处理请求中的请求数据)

npm install body-parser

CORS跨域

npm install cors

数据库连接(mysql)

npm install --save mysql2

项目分层

Controllers

const UserService = require("../../service/admin/UserService")

const UserController = {
    login: async (req, res) => {
        console.log(req)
        var result = await UserService.login(req.body)
        if (result.length === 0) {
            res.send({
                code: "-1",
                error: "用户名密码不匹配"
            })
        } else {
            res.send({
                ActionType: "OK"
            })
        } 
    }
}
module.exports = UserController

Service

const { connectionQuery } = require("../../utils/connectionQuery");

const UserService = {
    login: async ({ username, password }) => {
        const searchSQL = `SELECT * FROM user WHERE username = "${username}" AND password = "${password}"`;
        return connectionQuery(searchSQL);
    }
}
module.exports = UserService

routers

var express = require('express');
const UserController = require('../../controllers/admin/UserController');
var UserRouter = express.Router();

UserRouter.post('/adminapi/login', UserController.login);

module.exports = UserRouter;

config(数据库及其配置)

配置文件

const dbConfig = {
    connectionLimit: 20, //最大连接数
    host: 'localhost', // 主机名称,一般是本机
    port: '3306', // 数据库的端口号,如果不设置,默认是3306
    user: 'root', // 创建数据库时设置用户名
    password: '****', // 创建数据库时设置的密码
    database: 'AdminSystem',  // 创建的数据库
    connectTimeout: 5000 // 连接超时
}

module.exports = dbConfig;

数据库连接池

var mysql = require('mysql2');
var dbConfig = require('./db.config');

const pool = mysql.createPool({ //创建一个数据库连接实例
  connectionLimit: dbConfig.connectionLimit,
  host: dbConfig.host,//这里是ip主机地址,因为此次示例中我们都是本地项目启动,包括数据库也是本地的,所以直接在这里使用localhost
  user: dbConfig.user, //数据库用户名称
  password: dbConfig.password, //数据库用户密码
  port: dbConfig.port, //数据库端口
  database: dbConfig.database, //数据库表名称
  connectTimeout: dbConfig.connectTimeout, //连接超时
});
const repool = () => {//创建一个函数,函数中的代码功能时启动连接数据库并监听是否连接成功
  pool.on('connection', () => {
    console.log('someone connected!');
  });
};
module.exports = { pool, repool }

utils

封装数据库函数connectionQuery.js

//对执行sql语句的方法进行封装
const {pool} = require('../config/db') //引入数据库配置文件中的数据库实例
const connectionQuery = (sql) => {
    return new Promise((resolve, reject) => {
        pool.getConnection((err, conn) => {
            if (err) {
                resolve(err);//错误的回调,返回错误信息
            }
            conn.query(sql, (err, result) => { //执行查数据库查询
                conn.release();//释放数据连接,以免占用过多的资源导致系统崩溃或者运行缓
                if (err) {
                    reject(err);//以免占用过多的资源导致系统崩溃或者运行缓
                }
                resolve(result);//成功的回调,返回从数据库拿到的数据
            });
        });
    });
};
module.exports = {connectionQuery};//导出执行sql的方法

app.js 配置

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var bodyParser = require('body-parser');
const cors = require('cors');
const {repool} = require('./config/db')

const UserRouter = require('./routes/admin/UserRouter');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(cors());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())

app.use(UserRouter)
// 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');
});

repool(); // 连接数据库

module.exports = app;

.gitignore文件的书写

根目录下新建.gitignore

# Build and Release Folders
# 忽略不上传更新的文件
bin-debug/
bin-release/
[Oo]bj/
[Bb]in/
node_modules/
dist/
static/
yarn-error.log
# Other files and folders
.settings/
#log file
*.log
*.lock
logs/
# Executables
.eslintcache
*.swf
*.air
*.ipa
*.apk
*.exe
# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
# should NOT be excluded as they contain compiler settings and other important
# information for Eclipse / Flash Builder.

VUE前端连接

在前端采用了封装接口api,axios二次封装来访问后端数据库。 以下以登录模块为例。

api文件夹下:

import httpInstance from '@/utils/http'
import type { LoginReq } from './models/UserModel'

export const doLoginAPI = (data:LoginReq) => {
    return httpInstance({
        url: '/adminapi/login',
        method: 'POST',
        data
    })
  }

utils文件夹下:

import axios from 'axios'

// 创建axios实例
const http = axios.create({
  baseURL: 'http://localhost:3000',
  timeout: 5000
})

// axios请求拦截器
http.interceptors.request.use(config => {
  return config
}, e => Promise.reject(e))

// axios响应式拦截器
http.interceptors.response.use(res => res.data, e => {
  return Promise.reject(e)
})


export default http