nodejs+koa2 实现模仿springMVC框架


Posted in NodeJs onOctober 21, 2020

koa2-MVC架构

---------后端技术做前端

环境:nodejs

开发工具:Visual Studio Code(下文简称:VSC)

环境安装,工具安装及中文自行百度,环境调整好后开始进入正题。

1、在硬盘上新增一个文件夹,打开VSC,点击‘添加工作区文件夹',如果没有欢迎‘使用页面',点击--文件--新建窗口,效果如下图:

nodejs+koa2 实现模仿springMVC框架

nodejs+koa2 实现模仿springMVC框架

2、添加vsc调试。Shift+ctrl+p,输入框内输入:launch.json

nodejs+koa2 实现模仿springMVC框架

选择刚刚的文件夹

nodejs+koa2 实现模仿springMVC框架

nodejs+koa2 实现模仿springMVC框架

3、目录结构

nodejs+koa2 实现模仿springMVC框架

从低到高one by one

3-1、package.json

{
 "name": "koa2mcv",
 "version": "1.0.0",
 "description": "Hello Koa 2 example with MVC",
 "main": "app.js",
 "scripts": {
  "start": "node app.js"
 },
 "author": "baba",
 "dependencies": {
  "koa": "2.11.0",
  "koa-router": "8.0.8",
  "koa-bodyparser": "4.3.0",
  "koa-static-plus": "0.1.1",
  "koa-view": "2.1.3",
  "koa-jwt": "4.0.0",
  "koa-log4": "2.3.2",
  "jsonwebtoken": "8.5.1",
  "nunjucks": "3.2.1",
  "mime": "2.4.5",
  "mz": "2.7.0"
 }
}

参数介绍:name项目名称、version版本号、description项目描述、main项目启动文件、scripts启动快捷设置,author作者,dependencies第3方中间件名称及版本。

3-2、app.js

//启动服务
require('./config/init').startServer();

启动相关配置,封装到config/init.js中,启动文件直接引用即可。

3-3、views存放html页面

3-4、static存放静态文件,css,js,font等

3-5、src存放业务控制,类似于springMVC中的controller、service。

3-6、config存放核心配置文件。

3-6-1、init.js项目核心。

异常友好处理

function handler(){
 return async (ctx, next) => {

  const start = new Date().getTime();

  var urlReq=ctx.request.url;
  if(urlReq !== '/favicon.ico'){

   console.log(`请求地址:${ctx.request.method} ${urlReq}`);
   try {

    let params =Object.assign({}, ctx.request.query, ctx.request.body);

    if(config["token"].excludeUrl.indexOf(urlReq) == -1 && !tokenFunction.varifyToken(params.token)){
     ctx.status =401;
    }else{
     await next();
    }
   } catch (error) {
    ctx.status=401;
    console.log(`错误!无法获取token参数`);
   }finally{

     let err={};
     if(!ctx.status){
      err.status = 500;
     }else if(ctx.status==200){
      return;
     }else{
      err.status = ctx.status;
     }

     switch(err.status){
      case 404:
       err.url = config["server-name"]+'/static/public/404.html';
       err.message="资源不存在!";
       break;
      case 401:
       err.url = config["server-name"]+'/static/public/10000.html';
       err.message="登陆失效!请重新登陆!";
       break;
      case 500:
       err.url = config["server-name"]+'/static/public/500.html';
       err.message="系统内部错误!";
       break;
     }

     switch(ctx.request.type){
      case 'application/json':
       ctx.type = 'application/json';
       ctx.body = {errorCode:err.errorCode,message: err.message}
       break;
      default:

       ctx.type = 'text/html';
       ctx.redirect(err.url);
       break;
     }
   }
  }
  const ms = new Date().getTime() - start;
  console.log(`请求消耗时间: ${ms}ms`);
 }
}

路由配置

function controller(){

 const router = new koaRouter({
  prefix: config["server-name"]
 });

 function findJsonFile(rootpathStr){

  fs.readdirSync(rootpathStr).forEach(function (item, index) {

   let fPath = path.join(rootpathStr,item);

   let stat = fs.statSync(fPath);

   if(stat.isDirectory() === true) {
    findJsonFile(fPath);
   }

   if (stat.isFile() === true&&fPath.endsWith('.js')) {

    var mapping = require(fPath);
    for (var url in mapping) {
     if (url.startsWith('GET ')) {
      router.get(url.substring(4), mapping[url]);
     } else if (url.startsWith('POST ')) {
      router.post(url.substring(5), mapping[url]);
     } else if (url.startsWith('PUT ')) {
      router.put(url.substring(4), mapping[url]);
     } else if (url.startsWith('DELETE ')) {
      router.del(url.substring(7), mapping[url]);
     }
     console.log(`注册 URL: ${url}`);
    }
   }
  });
 }

 findJsonFile(rootpath + 'src');
 return router.routes();
}

