[转]Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例

news/2024/5/9 9:27:54/文章来源:https://blog.csdn.net/weixin_30919571/article/details/97720708

本文转自:https://www.cnblogs.com/zhongweiv/p/nodejs_koa2_webapp.html

目录

前言

  前面一有写到一篇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 = developmentmodule.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() - startconsole.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
复制代码

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.bodyconst 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.bodyconst 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>
复制代码

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

 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

复制代码
<html>
<head>
<title>Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例</title>
</head>
<body>
<h1><%= title %></h1><% if(id != null) {%><h3>登录用户ID:<%= id %> <a id="btnLogOut" href="javascript:void(0);">安全退出</a></h3>
<% } %>
</body>
</html><script src="/javascripts/jquery-1.11.2.min.js" type="text/javascript"></script><script type="text/javascript">   $(function(){$('#btnLogOut').on('click', function(){if(!confirm('确认要退出吗?')){return;}$.ajax({url: '/logout',type: 'POST',dataType: 'json',data: {},beforeSend: function (xhr) {},success: function (res) {if (res != null && res.code) {var retVal = parseInt(res.code);switch (retVal) {                           case 0:alert('失败');break;case 1:alert('成功!');location.href = '/login'                                break;                           }}else {alert('操作失败');}},complete: function (XMLHttpRequest, textStatus) {},error: function (XMLHttpRequest, textStatus, errorThrown) {alert('操作失败');}});            })});</script>
复制代码

 2.routes目录下index.js

复制代码
const router = require('koa-router')()
const title = '首页'router.get('/', async (ctx, next) => {  //判断登录if(!ctx.session || !ctx.session.id){await ctx.redirect('/login')  }else{    const id = ctx.session.id;await ctx.render('index', { title, id })}  
})module.exports = router
复制代码

 index.js文件中实现如果不存在session则跳回登录页

安全退出

 1.routes目录下logout.js

复制代码
const router = require('koa-router')()
const retCode = require('./../pub/utils/retcode.js')router.prefix('/logout')router.get('/', async (ctx, next) => {await ctx.render('logout', {})
})router.post('/', async (ctx, next) => {ctx.session = null;let result = {code: retCode.Success,    data: null}ctx.body = result;})module.exports = router
复制代码

写在之后

   没有去说一些细节API,写这篇主要可以对比 Nodejs学习笔记(七)--- Node.js + Express 构建网站简单示例 来看,完全是一亲的示例,只是这次用的Koa2,方便大家看看Koa2和express写出来的不同

   总的来说Koa2还是比较好上手,async、await这个对于有C#语言基础的来说也比较亲切,不用二次理解

   可以对比一下express时的各种嵌套回调写法,Koa2写好更优雅、更易阅读

 示例有限,其它操作通过官网查找API或github找一些组件来动手试,比如最常用的一些功能:操作cookies、上传文件、session存储到其它介质等

 

 参考资料: https://koa.bootcss.com/

 

 老规矩不放源码,虽然是示例结构,但是尽量按照平常做项目的想法去实现的,有兴趣的动手去搭项目做才会理解一些思路,代码都放在文章中了,有问题留言^_^!

作   者:   Porschev[钟慰] 
出   处:   http://www.cnblogs.com/zhongweiv/ 
微   博:     http://weibo.com/porschev 
欢迎任何形式的转载,但请务必注明原文详细链接

 

转载于:https://www.cnblogs.com/freeliver54/p/10562928.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_799015.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

提供图片服务网站

有了这些图片API&#xff0c;可以获取随机图片&#xff0c;很适合做Blogs背景图片 1、Unsplash API&#xff1a;https://unsplash.com/developers 接口文档&#xff1a;https://unsplash.com/documentation#get-a-random-photo 例&#xff1a;https://source.unsplash.com/1920…

网站架构核心设计知识(三)之高并发

转载于:https://www.cnblogs.com/htkj/p/11055765.html

省政府网站绩效评估细则及方法

<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />各省电子政务办公室针对于网站做出了绩效评估细则及方法&#xff0c;然后各厅、局、科室等惯彻省里的思想&#xff0c;对自己所管辖范围内的政府网站进行人性化评估。以下就是湖北…

转载 --电子商务基础:中小企业建站方案和资源

目前国内的中小企业数量已经有几千万家&#xff0c;但信息化建设却并不理想&#xff0c;拥有网站的只有不超过两百万家&#xff0c;数以千万计的中小企业存在电子商务需求&#xff0c;却没有自己独立的网站。现在&#xff0c;越来越多的企业意识到通过建立网站开展电子商务的重…

分享10个免费H5模版(主题)资源网站

并非所有程序员都是伟大的设计师&#xff08;实际上我认识的大部分程序员审美都很要命&#xff09;。所以即使你心血来潮想为自己开发的网站做一把设计&#xff0c;但显然并不是所有用户想为此付钱。。所以在找不到靠谱的美工的时候&#xff0c;还是老老实实的看看有没有现成的…

导航之变—移动网站的导航设计

导航是互联网网站最重要的组成部分之一&#xff0c;它涉及到产品的信息架构、页面布局和用户交互行为等诸多方面。一个网站用户体验的优劣往往和导航的优劣有密切的联系。 随着移动互联网的发展&#xff0c;越来越多的网站以移动网站的形式移植到手机上。在网站移植过程中&…

薛峰SEO培训:优化网站前的思考

