合欢树适合什么时候种植? 当前位置:首页>合欢树适合什么时候种植?>正文

合欢树适合什么时候种植?

发布时间:2019-05-20

原标题:Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例

目录

前言

  前面一有写到一篇Node.js+Express构建网站简单示例:http://www.cnblogs.com/zhongweiv/p/nodejs_express_webapp.html

  这篇还是用以前的例子, 用Node.js+Koa2构建

 

  Koa:   https://github.com/koajs/koa

       http://koa.bootcss.com  (中文)

 

  Koa就不多介绍了,前面也写过Express,同一个团队打造,前面也过express文章,对比着看,自然可以看出些优点!

 

搭建项目及其它准备工作

创建数据库

CREATE DATABASE IF NOT EXISTS nodesample CHARACTER SET UTF8;

USE nodesample;

SET FOREIGN_KEY_CHECKS=0;

DROP TABLE IF EXISTS `userinfo`;
CREATE TABLE `userinfo` (
  `Id` int(11) NOT NULL AUTO_INCREMENT COMMENT "主键",
  `UserName` varchar(64) NOT NULL COMMENT "用户名",
  `UserPass` varchar(64) NOT NULL COMMENT "用户密码",
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT="用户信息表";

创建Koa2项目

  安装koa-generator:  https://github.com/17koa/koa-generator

npm install -g koa-generator

 安装成功后下图(版本:1.1.16)

 

 然后创建Koa2项目,安装相关依赖项

cd 工作目录
koa2 项目名
cd 项目目录 && npm install

安装项目其它需要包

1.安装使用MySQL需要的包

npm install --save mysql

 没有使用过的可以看我以前写的相关操作文章:http://www.cnblogs.com/zhongweiv/p/nodejs_mysql.html

 2.安装ejs(koa2默认为jade,我习惯使用ejs)

npm install --save ejs

没有使用过的可以看我以前写的相关操作文章:http://www.cnblogs.com/zhongweiv/p/nodejs_express.html

3.安装Session存储相关包(存储到redis)

npm install koa-session  https://github.com/koajs/session

npm install --save koa-session

koa-session-redis https://github.com/Chilledheart/koa-session-redis

npm install --save koa-session-redis

清除冗余文件并重新规划项目目录

 1.删除掉创建项目后自带的views和routes下的文件

 2.重新规划项目目录,规划后如下

目录规则解释:

1.新增pub目录:主要为了统一存放"数据访问"、"业务逻辑"、"公共方法文件"、"数据库帮助文件"、"配置文件"等

2.新增pub目录下utils目录:主要为了统一存放类似"公共函数文件"、"返回值文件"、"枚举文件"等公共文件

3.新增pub目录下config目录:主要为了统一存放各种类型的配置文件

4.新增pub目录下db目录:主要为了统一存放各种数据库帮助类,比如:"mysql-helper.js"、"mongo-helper.js"等等

5.新增pub目录下model目录:主要为了统一存放各种数据库各表CURD操作

6.新增pub目录下bll目录:主要为了统一存放各种业务逻辑的具体实现

配置文件

 从上面的图可以看出,我在pub下新建的config目录下新建了一个config.js

 这个config.js中将编写“开发环境”和“发布环境”中所需的配置,代码如下

/**
 * 配置文件
 */
//发布配置
const production = {

    //服务器端口
    SERVER_PORT : 3000,

    //REDIS配置
    REDIS: {
        host: "localhost",            
        port: 6379,
        password: "abcd",
        maxAge: 3600000
    },

    //MYSQL数据库配置
    MYSQL: {
        host: "localhost",
        user: "root",
        password: "abcd",
        port: "3306",
        database: "nodesample",
        supportBigNumbers: true,
        multipleStatements: true,
        timezone: "utc"
    }

}

//开发配置
const development = {

    //服务器端口
    SERVER_PORT : 3000,

    //REDIS配置
    REDIS: {
        host: "localhost",            
        port: 6379,
        password: "abcd",
        maxAge: 3600000
    },

    //MYSQL数据库配置
    MYSQL: {
        host: "localhost",
        user: "root",
        password: "abcd",
        port: "3306",
        database: "nodesample",
        supportBigNumbers: true,
        multipleStatements: true,
        timezone: "utc"
    }

}

const config = development

module.exports = config

规划示例路由,并新建相关文件

 示例中将有注册、登录功能,先规划好路由,新建routes、views下的相关需要的文件(如项目目录图中文件),并修改app.js文件

const Koa = require("koa")
const app = new Koa()
const views = require("koa-views")
const json = require("koa-json")
const onerror = require("koa-onerror")
const bodyparser = require("koa-bodyparser")
const logger = require("koa-logger")

const config = require("./pub/config/config.js");
const session = require("koa-session");
const RedisStore = require("koa2-session-redis");

const index = require("./routes/index")
const reg = require("./routes/reg")
const login = require("./routes/login")
const logout = require("./routes/logout")

// error handler
onerror(app)

// middlewares
app.use(bodyparser({
  enableTypes:["json", "form", "text"]
}))
app.use(json())
app.use(logger())
app.use(require("koa-static")(__dirname + "/public"))

app.use(views(__dirname + "/views", {
  extension: "ejs"
}))

// logger
app.use(async (ctx, next) => {
  const start = new Date()
  await next()
  const ms = new Date() - start
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
})

app.keys = ["Porschev"];
const redis_conf = {  
  key: "Porschev",
  maxAge: config.REDIS.maxAge,
  overwrite: true,
  httpOnly: true,  
  rolling: false,
  sign: true,
  store: new RedisStore({
    host: config.REDIS.host,
    port: config.REDIS.port,    
    password: config.REDIS.password    
  })
};

app.use(session(redis_conf, app));

// routes
app.use(index.routes(), index.allowedMethods())
app.use(reg.routes(), reg.allowedMethods())
app.use(login.routes(), login.allowedMethods())
app.use(logout.routes(), logout.allowedMethods())

// error-handling
app.on("error", (err, ctx) => {
  console.error("server error", err, ctx)
});

app.listen(config.SERVER_PORT, () => {
  console.log(`Starting at port ${config.SERVER_PORT}!`)
});

module.exports = app

注意看红色标记修改或增加的部分

实现数据访问和业务逻辑相关方法

 1.首先编写一个mysql-helper.js方便以连接池的方式进行操作

const config = require("./../config/config.js")
const mysql = require("mysql")

const pool = mysql.createPool(config.MYSQL)
  
let query = function(sql, args) {
  
    return new Promise((resolve, reject) => {
        pool.getConnection(function(err, connection) {
            if (err) {
                resolve(err)
            } else {
                connection.query(sql, args, (err, result) => {
        
                    if (err) {
                        reject(err)
                    } else {
                        resolve(result)
                    }
                    connection.release()

                })
            }
        })
    })
  
}

module.exports = { 
    query 
}

2.编写数据访问相关方法(model目录下的userinfo.js),如下

const mysqlHelper = require("./../db/mysql-helper.js")

const userinfo = {

  /**
   * 增加一条数据
   * @param  {object} args  参数
   * @return {object}       结果
   */
  async add ( args ) {
    let sql = "INSERT INTO userinfo(UserName, UserPass) VALUES(?, ?)"
    let params = [args.username, args.userpass]
    let result = await mysqlHelper.query(sql, params)
    return result
  },

  /**
   * 根据UserName得到一条数据
   * @param  {object} args  参数
   * @return {object}       结果
   */
  async getByUserName( args ){
    let sql = "SELECT Id, UserName, UserPass FROM userinfo WHERE UserName = ?"
    let params = [args.username]
    let result = await mysqlHelper.query(sql, params)
    return result
  },

   /**
   * 根据UserName得到数量
   * @param  {object} args  参数
   * @return {object}       结果
   */
  async getCountByUserName( args ){
    let sql = "SELECT COUNT(1) AS UserNum FROM userinfo WHERE UserName = ?"
    let params = [args.username]
    let result = await mysqlHelper.query(sql, params)
    return result
  },

}

module.exports = userinfo

3.在写业务逻辑之前先规划好返回值(utils目录下retcode.js)

/*
 * 返回码
 */
const RetCode = {
    SessionExpired: -1,             //session过期
    Fail: 0,                        //失败
    Success: 1,                     //成功
    ArgsError: 2,                   //参数错误
    UserExisted: 10,                //用户已经存在
    UsernameOrPasswordError: 11,    //用户名或者密码错误      
    UserNotExist: 12,               //用户不存在    
};

module.exports = RetCode
retcode.js

4.编写“登录”、“注册”等业务逻辑(bll下userinfo.js)

const usermodel = require("./../model/userinfo.js")
const retCode = require("./../utils/retcode.js")

const userinfo = {

  /**
   * 注册
   * @param  {object} ctx   上下文
   * @return {object}       结果
   */
  async register ( ctx ) {
    let form = ctx.request.body
    
    const args = {
        username: form.username,
        userpass: form.userpass
    }
        
    let result = {
        code: retCode.Success,    
        data: null
    }
    
    //验证非空
    if(!args.username || !args.userpass){
        result.code = retCode.ArgsError        
        return result
    }

    //根据用户名得到用户数量
    let userNumResult = await usermodel.getCountByUserName(args)

    //用户名已被注册
    if(userNumResult[0].UserNum > 0){
        result.code = retCode.UserExisted        
        return result
    }

    //插入注册数据
    let userResult = await usermodel.add(args)

    if(userResult.insertId <= 0){
        result.code = retCode.Fail        
        return result
    }

    return result
  },

  /**
   * 登录
   * @param  {object} ctx   上下文
   * @return {object}       结果
   */
  async login ( ctx ) {
    let form = ctx.request.body
    
    const args = {
        username: form.username,
        userpass: form.userpass
    }
        
    let result = {
        code: retCode.Success,    
        data: null
    }
    
    //验证非空
    if(!args.username || !args.userpass){
        result.code = retCode.ArgsError        
        return result
    }

    //根据用户名得到用户信息
    let userResult = await usermodel.getByUserName(args)

    //用户不存在
    if(userResult.length == 0){
        result.code = retCode.UserNotExist        
        return result
    }
    
    //用户名或密码错误
    if(userResult[0].UserName != args.username || userResult[0].UserPass != args.userpass){
        result.code = retCode.UsernameOrPasswordError        
        return result
    }

    //将用户ID存入Session中
    ctx.session = {id: userResult[0].Id}

    return result
  },

}

module.exports = userinfo

注册

1.views目录下reg.ejs

<html>
<head>
<title>Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例</title>
</head>
<body>
<h1><%= title %></h1>
登录名:<input type="text" id="txtUserName" maxlength="20" />
<br/>
<br/>
密码:<input type="password" id="txtUserPwd" maxlength="12" />
<br/>
<br/>
密码:<input type="password" id="txtUserRePwd" maxlength="12" />
<br/>
<br/>
<input type="button" id="btnSub" value="注册" />
</body>
</html>

<script src="/javascripts/jquery-1.11.2.min.js" type="text/javascript"></script>
<script src="/javascripts/md5.js" type="text/javascript"></script>

<script type="text/javascript">   
    $(function(){
        $("#btnSub").on("click", function(){
            var $txtUserName = $("#txtUserName"),
                txtUserNameVal = $.trim($txtUserName.val()),
                $txtUserPwd = $("#txtUserPwd"),
                txtUserPwdVal = $.trim($txtUserPwd.val()),
                $txtUserRePwd = $("#txtUserRePwd"),
                txtUserRePwdVal = $.trim($txtUserRePwd.val());
                       
            if(txtUserNameVal.length == 0){
                alert("用户名不能为空");                
                return false;
            }

            if(txtUserPwdVal.length == 0){                
                alert("密码不能为空");                
                return false;
            }

            if(txtUserRePwdVal.length == 0){
                alert("重复密码不能为空");   
                return false;
            }

            if(txtUserPwdVal != txtUserRePwdVal){                 
                alert("两次密码不一致");                 
                return false;
            }

            $.ajax({
                url: "/reg",
                type: "POST",
                dataType: "json",
                data: {
                    username: txtUserNameVal,                    
                    userpass: hex_md5(txtUserPwdVal)                                        
                },
                beforeSend: function (xhr) {},
                success: function (res) {
                    if (res != null && res.code) {

                        var retVal = parseInt(res.code);

                        switch (retVal) {
                            case 2:
                                alert("输入有误");
                                break;
                            case 0:
                                alert("注册失败");
                                break;
                            case 1:
                                alert("注册成功!");
                                location.href = "/login"                                
                                break;
                            case 10:
                                alert("用户已注册");
                                break;                         
                        }
                    }
                    else {
                        alert("操作失败");
                    }

                },
                complete: function (XMLHttpRequest, textStatus) {},
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert("操作失败");
                }
            });            
        })
    });

