koa2-MVC架構
---------后端技術做前端
環境:nodejs
開發工具:Visual Studio Code(下文簡稱:VSC)
環境安裝,工具安裝及中文自行百度 ,環境調整好后開始進入正題,
1、在硬碟上新增一個檔案夾,打開VSC,點擊‘添加作業區檔案夾’,如果沒有歡迎‘使用頁面’,點擊--檔案--新建視窗,效果如下圖:


2、添加vsc除錯,Shift+ctrl+p,輸入框內輸入:launch.json

選擇剛剛的檔案夾


3、目錄結構

從低到高one by one
3-1、package.json
1 { 2 "name": "koa2mcv", 3 "version": "1.0.0", 4 "description": "Hello Koa 2 example with MVC", 5 "main": "app.js", 6 "scripts": { 7 "start": "node app.js" 8 }, 9 "author": "baba", 10 "dependencies": { 11 "koa": "2.11.0", 12 "koa-router": "8.0.8", 13 "koa-bodyparser": "4.3.0", 14 "koa-static-plus": "0.1.1", 15 "koa-view": "2.1.3", 16 "koa-jwt": "4.0.0", 17 "koa-log4": "2.3.2", 18 "jsonwebtoken": "8.5.1", 19 "nunjucks": "3.2.1", 20 "mime": "2.4.5", 21 "mz": "2.7.0" 22 } 23 }
引數介紹:name專案名稱、version版本號、description專案描述、main專案啟動檔案、scripts啟動快捷設定,author作者,dependencies第3方中間件名稱及版本,
3-2、app.js
1 //啟動服務 2 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專案核心,
例外友好處理1 function handler(){ 2 return async (ctx, next) => { 3 4 const start = new Date().getTime(); 5 6 var urlReq=ctx.request.url; 7 if(urlReq !== '/favicon.ico'){ 8 9 console.log(`請求地址:${ctx.request.method} ${urlReq}`); 10 try { 11 12 let params =Object.assign({}, ctx.request.query, ctx.request.body); 13 14 if(config["token"].excludeUrl.indexOf(urlReq) == -1 && !tokenFunction.varifyToken(params.token)){ 15 ctx.status =401; 16 }else{ 17 await next(); 18 } 19 } catch (error) { 20 ctx.status=401; 21 console.log(`錯誤!無法獲取token引數`); 22 }finally{ 23 24 let err={}; 25 if(!ctx.status){ 26 err.status = 500; 27 }else if(ctx.status==200){ 28 return; 29 }else{ 30 err.status = ctx.status; 31 } 32 33 switch(err.status){ 34 case 404: 35 err.url = config["server-name"]+'/static/public/404.html'; 36 err.message="資源不存在!"; 37 break; 38 case 401: 39 err.url = config["server-name"]+'/static/public/10000.html'; 40 err.message="登陸失效!請重新登陸!"; 41 break; 42 case 500: 43 err.url = config["server-name"]+'/static/public/500.html'; 44 err.message="系統內部錯誤!"; 45 break; 46 } 47 48 switch(ctx.request.type){ 49 case 'application/json': 50 ctx.type = 'application/json'; 51 ctx.body = {errorCode:err.errorCode,message: err.message} 52 break; 53 default: 54 55 ctx.type = 'text/html'; 56 ctx.redirect(err.url); 57 break; 58 } 59 } 60 } 61 const ms = new Date().getTime() - start; 62 console.log(`請求消耗時間: ${ms}ms`); 63 } 64 }
路由配置
1 function controller(){ 2 3 const router = new koaRouter({ 4 prefix: config["server-name"] 5 }); 6 7 function findJsonFile(rootpathStr){ 8 9 fs.readdirSync(rootpathStr).forEach(function (item, index) { 10 11 let fPath = path.join(rootpathStr,item); 12 13 let stat = fs.statSync(fPath); 14 15 if(stat.isDirectory() === true) { 16 findJsonFile(fPath); 17 } 18 19 if (stat.isFile() === true&&fPath.endsWith('.js')) { 20 21 var mapping = require(fPath); 22 for (var url in mapping) { 23 if (url.startsWith('GET ')) { 24 router.get(url.substring(4), mapping[url]); 25 } else if (url.startsWith('POST ')) { 26 router.post(url.substring(5), mapping[url]); 27 } else if (url.startsWith('PUT ')) { 28 router.put(url.substring(4), mapping[url]); 29 } else if (url.startsWith('DELETE ')) { 30 router.del(url.substring(7), mapping[url]); 31 } 32 console.log(`注冊 URL: ${url}`); 33 } 34 } 35 }); 36 } 37 38 findJsonFile(rootpath + 'src'); 39 return router.routes(); 40 }
視圖渲染
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 = https://www.cnblogs.com/yk-1992/archive/2020/10/21/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所有包,以及這些包所依賴的包,

執行后專案結構會增加兩個檔案

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="https://www.cnblogs.com/yk-1992/archive/2020/10/21/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、啟動專案

啟動成功

測驗訪問:http://127.0.0.1:3000/koa/login

輸入值獲取token


先不用帶token進行訪問

攔截成功
帶上token 進行訪問

測驗成功!
end
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/184158.html
標籤:其他
下一篇:js變數與簡單資料型別
