前言

这一章写的很没有底气,因为我完全不懂一个正经的后台应用是怎么结构分层的,

所有只能按照我自己的理解去写,即使这样也仅仅只分离出了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()
})
}
})
})
}

utilsindex.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结构分层、配置数据库、接口的更多相关文章

  1. Redis:学习笔记-03

    Redis:学习笔记-03 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 7. Redis配置文件 启动 ...

  2. 机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理、源码解析及测试

    机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理.源码解析及测试 关键字:决策树.python.源码解析.测试作者:米仓山下时间:2018-10-2 ...

  3. OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓

    本节代码使用的opencv-python 4.0.1,numpy 1.15.4 + mkl 使用图片为 Mjolnir_Round_Car_Magnet_300x300.jpg 代码如下: impor ...

  4. OpenCV 学习笔记03 findContours函数

    opencv-python   4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ...

  5. C++ GUI Qt4学习笔记03

    C++ GUI Qt4学习笔记03   qtc++spreadsheet文档工具resources 本章介绍创建Spreadsheet应用程序的主窗口 1.子类化QMainWindow 通过子类化QM ...

  6. ZooKeeper学习笔记三:使用ZooKeeper实现一个简单的配置中心

    作者:Grey 原文地址:ZooKeeper学习笔记三:使用ZooKeeper实现一个简单的配置中心 前置知识 完成ZooKeeper集群搭建以及熟悉ZooKeeperAPI基本使用 需求 很多程序往 ...

  7. SaToken学习笔记-03

    SaToken学习笔记-03 如果排版有问题,请点击:传送门 核心思想 所谓权限验证,验证的核心就是一个账号是否拥有一个权限码 有,就让你通过.没有?那么禁止访问! 再往底了说,就是每个账号都会拥有一 ...

  8. JavaWeb和WebGIS学习笔记(七)——MapGuide Open Source安装、配置以及MapGuide Maestro发布地图——超详细!目前最保姆级的MapGuide上手指南!

    JavaWeb和WebGIS学习笔记(七)--MapGuide Open Source安装.配置以及MapGuide Maestro发布地图 超详细!目前最保姆级的MapGuide上手指南! 系列链接 ...

  9. 【Unity Shaders】学习笔记——SurfaceShader(二)两个结构体和CG类型

    [Unity Shaders]学习笔记——SurfaceShader(二)两个结构体和CG类型 转载请注明出处:http://www.cnblogs.com/-867259206/p/5596698. ...

随机推荐

  1. input button 与 submit 的区别

    在表单中,我们会经常提交数据,通常使用<input type="submit" value="提交"/>进行提交数据, 另一种方式是使用<bu ...

  2. Exception in thread "main" java.lang.UnsatisfiedLinkError: no awt in java.library.path:

    Exception in thread "main" java.lang.UnsatisfiedLinkError: no awt in java.library.path: 这是 ...

  3. 浏览器缓存(Web Cache/ Http Cache)

    浏览器缓存(Web Cache/ Http Cache)是前端性能优化中很重要的组成部分. 缓存策略 浏览器的缓存策略是: 1.如果本地没有缓存,则发送非条件性请求. 2.如果本地有缓存,则判断本地缓 ...

  4. Netty高性能web框架

    框架背景: 前期为公司项目做全链路压测,发现公司跑到tomcat上的服务,即使是最简单的方法QPS也就到3000左右,后期查询发现可能和tomcat的业务逻辑有关. 因为以前在项目开发中用netty做 ...

  5. 解决nginx使用proxy_pass反向代理时,session丢失的问题

       这2天在测试Nginx作为反向代理到Tomcat应用时,session丢失的问题.经过一系列查看官方文档和测试,发现如下:1.如果只是host.端口转换,则session不会丢失.例如:     ...

  6. Angular5中提取公共组件之radio list

    上一篇说到了Checkbox List的公共组件提取,现在说一下Radio List的公共组件提取. Radio List组件提取起来很方便,不想Checkbox那么复杂. radio-list.co ...

  7. linux下安装rar以及rar相关命令参数详解

    Linux平台默认是不支持RAR文件的解压,需要安装Linux版本的RAR压缩软件,下载地址:http://www.rarlab.com/download.htm 下载之后进行解压之后,进入rar目录 ...

  8. Python学习---range/for/break/continue简单使用

    range的使用:注意,在python3中,交互模式下已经不显示了 for循环的使用 打印50-70 # 第一种方案 for i in range(100): if i <= 70 and i ...

  9. 5 Dockerfile指令详解 && CMD 指令

    CMD 指令的格式和 RUN 相似,也是两种格式: shell 格式: CMD <命令> exec 格式: CMD ["可执行文件", "参数1", ...

  10. html禁用缓存

    <!-- 禁用缓存 --><meta http-equiv="pragma" content="no-cache"><META H ...