koa2学习笔记03 - 给koa2配置session ——koa2结构分层、配置数据库、接口
前言
这一章写的很没有底气,因为我完全不懂一个正经的后台应用是怎么结构分层的,
所有只能按照我自己的理解去写,即使这样也仅仅只分离出了controller层,
至于所谓的service层,dao层,完全不懂该怎么分离出来。
所以这一章仅供参考。如果有人能指点一下,不胜感激。
正文
数据库是采用的mysql,所以需要在本机安装一个mysql。
具体安装这里不多说了,请移步 菜鸟教程。
置于MySQL图形化管理工具推荐使用 navicat 或者 heidisql
1 安装依赖
npm install koa-session-minimal koa-mysql-session mysql --save
2 配置数据库和session
config 目录下新建 config.js 放置配置文件。
const database = {
    host: '127.0.0.1',			// 数据库地址,本机默认127.0.0.1
    port: 3306,					// 数据库默认端口
    database: 'koa2db',			// 数据库名字
    user: 'root',				// 数据库默认用户名
    password: 'XXXX'			// 你设置的数据库密码
}
module.exports = {
    database: database
}
改造根目录下的 app.js
//  配置session
app.use(session({
    key: 'USER_SID',
    store: new MysqlStore(mysqlConfig),
    cookie: {
        maxAge: 1000 * 60 * 60 * 24, // cookie有效时长
        overwrite: false
    }
}))
具体如图:

然后运行项目,看是否在数据库中自动创建了一个 _mysql_session_store 的表。 如果成功说明配置成功。

3 配置接口,分离controller
在目录 router 中新建 api 目录,放置各模块接口。再新建api.js作为 api的入口文件。
我们可以在里面加入一些测试接口,捕获不存在的接口、输出不存在的错误接口方便排查。
api.js
const router = require('koa-router')();
const user = require('./api/user.js');
router.prefix('/api');   // 统一定义接口前缀都为api, 之后写的所有接口都在api下。
user(router);
/* 测试接口 */
router.get('/', function (ctx, next) {
    ctx.body = {
        code: 0,
        data: null,
        msg: "接口请求成功",
        request: ctx.originalUrl
    }
})
/* 404 */
router.all('/*', function (ctx, next) {
    ctx.body = {
        code: 1001,
        ctx: ctx,
        data: null,
        msg: "接口不存在",
        request: ctx.originalUrl
    }
})
module.exports = router
// router.get()  ==>  仅仅get请求可以访问到接口
// router.post() ==>  仅仅post请求可以访问到接口
// router.all()  ==>  所有请求都可以访问到接口
定义好了接口的入口文件,我们先在
app.js引入

引入之后接下来配置接口的详细信息,在
routers中 新建api目录, 并在其中新建user.js
/**
 * 用户相关接口
 */
const user = require("../../controller/user.js")
module.exports = function(router) {
	router.all('/user/login', user.userLogin)
	router.all('/user/isLogin', user.isLogin)
}
根目录下新建目录
controller,controller下新建user.js, 此处暂不考虑密码明文传输安全性问题。
const { responseFormatter, getParams } = require("../utils/index.js") //	格式化输出方法、获取参数方法
const { logHandle } = require("../utils/logs.js") //  上一章记录操作日志的方法
const handleDB = require("../utils/handleDb.js") //  操作数据库方法
// 用户登录接口
async function userLogin(ctx, next) {
    var params = getParams(ctx.request)
    try {
        let sql = "select * from user where username=? and password=?"
        let data = await handleDB(sql, [params.username, params.password]);
        // 记录登录日志
        logHandle({
            title: '用户登录',
            sql,
            params,
            data
        });
        if (data.length) {
            // 存入session信息(最终会存在数据库中)
            ctx.session = {
                isLogin: true,
                userId: data[0].userId,
                userName: data[0].username,
                nickName: data[0].nickname
            }
            ctx.body = responseFormatter(0, '登录成功!');
        } else {
            ctx.body = responseFormatter(201);
        }
    } catch (err) {
        ctx.body = responseFormatter(103, err);
    }
}
// 检测用户是否登录接口
async function isLogin(ctx, next) {
    if (ctx.session && ctx.session.isLogin) {
        ctx.body = responseFormatter(0, {
            nickName: ctx.session.nickName
        });
    } else {
        ctx.body = responseFormatter(202);
    }
}
module.exports = {
    isLogin,
    userLogin
}
utils目录下的index.js
/**
 * @name responseFormatter   格式化输出响应结果
 * @params { @Number 状态码, @Object 返回数据}
 * @return { @Object }
 * @author HoChine.
 */
