从零搭建一个全栈项目(二)—— 接口调试

1,847 阅读6分钟

一、内容简介

本章主要实现前后端接口调试:前端可以通过axios调用后端接口,返回数据库(mysql)中的数据的基本功能。由于大部分的功能接口会在后面单独详细说明,所以这章只实现一个测试接口。

二、接口结构搭建

上一章已经实现node启动后端服务,当时在http.createServer() 中有一个回调函数serverHandle:

/server/app.js

const handleBlogRouter = require('./router/blog')
const handleUserRouter = require('./router/user')
const mime = require('./util/mime')

const serverHandle = (req, res) => {
  const url = req.url
  res.setHeader('Content-type', mime(url))
  req.path = url.split('?')[0]
  const blogData = handleBlogRouter(req, res)
  const userData = handleUserRouter(req, res)
  if (url.match('api')) {
    if (blogData) {
      blogData.then(data => {
        res.end(JSON.stringify(data))
      })
      return
    }
    if (userData) {
      userData.then(data => {
        res.end(JSON.stringify(data))
      })
      return
    }
  }
  res.end()
}

module.exports = serverHandle

在serverHandle中我们可以通过判断req.path来判断不同类型的接口,这里我加了url.match('api')来校验路径中是否含有api,如果有则证明是请求接口的路径,假如后面有其他功能可以在else中补充。假如请求路径命中了blog.js或者说blogData有对应返回,则直接给前端返回blogData返回的值。
可以看到对应的blogData对应了一个方法,这是因为可能我们的接口有不同类型,为了方便后续维护,使代码结构更清晰,所以新建了一个router文件夹,在这个文件夹中可以根据不通的类型来分成几个不同的模块,比如:blog.js、user.js等。这里我们就用blog.js中获取博客列表接口举例:

/server/router/blog.js

const { getList } = require('../controller/blog')
const { SuccessModel, ErrorModel } = require('../model/index')

const handleBlogRouter = (req, res) => {
  const method = req.method
  // 获取博客列表
  if (method === 'GET' && req.path === '/api/blog/list') {
    return getList().then(list => {
      return new SuccessModel(list)
    })
  }
}

module.exports = handleBlogRouter

getList实际上就是通过sql语句获取博客列表的一个方法,直接返回数据库数据,这里我们后面详细说明,假如我们请求的path为/api/blog/list并且是get请求,那么就说明我们是博客列表接口,getList返回了一个列表数组list,可以看到我并不是直接将list直接返回到前端,而是通过SuccessModel, ErrorModel来对数据进行一个封装,这是由于通常我们请求接口都会有code,如果code为0证明返回成功,否则说明失败,所以我们也专门写了两个方法,对数据库的数据进行了一次封装:

/server/model/index.js

class BaseModel {
  constructor (data, message) {
    if (typeof data === 'string') {
      this.message = data
      data = null
      message = null
    }
    if (data) {
      this.data = data
    }
    if (message) {
      this.message = message
    }
  }
}

class SuccessModel extends BaseModel {
  constructor (data, message) {
    super(data, message)
    this.code = 0
  }
}

class ErrorModel extends BaseModel {
  constructor (data, message) {
    super(data, message)
    this.code = -1
  }
}

module.exports = {
  SuccessModel,
  ErrorModel
}

SuccessModel, ErrorModel实际就是简单的对数据进行了封装,data是实际数据,code判断接口是否请求成功。到这里我们后端接口的逻辑就已经基本完成了。下面就是后端通过node链接mysql和使用简单的sql语句获取数据库数据。

三、接口数据获取

首先,要在项目中安装mysql:npm install mysql。 在自己电脑上也需要安装mysql和一个可视化的mysql工具,我安装的可视化工具是workbench,官网都有相关的下载,就不多介绍了。
安装好mysql之后,我们可以打开workbench,点击图中标记按钮新建一个数据库myblog

新建数据库后可以再新建一个blogs表:

然后编辑表,可以添加一些自定义的字段,我目前添加的都是一些比较常用的字段:文章id,标题,内容,创建时间,作者等。