视图渲染

function templating() {
 var
  autoescape = config['templating-autoescape'] === null ? true : config['templating-autoescape'],
  noCache = config['templating-noCache'] === null ? false : config['templating-noCache'],
  watch = config['templating-watch'] === null ? false : config['templating-watch'],
  throwOnUndefined = config['templating-throwOnUndefined'] === null ? false :config['templating-throwOnUndefined'],
  env = new nunjucks.Environment(
   new nunjucks.FileSystemLoader(rootpath+'views', {
    noCache: noCache,
    watch: watch,
   }), {
    autoescape: autoescape,
    throwOnUndefined: throwOnUndefined
   });
 if (config['templating-filters'] != null) {
  for (var f in config['templating-filters']) {
   env.addFilter(f, config['templating-filters'][f]);
  }
 }
 return async (ctx, next) => {
  ctx.render = function (view, model) {
   ctx.response.body = env.render(view, Object.assign({}, ctx.state || {}, model || {}));
   ctx.response.type = 'text/html';
  };
  await next();
 };
}

启动构建

function startServer(){

 const app = new koa();

 app.use(koaStaticPlus(rootpath+'static', {
  pathPrefix: config["server-name"]+'/static'
 })
 );
 
 app.use(koaBodyParser());
 
 app.use(handler());
 
 app.use(templating());
 
 app.use(controller());
 
 app.listen(config["server-port"]);

}

3-6-2、config.js项目参数配置。

module.exports ={
 'server-name':'/koa',
 'server-port':3000,
 "templating-noCache":true,
 "templating-watch":true,
 "templating-autoescape":null,
 "templating-throwOnUndefined":null,
 "templating-filters":null,
 "token":{
  "excludeUrl":[
  "/koa/login",
  "/koa/dologin"
  ],
  "timeout":1000 * 60 * 60 * 24 * 7,
  "secret":"jiaobaba"
 }
 

}

3-6-3、token.js项目token相关方法封装。

const jwt = require("jsonwebtoken");
const config = require('./config');
/**
 * 创建token的方法
 */
let createToken = (data)=>{
 let obj = {};
 //存入token的数据
 obj.data = data || {};
 //token的创建时间
 obj.ctime = (new Date()).getTime();
 return jwt.sign(obj,config["token"].secret);
}
/**
 * 验证token是否合法的方法
 * @param {*} token 
 */
let varifyToken = (token)=>{
 let result = null;
 try{
  let {data,ctime,expiresIn} = jwt.verify(token,config["token"].secret);
  let nowTime = (new Date()).getTime();
  if(nowTime-ctime<config["token"].timeout){
   result = data;  
  }
 }catch(error){

 }
 return result;
}

module.exports = {
 createToken,
 varifyToken
};

3-6-4、logger.js项目日志配置文件。

4、项目结构构建结束,接着引入所有依赖包,在终端中执行‘npm install' ,会下载package.json中dependencies所有包,以及这些包所依赖的包。

nodejs+koa2 实现模仿springMVC框架

执行后项目结构会增加两个文件

nodejs+koa2 实现模仿springMVC框架

5、编写测试用例,在src下新建hello.js。

//token
const token = require('../config/token');

var fn_hello = async (ctx, next) => {
 var name = ctx.params.name;
 ctx.response.body = `<h1>Hello, ${name}!</h1>`;
};


var fn_index = async (ctx, next) => {
 ctx.response.body = `<h1>Index</h1>
  <form action="/koa/signin" method="post">
   <p>Name: <input name="name" value=""></p>
   <p>Password: <input name="password" type="password"></p>
   <p><input type="submit" value="Submit"></p>
  </form>`;
};

var fn_signin = async (ctx, next) => {
 var
  name = ctx.request.body.name || '',
  password = ctx.request.body.password || '';
 console.log(`登陆名: ${name}, 密码: ${password}`);
  ctx.response.body = `<h1>Welcome, ${name}!</h1><br/>you token:<br/>${token.createToken({user: name,password: password})}`;
 
};

module.exports = {
 'GET /hello/:name': fn_hello,
 'GET /login': fn_index,
 'POST /dologin': fn_signin
};

6、启动项目

nodejs+koa2 实现模仿springMVC框架

启动成功

nodejs+koa2 实现模仿springMVC框架

测试访问:http://127.0.0.1:3000/koa/login

nodejs+koa2 实现模仿springMVC框架

输入值获取token

nodejs+koa2 实现模仿springMVC框架