2019独角兽企业重金招聘Python工程师标准>>> 学习SEO的五个步骤 1.初步的了解SEO 2.重复是学习之母 3.开始运用你所学到的SEO知识 4.融汇贯通所学的SEO知识。 5.再一次地加强SEO的学习 定位与资源成反比 量力而行 不可能做大型门户如&#xff1a;娱乐门户 游戏门户 …

优秀网页设计:35个吸引眼球的精美作品集网站

作品集网站是设计师、艺术家和摄影师展示个人作品的最佳方式&#xff0c;因为网站能够非常便捷和直观的向潜在客户呈现其作品。同时&#xff0c;网站也能体现出作者的创意能力和专业水平。下面推荐的35个优秀作品集网站在网站布局&#xff0c;色彩运用方面都非常的好&#xff0…

视频直播网站开发千万不能忘的一个知识点

对于视频直播网站开发的技术人员来讲&#xff0c;音视频即时通讯技术是需要熟练掌握的。毕竟像直播这样重视互动和实时性的应用场景&#xff0c;即时通讯可以从中起到很大的配合作用。目前市面上有很多服务商所提供的SDK可以帮助实现这一技术&#xff0c;但是在选择哪一家服务商…

做了个新网站http://qq.ihaonet.com/全球最大QQ聊天交友网站

做了个新网站http://qq.ihaonet.com/全球最大QQ聊天交友网站 有什么建议欢迎大家点评&#xff0c;谢谢&#xff01;

应该常去的一些网站

2019独角兽企业重金招聘Python工程师标准>>> IT相关的话&#xff0c;国外&#xff1a; http://stackoverflow.com/ http://www.techrepublic.com/ http://www.theserverside.com/ http://www.infoq.com/ (中文网&#xff1a;http://www.infoq.com/cn) http://www…

《转》VS2012发布网站详细步骤

本文转载自MannyGuo 如果给您带来不便请联系博主 1、打开你的VS2012网站项目&#xff0c;右键点击项目》菜单中 重新生成一下网站项目&#xff1b;再次点击右键》发布&#xff1a; 2、弹出网站发布设置面板&#xff0c;点击<新建..>,创建新的发布配置文件&#xff1a; 输…

Python+Bottle+Sina SAE快速构建网站

Bottle是新生一代Python框架的代表&#xff0c;利用Bottle构建网站将十分简单。 Sina SAE是国内较出名的云平台之一&#xff0c;十分适用于个人网站的开发或创业公司网站开发。 下面将介绍如果通过PythonBottleSina SAE快速搭建一个网站。 1.注册Sina SAE账号后&#xff0c;创建…

HDInsight-Hadoop实战(一)网站日志分析

HDInsight-Hadoop实战&#xff08;一&#xff09;网站日志分析简介 在此示例中&#xff0c;你将使用分析网站日志文件的 HDInsight 查询来深入了解客户使用网站的方式。借助此分析&#xff0c;你可查看外部网站一天内对该网站的访问频率以及用户体验的网站错误总结。 在此教程…

20个学习CSS的绝佳网站-让你从入门到精通

CSS&#xff08;层叠样式表&#xff09;是一种简单的设计语言&#xff0c;能够将页面变漂亮这回事儿变的简单化。在HTML和XHTML中设定页面的样式&#xff0c;这是最常用的应用。但也可以应用于 XML类的文档&#xff0c;包括SVG和XUL。他负责管理网页的设计和外观。使用CSS&…

ios图文详情加载html_WordPress 网站深度优化加载速度(技术篇)

本篇文章主要介绍如何对网站的静态资源进行优化。静态资源就是网页中用到的 js/css/fonts 这些文件。基本上 WordPress 的每个插件&#xff0c;每个主题都会有自己的 css/js/fonts。最终在做好的网站上会加载这些全部的 js/css/fonts 文件。而我们需要做的就是优化这些静态资源…

Nginx配置SSL证书部署HTTPS网站

一、什么是 SSL 证书&#xff0c;什么是 HTTPSSSL 证书是一种数字证书&#xff0c;它使用 Secure Socket Layer 协议在浏览器和 Web 服务器之间建立一条安全通道&#xff0c;从而实现&#xff1a;1、数据信息在客户端和服务器之间的加密传输&#xff0c;保证双方传递信息的安全…

前端通过网站得到json_【WEB开发】Django中方便快捷的json响应

目前流行的前后端分离开发模式中&#xff0c;前端工程师需要根据后端开发人员给出的API文档发起不同的请求得到数据&#xff0c;API文档规定了一些请求的模板以及响应的数据格式和代码。通常&#xff0c;前后端约定一些代码以代表一定含义的响应。在这里&#xff0c;分享一个作…

java 文件上传漏洞_网站漏洞修复之UEditor漏洞 任意文件上传漏洞

UEditor于近日被曝出高危漏洞&#xff0c;包括目前官方UEditor 1.4.3.3 最新版本&#xff0c;都受到此漏洞的影响&#xff0c;ueditor是百度官方技术团队开发的一套前端编辑器&#xff0c;可以上传图片&#xff0c;写文字&#xff0c;支持自定义的html编写&#xff0c;移动端以…

linux服务器网站php无法访问,linux服务器无法远程连接

1、查看SSH是否安装(检查是否装了SSH包)输入命令&#xff1a;rpm -qa | grep ssh如下如所示系统已经默认安装了SSH&#xff1a;若没有安装&#xff0c;则输入&#xff1a;yum install openssh-server进行安装。在线视频教程推荐&#xff1a;linux视频教程2、查看SSH服务是否运行…