const errorCode = require("../config/errorCode.js")
exports.responseFormatter = function (code, data) {
    return {
        code: code,
        msg: errorCode[code],
        data: data || null
    }
}
/**
 * @name getParams 获取url参数
 * @params { @String url}
 * @return { @Object }
 * @author HoChine.
 */
let getUrlParams = function (url) {
    let paramsList = {};
    if (!url) {
        console.log("url 为必填项");
        return paramsList;
    }
    let paramsStr = url.split("?")[1];
    let params = paramsStr ? paramsStr.split("&") : [];
    params.forEach(function (item) {
        let temp = item.split("=");
        temp[0] ? paramsList[temp[0]] = temp[1] : '';
    })
    return paramsList;
}
exports.getUrlParams = getUrlParams
/**
 * @name getParams 根据请求方式不同获取参数
 * @params { @Object ctx.request}
 * @return { @Object }
 * @author HoChine.
 */
exports.getParams = function (request) {
    if (request.method === "GET") {
        return getUrlParams(request.url)
    }else{
        return request.body
    }
}
utils目录下的handleDb.js。 database为上面的数据库配置文件
onst mysql = require('mysql')
const { database } = require('../config/config');
const pool = mysql.createPool(database);
module.exports = function(sql, values) {
    return new Promise((resolve, reject) => {
        pool.getConnection(function(err, connection) {
            if (err) {
                reject(err)
            } else {
                connection.query(sql, values, (err, rows) => {
                    if (err) {
                        reject(err)
                    } else {
                        resolve(rows)
                    }
                    connection.release()
                })
            }
        })
    })
}
utils中index.js所引入的errorCode.js
/*  错误码1-2位按服务端业务模块区分
 *  01. 接口相关 (参数不全等,参数有误)
 *  02. user相关
 *  03. blog相关
*/
/*  错误码3-4位按具体错误情况排列
 *  01.
 *  02.
*/
module.exports = {
    0: 'success',
    101: '缺少必须参数!',
    102: '参数有误!',
    103: '接口异常',
    201: '用户不存在!',
    202: '用户未登录或已过期!',
    203: '用户名或密码错误,请重试!',
    220: '抱歉,您没有权限!',
    9999: '未知错误!'
};
最后配置一下数据库 随意新增一条数据。

至此,接口、session、数据库配置基本上配置好了。
4 前台页面验证
view目录下的 index.html (是我不知道在哪抄来的一个登录模块样式)
<!DOCTYPE HTML>
<html>
<head>
    <title>Home</title>
    <link href="/stylesheets/style.css" rel="stylesheet" />
</head>
<body>
    <div class="login" style="display:none">
        <h2>商家登录 </h2>
        <div class="login-top">
            <h1>登录</h1>
            <form>
                <input type="text" id="username" placeholder="用户名" value="admin">
                <input type="password" id="password" placeholder="******" value="admin">
            </form>
            <div class="forgot">
                <a href="#">忘记密码?</a>
                <input type="button" id="login" value="登录">
            </div>
        </div>
        <div class="login-bottom">
            <h3>400-000-0000</h3>
        </div>
    </div>
    <div class="logined" style="display:none"></div>
</body>
<script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script>
<script src="/javascripts/index.js"></script>
</html>
public中的stylesheets样式文件,具体可以github上复制,放这里太占篇幅 。 style.css点这里
public中的javascripts登录逻辑随便写写,不要深究写的SB不SB,只是测试接口用。
$(function() {
	isLogin()
	function isLogin() {
		$.get("http://localhost:3000/api/user/isLogin", function(res) {
			console.log(res);
			if (res.code) {
				$(".login").show();
				login()
			} else {
				$(".logined").show().text("hello, " + res.data.nickName)
			}
		})
	}
	function login() {
		$("#login").on("click", function() {
			var username = $("#username").val();
			var password = $("#password").val();
			if (username && password) {
				$.post("http://localhost:3000/api/user/login", {
					username: username,
					password: password
				}, function(res) {
					console.log(res);
					if(!res.code){
						alert(res.data);
						location.reload();
					}
				})
			} else {
				alert("用户名或密码为空")
			}
		})
	}
})
作者 HoChine
2019 年 04月 16日
GitHub地址:https://github.com/HoChine/Koa2-demo/tree/03
koa2学习笔记03 - 给koa2配置session ——koa2结构分层、配置数据库、接口的更多相关文章
- Redis:学习笔记-03
		Redis:学习笔记-03 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 7. Redis配置文件 启动 ... 
- 机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理、源码解析及测试
		机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理.源码解析及测试 关键字:决策树.python.源码解析.测试作者:米仓山下时间:2018-10-2 ... 
- OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓
		本节代码使用的opencv-python 4.0.1,numpy 1.15.4 + mkl 使用图片为 Mjolnir_Round_Car_Magnet_300x300.jpg 代码如下: impor ... 
- OpenCV 学习笔记03 findContours函数
		opencv-python 4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ... 
- C++ GUI Qt4学习笔记03
		C++ GUI Qt4学习笔记03 qtc++spreadsheet文档工具resources 本章介绍创建Spreadsheet应用程序的主窗口 1.子类化QMainWindow 通过子类化QM ... 
- ZooKeeper学习笔记三:使用ZooKeeper实现一个简单的配置中心
		作者:Grey 原文地址:ZooKeeper学习笔记三:使用ZooKeeper实现一个简单的配置中心 前置知识 完成ZooKeeper集群搭建以及熟悉ZooKeeperAPI基本使用 需求 很多程序往 ... 
- SaToken学习笔记-03
		SaToken学习笔记-03 如果排版有问题,请点击:传送门 核心思想 所谓权限验证,验证的核心就是一个账号是否拥有一个权限码 有,就让你通过.没有?那么禁止访问! 再往底了说,就是每个账号都会拥有一 ... 
- JavaWeb和WebGIS学习笔记(七)——MapGuide Open Source安装、配置以及MapGuide Maestro发布地图——超详细!目前最保姆级的MapGuide上手指南!
		JavaWeb和WebGIS学习笔记(七)--MapGuide Open Source安装.配置以及MapGuide Maestro发布地图 超详细!目前最保姆级的MapGuide上手指南! 系列链接 ... 
- 【Unity Shaders】学习笔记——SurfaceShader(二)两个结构体和CG类型
		[Unity Shaders]学习笔记——SurfaceShader(二)两个结构体和CG类型 转载请注明出处:http://www.cnblogs.com/-867259206/p/5596698. ... 
随机推荐
- Java学习笔记(5)----使用正则表达式解决Google Code Jam Qualification2009赛题 Alien Language
			原题地址:https://code.google.com/codejam/contest/90101/dashboard#s=p0 题目描述: Problem After years of study ... 
- 阿里,百度,腾讯招聘 Java 程序员的技术标准
			阿里巴巴篇 扎实的计算机专业基础,包括算法和数据结构,操作系统,计算机网络,计算机体系结构,数据库等 具有扎实的Java编程基础,理解IO.多线程等基础框架 熟练使用Linux系统的常用命令及shel ... 
- 【分享】BS大神的C++ 11 keynotes
			看到infoQ上面有BS大神的keynotes讲C++ 11的,有点长,但是值得一看. http://www.infoq.com/presentations/Cplusplus-11-Bjarne ... 
- sql随机时间
			declare @endtime datetime declare @starttime datetime set @starttime='2017-09-01' set @endtime = '20 ... 
- 消除 Xcode7 中 directory not found for option 'xxxx' 警告
			消除 Xcode7 中 directory not found for option 'xxxx' 警告 升级Xcode7之后,你会遇到一些警告信息,诸如以下一条: ld: warning: dire ... 
- linux 下安装ant
			1.下载 下载地址:http://ant.apache.org/bindownload.cgi 2.解压 cd /home/work/ant/ tar -zxvf apache-ant-1.8 ... 
- Win10系统创建关机快捷方式和快捷键的方法,实现一键关机
			想不想关机变得更加简单?在Win10中总有些朋友想要快速的操作体验,所以关机这个经常使用的功能也被设置的更简单,下面小编要分享的是“Win10系统创建关机快捷方式和快捷键的方法”. 1.在win10下 ... 
- 沉淀,再出发:jQuery的初步了解和入门
			沉淀,再出发:jQuery的初步了解和入门 一.前言 对于后端开发者来说,是不是真的不需要了解前端的开发经过和相关技术,从我个人的角度来说,我觉得如果不了解或者接触很少,极有可能造成开发的时候 ... 
- 组合数计算-java
			排列组合是计算应用经常使用的算法,通常使用递归的方式计算,但是由于n!的过于大,暴力计算很不明智.一般使用以下两种方式计算. 一,递归的思想:假设m中取n个数计算排列组合数,表示为comb(m,n). ... 
- 015.1 Lock接口
			内容:Lock接口使用步骤,同步生产大白兔奶糖的例子 同步代码块的锁是隐式的,显式容易让我们理解.所以我们使用这个显式的方法,方便理解代码.######实现同步步骤:1.获取锁:lock()2.同步代 ... 
 
			
		