nodejs+koa2 实现模仿springMVC框架

先不用带token进行访问

nodejs+koa2 实现模仿springMVC框架

拦截成功

带上token 进行访问

nodejs+koa2 实现模仿springMVC框架

测试成功!

到此这篇关于nodejs+koa2 实现模仿springMVC的文章就介绍到这了,更多相关nodejs+koa2 springMVC内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

NodeJs 相关文章推荐
Ubuntu中搭建Nodejs开发环境过程分享
Jun 01 NodeJs
nodejs教程之异步I/O
Nov 21 NodeJs
NodeJS学习笔记之Connect中间件模块(二)
Jan 27 NodeJs
nodeJS代码实现计算交社保是否合适
Mar 09 NodeJs
nodejs async异步常用函数总结(推荐)
Nov 17 NodeJs
windows系统下更新nodejs版本的方案
Nov 24 NodeJs
NodeJs实现定时任务的示例代码
Dec 05 NodeJs
解决nodejs的npm命令无反应的问题
May 17 NodeJs
NodeJs项目中关闭ESLint的方法
Aug 09 NodeJs
Nodejs把接收图片base64格式保存为文件存储到服务器上
Sep 26 NodeJs
详解从NodeJS搭建中间层再谈前后端分离
Nov 13 NodeJs
Nodejs实现WebSocket代码实例
May 19 NodeJs
nodejs使用Sequelize框架操作数据库的实现
Oct 21 #NodeJs
用Nodejs实现在终端中炒股的实现
Oct 18 #NodeJs
Nodejs在局域网配置https访问的实现方法
Oct 17 #NodeJs
NodeJS开发人员常见五个错误理解
Oct 14 #NodeJs
浅谈vue websocket nodeJS 进行实时通信踩到的坑
Sep 22 #NodeJs
基于NodeJS开发钉钉回调接口实现AES-CBC加解密
Aug 20 #NodeJs
浅谈使用nodejs搭建web服务器的过程
Jul 20 #NodeJs
You might like
php处理json时中文问题的解决方法
2011/04/12 PHP
php使HTML标签自动补全闭合函数代码
2012/10/04 PHP
PHP实现通过Luhn算法校验信用卡卡号是否有效
2015/03/23 PHP
PHP 信号管理知识整理汇总
2017/02/19 PHP
tp5实现微信小程序多图片上传到服务器功能
2018/07/16 PHP
javascript css styleFloat和cssFloat
2010/03/15 Javascript
改写一个简单的菜单 弹性大小
2010/12/02 Javascript
IE6下javasc#ipt:void(0) 无效的解决方法
2013/12/23 Javascript
node.js中的http.response.write方法使用说明
2014/12/14 Javascript
jquery实现图片随机排列的方法
2015/05/04 Javascript
整理JavaScript创建对象的八种方法
2015/11/03 Javascript
javascript数据结构之双链表插入排序实例详解
2015/11/25 Javascript
jQuery中slidedown与slideup方法用法示例
2016/09/16 Javascript
JavaScript实现汉字转换为拼音的库文件示例
2016/12/22 Javascript
微信小程序开发之Tabbar实例详解
2017/01/09 Javascript
JavaScript中Promise的使用详解
2017/02/26 Javascript
基于vue.js实现的分页
2018/03/13 Javascript
解决element UI 自定义传参的问题
2018/08/22 Javascript
React 项目迁移 Webpack Babel7的实现
2018/09/12 Javascript
原生js实现商品筛选功能
2019/10/28 Javascript
Python中itertools模块用法详解
2014/09/25 Python
python实现颜色空间转换程序(Tkinter)
2015/12/31 Python
学习python可以干什么
2019/02/26 Python
对Python中 \r, \n, \r\n的彻底理解
2020/03/06 Python
python如何代码集体右移
2020/07/20 Python
Python logging模块原理解析及应用
2020/08/13 Python
基于Python正确读取资源文件
2020/09/14 Python
python 基于UDP协议套接字通信的实现
2021/01/22 Python
HTML5 的新的表单元素(datalist/keygen/output)使用介绍
2013/07/19 HTML / CSS
西班牙土拨鼠床垫公司,感觉在云端:Marmota
2019/03/18 全球购物
理工大学毕业生自荐信范文
2014/02/22 职场文书
高中军训感言400字
2014/02/24 职场文书
安全宣传标语口号
2014/06/06 职场文书
提取视频中的音频 Python只需要三行代码!
2021/05/10 Python
JavaScript数组 几个常用方法总结
2021/11/11 Javascript
国际最新研究在陨石中发现DNA主要成分 或由陨石带来地球
2022/04/29 数码科技