</script>
reg.ejs

2.routes目录下reg.js

const router = require("koa-router")()
const userBll = require("./../pub/bll/userinfo.js")
const title = "注册"

router.prefix("/reg")

router.get("/", async (ctx, next) => {
  await ctx.render("reg", { title })
})

router.post("/", async (ctx, next) => {

  let result = await userBll.register(ctx)

  ctx.body = result;

})

module.exports = router

登录

 1.views目录下login.ejs

<html>
<head>
<title>Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例</title>
</head>
<body>
<h1><%= title %></h1>
登录名:<input type="text" id="txtUserName" maxlength="20" />
<br/>
<br/>
密码:<input type="password" id="txtUserPwd" maxlength="12" />
<br/>
<br/>
<input type="button" id="btnSub" value="登录" />
</body>
</html>

<script src="/javascripts/jquery-1.11.2.min.js" type="text/javascript"></script>
<script src="/javascripts/md5.js" type="text/javascript"></script>

<script type="text/javascript">   
    $(function(){
        $("#btnSub").on("click", function(){
            var $txtUserName = $("#txtUserName"),
                txtUserNameVal = $.trim($txtUserName.val()),
                $txtUserPwd = $("#txtUserPwd"),
                txtUserPwdVal = $.trim($txtUserPwd.val());
                       
            if(txtUserNameVal.length == 0){
                alert("用户名不能为空");                
                return false;
            }

            if(txtUserPwdVal.length == 0){                
                alert("密码不能为空");                
                return false;
            }
           
            $.ajax({
                url: "/login",
                type: "POST",
                dataType: "json",
                data: {
                    username: txtUserNameVal,                    
                    userpass: hex_md5(txtUserPwdVal)                                        
                },
                beforeSend: function (xhr) {},
                success: function (res) {
                    if (res != null && res.code) {

                        var retVal = parseInt(res.code);

                        switch (retVal) {
                            case 2:
                                alert("输入有误");
                                break;
                            case 0:
                                alert("登录失败");
                                break;
                            case 1:
                                alert("登录成功!");
                                location.href = "/"                                
                                break;
                            case 11:
                                alert("用户名或者密码错误");
                                break;
                            case 12:
                                alert("用户不存在");
                                break;
                        }
                    }
                    else {
                        alert("操作失败");
                    }

                },
                complete: function (XMLHttpRequest, textStatus) {},
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert("操作失败");
                }
            });            
        })
    });

</script>
login.ejs

 2.routes目录下login.js

const router = require("koa-router")()
const userBll = require("./../pub/bll/userinfo.js")
const title = "登录"

router.prefix("/login")

router.get("/", async (ctx, next) => {
  await ctx.render("login", { title })
})

router.post("/", async (ctx, next) => {
  
    let result = await userBll.login(ctx);

    ctx.body = result;
  
})

module.exports = router

首页

 1.views目录下index.ejs