zoukankan      html  css  js  c++  java
  • koa2学习笔记03

    前言

    这一章写的很没有底气,因为我完全不懂一个正经的后台应用是怎么结构分层的,
    所有只能按照我自己的理解去写,即使这样也仅仅只分离出了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
        }
    }))
    

    具体如图:
    配置session
    然后运行项目,看是否在数据库中自动创建了一个 _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

  • 相关阅读:
    [Jenkins]admin用户登陆,提示登陆无效(之前登陆OK,三天没有登陆,突然提示登陆无效,重启无法解决)的解决方法
    科普技术贴:个人开发者的那些赚钱方式
    赚钱必看:独立开发者必知的一些总结
    【转】微信小程序给程序员带来的可能是一个赚钱的机遇
    20个编写现代 CSS 代码的建议
    Python爬虫入门一之综述
    Python学习基础知识概要
    文本框输入邮箱自动联想补全
    鼠标移到图片放大效果
    网站banner无缝轮播
  • 原文地址:https://www.cnblogs.com/HoChine/p/10717840.html
Copyright © 2011-2022 走看看