美文网首页
跟我一起学NodeJs之环境搭建,路由初始化,应用分层,路由开发

跟我一起学NodeJs之环境搭建,路由初始化,应用分层,路由开发

作者: 喜剧之王爱创作 | 来源:发表于2020-04-08 10:49 被阅读0次
    u=4104387483,4024841696&fm=26&gp=0.jpg

    上一节,我们将了NodeJS的安装,server的创建、debugger等,想要满足开发,我们还是要接着往下看,那么,我们直奔主题!

    项目实战(原生环境搭建)

    依赖包
    • cross-env:提供兼容Win,Mac,Linux不同系统的环境变量
    • nodemon:监控NodeJS文件变化,实现自动编译,不用每次修改文件后手动重启服务

    可通过下面代码进行安装

    yarn add nodemon cross-env --save-dev
    
    创建目录结构
    1. 执行npm init -y,创建一个初始化的npm环境,用来将来安装一些依赖包,生成package.json文件
    2. 项目目录下创建'bin'文件夹,一般存放可执行文件,并在其下层创建'www.js'文件,在这里我们写一些Server相关的代码,即server
    3. 在项目目录下创建app.js,在这里我们用来写我们的业务代码
    写代码
    //www.js
    const http = require('http')
    const PORT = 8000
    const serverHandel = require('../app')
    const server = http.createServer(serverHandel)
    server.listen(PORT)
    console.log('success')
    
    //app.js
    const serveHandel = (req, res) => {
        //设置返回格式为JSON
        res.setHeader('Content-type', 'application/json')
        const resData = {
            name:'张三',
            age: 18,
            env: process.env.NODE_ENV
        }
        res.end(
            JSON.stringify(resData)
        )
    
    }
    module.exports = serveHandel
    
    //在安装完以上'nodemon 和cross-env'后,需要配置一下node指令,和主文件,如下
      "main": "bin/www.js",
      "scripts": {
        "dev": "cross-env NODE_ENV=dev nodemon ./bin/www.js",
        "prd": "cross-env NODE_ENV=production nodemon ./bin/www.js"
      },
    

    上面我将server代码,业务代码抽离开,使得项目更加易于维护,我们可以在app.js里面进行各种配置和解析,并且可以将不同的方法相互引用,而www.js只放心做server端的事。

    到这里,一个基础的NodeJS项目环境就搭建完成了,是不是很简单呢

    开发

    路由初始化

    首先需要注意

    • 接口,是通过路由实现的

    上面我们搭建了基本的开发环境,也将server层代码和业务代码分离,但毕竟业务是复杂的我们不能把业务代码都写在app.js里面,所以这里仍然需要做个拆分,一般我们采用的方案是在“bin”同级新建“src”文件夹,其中的每个人间代表一类接口,然后我们再通过模块化将其引入到app.js中,这样,我们就可以不同的业务代码写在不同文件件里,一些公共的配置也可以在app.js里面进行全局配置,这样的代码将拆分的更加简单

    一般的,我们需要先将接口调通,再去处理其具体数据,下面我将改造后的app.js和其中一个业务代码模块贴出来,同学们也可以跟着这个节奏进行扩展

    //app.js
    const handleBlogRouter = require('./src/router/blog')
    const handleUserRouter = require('./src/router/user')
    
    const serveHandel = (req, res) => {
        //设置返回格式为JSON
        res.setHeader('Content-type', 'application/json')
        //设置path
        const url = req.url
        req.path = url.split('?')[0]
        //处理blog路由
        const blogData = handleBlogRouter(req, res)
        if(blogData) {
            res.end(
                JSON.stringify(blogData)
            )
            return
        }
        //处理user路由
        const userData = handleUserRouter(req,res)
        if(userData) {
            res.end(
                JSON.stringify(userData)
            )
            return
        }
        //未命中路由返回404
        res.writeHead(404, {"Content-type": "text/plain"})
        res.write("404 Not Found\n")
        res.end()
    
    }
    module.exports = serveHandel
    
    //其中一个业务代码
    const handleBlogRouter = (req, res) => {
        const method = req.method //GET POST
    
        //实现接口
        //获取博客列表
        if (method === 'GET' && req.path === '/api/blog/list') {
            return {
                msg: '这是获取博客列表的接口'
            }
        }
        //获取博客详情
        if (method === 'GET' && req.path === '/api/blog/detail') {
            return {
                msg: '这是获取博客详情的接口'
            }
        }
        //新建一篇博客
        if (method === 'POST' && req.path === '/api/blog/new') {
            return {
                msg: '这是新建博客的接口'
            }
        }
        //更新一篇博客
        if (method === 'POST' && req.path === '/api/blog/update') {
            return {
                msg: '这是更新博客的接口'
            }
        }
        //删除一篇博客
        if (method === 'POST' && req.path === '/api/blog/del') {
            return {
                msg: '这是删除博客的接口'
            }
        }
    }
    module.exports = handleBlogRouter
    

    这样我们就创建了不同的接口,并且可以通过浏览器或postman对其进行测试。

    读到这里,我想做一个总结:

    我们把不同业务代码拆分到src对应的不同文件夹下,然后通过nodejs模块化将其引入到app.js,即入口文件中,并在这里做一些全局性的配置,如响应头的设置,path的配置等,当我们调用某接口时,如:'/api/blog/detail',就会命中业务代码中的某一个逻辑,并返回对应的对象(这里我们为了先将接口测通,先返回简单对象),并最终将其作为接口响应返回,假如不能命中任何逻辑代码,则响应为404。

    到这里,我们就完成了这个项目的路由初始化,下面我们就可以开发对应的路由(接口)了

    路由开发

    上面讲到了基础环境的搭建,Server层和业务层的分离,以及路由的初始化等,到此为止,我们已经具备了开发接口的能力(不涉及登录,不涉及数据库,只做接口的数据格式返回)

    这里介绍几个概念:

    • 数据模型:一种面向对象的变成思想,用到对象继承等一些知识,我们将在后面使用数据模型来定义将来要输出的数据结构,使我们接口所输出的数据达到一个格式上的一致性,或者是易于维护的特点。
    • controller: MVC设计模式中的C,在这里,我们将用来专心的处理数据,只做和数据有关的事情,包括一些计算等等的操作。

    这样,我们的项目暂时可以分为以下四层:

    • www.js:用来写Server逻辑,只关心Server的逻辑
    • app.js: 做一些基本配置,如参数的解析规则,不同接口的处理方法等,不涉及业务代码,可以看做是Server层和业务层的桥梁
    • router: 处理路由接口的逻辑,在这里我们只关心路由的都逻辑,包括匹配到路由后返回什么格式的数据等(在这里我们将用到数据模型,用来统一返回格式)
    • controller:在这里,我们只关心数据,我们可以在这里做具体的数据处理,处理参数等。

    将应用分层,然后通过nodejs模块化,将各个模块关联起来,这就行程了一个成熟应用的雏形,我们可以在此基础上开发各种借口,下面我将贴出一个获取博客详情的各层代码

    1. Server层

    和上面基础路由的搭建一样,这里不做说明

    1. app层

    和上面基础路由的搭建一样,只加入了query解析的代码,因为这属于公共的逻辑代码

    +++
    req.query = querystring.parse(url.split('?')[1])
    ...
    
    1. router层

    我们在上面搭建了基础的路由逻辑,即命中某一个路由,返回对应的数据,因为上面只是做初始化,使用了一些简单的“傻白甜”数据,这里我们将其具体化。

    const { getList } = require('../controller/blog')
    const { SuccessModel, ErrorModel } = require('../model/resModel')
        if (method === 'GET' && req.path === '/api/blog/list') {
            const author = req.query.author || ''
            const keyword = req.query.keyword || ''
            const listData = getList(author,keyword)
            return  new SuccessModel(listData)
        }
    

    可以看到,这里我们将具体的数据处理方法getList,抽离出去,并引入了数据模型用来规范返回的数据格式。

    1. 数据模型
    //我们将其建在router同级目录下的model文件夹下
    class BaseModel {
        constructor(data, message) {
            if(typeof data === 'string') {
                this.message = data
                data = null
                message = null
            }
            if(data) {
                this.data = data
            }
            if (message) {
                this.message = message
            }
        }
    }
    class SuccessModel extends BaseModel {
        constructor(data, message) {
            super(data,message)
            this.errno  = 0
        }
    }
    class ErrorModel extends BaseModel {
        constructor(data, message) {
            super(data, message)
            this.errno = -1
        }
    }
    module.exports = {
        SuccessModel,
        ErrorModel
    }
    

    这就是数据模型,可以看出,这里用到了JS继承的一些东西,就是定义一个数据结构

    1. controller 层
    //我们将其建在router同级目录下的controller文件夹下
    const getList = (author, keyword) => {
        // 先返回假数据(格式是正确的)
        return [
            {
                id: 1,
                title: '标题A',
                content: '内容A',
                createTime: 1586310687741,
                author: '张三'
            },
            {
                id: 2,
                title: '标题B',
                content: '内容B',
                createTime: 1586310687741,
                author: '李四'
            }
        ]
    }
    module.exports = {
        getList
    }
    

    可以看到,这里我们只针对传入参数做响应的逻辑,并输出对应的参数,这里再次说明controller只关心数据的处理
    于是我们访问http://localhost:8000/api/blog/list?author=zhangsan&keyword=A试试吧,是不是返回了我们想要的数据结构呢。

    小结:个人认为,这一部分十分重要,我们将应用分层,不同的层写不同的代码,将各个层之间串联起来,就是一个完整的应用。好了,自己在你的编辑器上捋一捋这样的逻辑吧!

    相关文章

      网友评论

          本文标题:跟我一起学NodeJs之环境搭建,路由初始化,应用分层,路由开发

          本文链接:https://www.haomeiwen.com/subject/jjvzphtx.html