新建完成后可以执行一条简单的sql语句添加一条数据:
use myblog;
insert into blogs (title, content, createtime, author) values ('博客标题', '博客内容', '123', 'lisi');
select * from blogs;

单独选中某一行点击也可以只执行那一行语句,这是应该会看到数据库blogs表的数据:
到这里后说明数据库中已经存了几条数据,在我们的服务端代码可以链接数据库获取这几条数据:
连接接数据库:

/server/db/mysql.js

const mysql = require('mysql')
const { MYSQL_CONF } = require('../conf/db')

// 创建链接对象
const con = mysql.createConnection(MYSQL_CONF)

// 开始链接
con.connect()

// 统一执行sql函数
function exec(sql) {
  return new Promise((resolve, reject) => {
    con.query(sql, (err, res) => {
      if (err) {
        reject(err)
        return
      }
      resolve(res)
    })
  })
}

module.exports = {
  exec
}

// MYSQL_CONF mysql的相关配置
const env = process.env.NODE_ENV // 环境参数

let MYSQL_CONF
// 开发环境下
if (env === 'dev') {
  MYSQL_CONF = {
    host: 'localhost',
    user: 'root',
    password: 'selfpassword',
    port: '3306',
    database: 'myblog'
  }
}
// 生产环境下
if (env === 'production') {
  MYSQL_CONF = {
    host: 'localhost',
    user: 'root',
    password: 'selfpassword',
    port: '3306',
    database: 'myblog'
  }
}

module.exports = {
  MYSQL_CONF
}
其中password为自己设置的密码

这部分为一个封装的执行sql语句的方法和mysql相关的配置。下面回到之前说的getList获取博客列表的方法:

/server/controller/blog.js

const { exec } = require('../db/mysql')
const getList = () => {
  // 返回假数据
  const sql = 'select * from blogs;'
  return exec(sql)
}

module.exports = {
  getList
}

select * from blogs; 就是博客列表中需要获取数据库数据的sql语句,当然后面如果有筛选搜索等功能,这个sql语句会相应修改,目前是一个最简单的语句用于测试我们的数据库是否已经连接成功。
现在我们可以试一下,运行我们的服务端代码,npm run server, 在浏览器输入: http://localhost:3000/api/blog/list, 看下数据库中的数据是否返回:

看到我们的接口已经可以返回数据库的博客列表了。

四、前端调试接口

现在我们要准备调试前端请求,前端的解决就更容易了,首先我们的前端代码是在80端口,直接使用axios会跨域,直接在webpack的devServer中设置proxy代理即可:

  devServer: {
    contentBase: path.resolve(__dirname, '../dist'),
    historyApiFallback: true,
    port: 8080,
    inline: true,
    hot: true,
    host: 'localhost',
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: {'^/' : ''}
      }
    }
  }

然后我们在/pages/blog/index.js中写一个简单的请求方法即可:

import './index.css'
import axios from 'axios'
axios
  .get('/api/blog/list')
  .then(function(response) {
    console.log(response)
  })
  .catch(function(error) {
    console.log(error)
  })

就是这么最简单的axios语法即可,因为我们目前只是把前后端请求接口的逻辑调试清楚,代码相关的优化还没有做,所以在这个js中直接写了axios原生的方法来测试,后面可能会封装成一个请求方法。
现在我们运行一下项目, npm run start, 打开http://localhost:8080/html/blog.html

已经可以看到前端console出了博客列表数据。

五、总结

本章介绍了后端如何连接数据库,并通过接口返回给前端数据;前端如何调试接口获取后端数据:

  1. 后端构建接口接口,规定接口路径;
  2. 后端连接mysql数据库,通过sql语句获取数据;
  3. 前端调用接口获取后端数据;

下一章主要内容:
1.优化前端公用代码(js、css);
2.实现项目登录注册功能;

六、最后

GitHub地址:戳这里

本项目仅为学习交流使用,如果有小伙伴有更好的建议欢迎提出来大家一起讨论,另外感兴趣的小伙伴就点个star吧! ^_^