zoukankan      html  css  js  c++  java
  • 原生NodeJS封装Express路由

    Express:https://www.expressjs.com.cn/

    express路由:

    var express = require('express')
    var app = express()
    app.get("/", function (req, res) {
    res.send('hello world')
    })
    app.get("/login", function (req, res) {
    res.send('hello world')
    })
    app.post("/doLogin", function (req, res) {
    res.send('POST request to the homepage')
    })

    考虑定义一个 Router 模块,Router 模块中绑定一个 get 方法配置路由和一个 post 方法配置路由,以及一个 error 方法处理路由出错情况,并向外暴露 Router 模块,外部调用这个模块时,只需要传入一个路由和路由回调执行路由逻辑。

    在 get 方法和post 方法中,首先需要在全局变量 Global 中注册一个路由,把我们外部传入的路由和路由回调绑定到 Global 中,在调用Router 模块时,就可以先判断是否这个路由是否注册了,没有注册,就执行 Router的 error 方法报 404,注册了就执行这个路由的路由回调逻辑。

    const url = require('url')
    const Global = { }
    const Router = function (req, res) { const pathname = url.parse(req.url).pathname if (Global[pathname]) { //如果是注册过的路由,就执行路由回调 Global[pathname](req, res) } else { Router.error(req, res) } } //给Router绑定get方法配置路由 Router.get = function (str, callback) { Global[str] = callback;//注册路由 }
    //给Router绑定post方法配置路由
    Router.post = function (str, callback) {
        Global[str] = callback;//注册路由
    }
    //给Router绑定error方法,路由未注册时报404 Router.error = function (req, res) { res.writeHead(404, { 'Content-Type': 'text/html;charset="utf-8"' }); res.end("404 error") } //将Router模块向外暴露出去 module.exports = Router;

    外部调用:

    Router.get('/login',function(req,res){
        res.end('login')
    })
    

    以上的Router模块 以及 Global 全部暴露在全局中,容易污染全局,所以可以将Router 封装到一个 Request 模块中,Request 模块的返回值就是 Router配置方法。

    get路由注册和 post路由注册需要有区别,否则 Global [pathname] 都一样,post 路由配置会覆盖 get 路由配置,区分方式是在 Global 中绑定 _get 和 _post 两个属性,在注册路由时,如果是 get类型就注册 Global._get 路由,是 post类型,就注册 Global._post 路由

    Global 中的 _get 和 _post 两种路由的执行,在执行之前先判断 reg的请求类型,拿到 reg.method,根据这个执行不同的路由回调,是 get 类型,直接执行 _get 路由逻辑,是 post 类型,可以拿到 post 请求中的参数,将这个参数放在 req.body 中,在执行 _post 的路由逻辑。

    当然,路由没有注册( pathname不匹配 ),就执行路由错误报404

    最后返回封装的路由方法给 Request 模块。

    const url = require('url')
    
    const Request = function(){
        const Global = {
            "_get":{ }, //把get和post分开
            "_post":{ },
        } 
    
        const Router = function (req, res) {
            const pathname = url.parse(req.url).pathname
            const method = req.method.toLowerCase() //获取请求类型 get/post
    
            if (Global['_'+method][pathname]) { //拿到请求类型,直接通过Global执行相应类型的请求
                if(method=='get'){
                    Global['_get'][pathname](req, res)
                }
                else if(method=='post'){
                    let params = '';
                    req.on('data',(chunk)=>{
                        params+=chunk;
                    })
                    req.on('end',()=>{
                        req.body=params
                        Global['_post'][pathname](req,res)
                    })
                }
            }
            else {
                Router.error(req, res)
            }
        }
    
        //给Router绑定get方法配置路由
        Router.get = function (str, callback) {
            Global['_get'][str] = callback;//注册路由
        }
    
        //给Router绑定post方法配置路由
        Router.post = function (str, callback) {
            Global['_post'][str] = callback;//注册路由
        }
    
        //给Router绑定error方法,路由未注册时报404
        Router.error = function (req, res) {
            res.writeHead(404, { 'Content-Type': 'text/html;charset="utf-8"' });
            res.end("404 error")
        }
        return Router;
    }
    //将Request模块向外暴露出去
    module.exports = Request();
    

    外部调用这个Request模块的路由配置方法,配置路由:

    const http = require('http');
    const ejs = require('ejs')
    const Request = require('./Router02')
    //注册web服务
    http.createServer(Request).listen(8081);
    
    //配置路由
    Request.get('/', function (req, res) {
        res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
        res.end('<h3>这是首页</h3>');
    })
    Request.get('/login',function(req,res){
        ejs.renderFile('./views/form.ejs', {}, (err, data) => {
            res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
            res.end(data);
        })
    })
    Request.post('/doLogin', function (req, res) {
        res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
        console.log(req.body)
        res.end(req.body);
    })
    Request.get('/register',function(req,res){
        res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
        res.end('<h3>这是注册页</h3>');
    })
    console.log('Server running at http://127.0.0.1:8081/');
    

    路由配置正常:

    下面将响应信息封装成一个 send() 方法:

    在 Router中可以修改 res ,扩展 res的方法:

    Router 中可以封装一个静态web服务,这样可以既直接访问静态资源,也可以执行后端路由逻辑:

    Router.js

    const fs = require('fs')
    const path = require('path')
    const url = require('url')
    
    //web静态服务
    function staticWeb(req,res,staticPath){
        let pathname = url.parse(req.url).pathname  //先获取地址
        pathname = pathname == '/' ? '/index.html' : pathname //根目录下定位到首页
        let ext = path.extname(pathname) //获取文件后缀名
        let getMime = function (ext) { //获取文件类型
            let data = fs.readFileSync('./mime.json'); //同步方法,没有回调
            let mime = JSON.parse(data.toString())[ext]
            return mime;
        }
        try {
            let data = fs.readFileSync(staticPath + pathname)
            if (data) {
                let mime = getMime(ext) //获取文件类型
                res.writeHead(200, { 'Content-Type': `${mime};charset="utf-8"` });
                res.end(data);
            }
        } catch (error) {
            console.log("静态资源没有匹配,执行匹配后端路由")
        }
    }
    
    
    const Request = function(){
        const Global = {
            "_get":{ }, //把get和post分开
            "_post":{ },
            staticPath:'./static' //设置默认静态web目录
        } 
        const Router = function (req, res) {
            const pathname = url.parse(req.url).pathname //获取访问的路由
            const method = req.method.toLowerCase() //获取请求类型 get/post
            //给 res 扩展一个send()方法响应请求
            res.send=function(data){
                res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
                res.end(data);
            }
            //配置静态web服务
            staticWeb(req,res,Global.staticPath)
    
            if (Global['_'+method][pathname]) { //拿到请求类型,直接通过Global执行相应类型的请求
                if(method=='get'){
                    Global['_get'][pathname](req, res)
                }
                else if(method=='post'){
                    let params = '';
                    req.on('data',(chunk)=>{
                        params+=chunk;
                    })
                    req.on('end',()=>{
                        req.body=params
                        Global['_post'][pathname](req,res)
                    })
                }
            }
            else {
                Router.error(req, res)
            }
        }
    
        //给Router绑定get方法配置路由
        Router.get = function (str, callback) {
            Global['_get'][str] = callback;//注册路由
        }
    
        //给Router绑定post方法配置路由
        Router.post = function (str, callback) {
            Global['_post'][str] = callback;//注册路由
        }
    
        //给Router绑定error方法,路由未注册时报404
        Router.error = function (req, res) {
            res.send("404 error")
        }
    
        //配置静态web服务,传入一个静态目录地址即可,不传的话取Global中的默认路径
        Router.static = function(staticPath){
            Global.staticPath=staticPath
        }
        return Router;
    }
    //将Request模块向外暴露出去
    module.exports = Request();
    

    app.js

    const http = require('http');
    const ejs = require('ejs')
    const Request = require('./Router04')
    //注册web服务
    http.createServer(Request).listen(8081);
    
    //配置路由
    Request.get('/', function (req, res) {
        res.send('<h3>这是首页</h3>');
    })
    Request.get('/login',function(req,res){
        ejs.renderFile('./views/form.ejs', {}, (err, data) => {
            res.send(data);
        })
    })
    Request.post('/doLogin', function (req, res) {
        res.send(req.body);
    })
    Request.get('/register',function(req,res){
        res.send('<h3>这是注册页</h3>');
    })
    console.log('Server running at http://127.0.0.1:8081/');
    

    静态资源访问正常,后端路由也执行正常:

  • 相关阅读:
    ceph概述
    docker网络
    ceph部署
    K8s集群搭建(二)
    K8s架构
    K8s集群搭建(一)
    Kubernetes介绍
    虚拟化网络管理(二)
    virt-manager创建虚拟机
    C#中TransactionScope的使用方法和原理
  • 原文地址:https://www.cnblogs.com/shanlu0000/p/13156790.html
Copyright © 2011-2022 走看看