主頁 > 企業開發 > nodejs+koa2 實作模仿springMVC

nodejs+koa2 實作模仿springMVC

2020-10-21 17:31:39 企業開發

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

標籤:其他

上一篇:創建Vue實體一:尋找 Vue 建構式

下一篇:js變數與簡單資料型別

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more