koa框架(二) mvc 模式及实现一个koa框架的web服务

news2024/12/23 11:01:19

mvc三层架构

  • mvc, 即 model 、controller、view;
  • mvc模式将model、view、controller分离;使用mvc分层是系统更加灵活,扩展性更强。让程序更加直观、复用性更强、可维护性更强。
    • model 负责数据访问;
    • controller 负责消息处理;
    • view 负责视图呈现。
      在这里插入图片描述

利用mvc模式实现后端分层

  • mvc分层开发模式: web server : 用户发起请求 => 分析用户请求,处理路由 => 处理数据(操作数据库,操作缓存)=> view(data+template)=> response。即 controller => model => view。
    在这里插入图片描述

实现一个koa框架的web服务

  • app.js
const Koa = require('koa');
const KoaRouter = require('koa-router');
const KoaStaticCache = require('koa-static-cache');
const koaBody = require('koa-body');
// 控制器加载
const mainController = require('./contollers/main');
const userController = require('./contollers/user');
const itemController = require('./contollers/item');
const server = new Koa();
const router = new KoaRouter();
// 静态资源处理
server.use( KoaStaticCache('./public', {
    prefix: '/public',
    gzip: true,
    dynamic: true
}) );
// body 解析中间件
server.use( koaBody({
    multipart: true,
    // 处理上传的二进制文件
    formidable: {
        // 上传目录
        uploadDir: __dirname + '/public/upload',
        // 是否保留上传文件名后缀
        keepExtensions: true
    }
}));
router.get('/', mainController.index);
router.get('/user/register', userController.register);
router.get('/user/login', userController.login);
router.get('/item/add', itemController.add);
router.post('/item/add', itemController.addPost);
server.use( router.routes() );
server.listen(8081, () => {
    console.log('服务启动成功:http://localhost:8081')
});
  • controller/main.js
const tpl = require('../libs/tpl');
const itemsModel = require('../models/items');
module.exports = {
    index: async ctx => {
        let items = await itemsModel.getItems();
        ctx.body = tpl.render('index.html', {
            items
        });  
    }
}
  • controller/user.js
const tpl = require('../libs/tpl');
module.exports = {
    register: async ctx => {
        ctx.body = '注册';
    },
    login: async ctx => {
        ctx.body = '登陆'
    }
}
  • controller/item.js
const tpl = require('../libs/tpl');
const categoriesModel = require('../models/categories');
const itemsModel = require('../models/items');
module.exports = {
    add: async ctx => {
        let categories = await categoriesModel.getCategories();
        ctx.body = tpl.render('add-item.html', {
            categories
        });
    },
    addPost: async ctx => {
        let data = ctx.request.body;
        let files = ctx.request.files;
        let filename = '';
        if (files && files.cover) {
            let lastPos = files.cover.path.lastIndexOf('/');
            filename = files.cover.path.substring(lastPos+1);
        }
        let rs = await itemsModel.addItem([
            data.category_id,
            data.name,
            data.price,
            filename
        ]);
        console.log('rs', rs);
        ctx.body = '添加成功';   
    }
}
  • libs/tpl.js
const nunjucks = require('nunjucks');
// 载入模板引擎
const tpl = new nunjucks.Environment(
    // FileSystemLoader => node 模板文件加载
    new nunjucks.FileSystemLoader('views', {
        watch: true,
        noCache: true
    })
);
module.exports = tpl;
  • models/items.js
const db = require('./model');
module.exports = {
    getItems() {
        return new Promise( (resolve, reject) => {
            db.query("select * from `items`", function(err, rs) {
                if (err) {
                    reject(err);
                } else {
                    resolve(rs);
                }
            });
        } )
    },
    addItem(newData) {
        return new Promise( (resolve, reject) => {
            db.query("insert into `items` (`category_id`, `name`, `price`, `cover`) values (?, ?, ?, ?)", newData, function(err, rs) {
                if (err) {
                    reject(err);
                } else {
                    resolve(rs);
                }
            });
        } )
    }
}
  • models/categories.js
const db = require('./model');
module.exports = {
    getCategories() {
        return new Promise( (resolve, reject) => {
            db.query("select * from `categories`", function(err, rs) {
                if (err) {
                    reject(err);
                } else {
                    resolve(rs);
                }
            });
        } )
    }
}
  • models/model.js
const mysql2 = require('mysql2');
// 数据链接不推荐使用use中间件
let db = mysql2.createConnection({
    host: '127.0.0.1',
    port: 3306,
    user: 'root',
    password: 'Chen@123',
    database: 'test'
});
module.exports = db;
  • views/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="/public/css/css.css" />
</head>
<body>
    <div id="app">
        <header id="header">
            <a href="/" id="logo"></a>
            <nav id="nav">
                <a href="">1</a>
                <a href="">笔记本</a>
                <a href="">家居</a>
            </nav>
            <div id="user">
                <a href="">登录</a>
                <a href="">注册</a>
            </div>
        </header>
        <div id="main"> 
            <ul class="items-list">
                {%for item in items%}
                <li class="panel">
                    <img src="/public/upload/{{item.cover}}" alt="" class="cover">
                    <div class="name">{{item.name}}</div>
                    <div class="price">¥ {{(item.price / 100).toFixed(2)}}</div>
                </li>
                {%endfor%}
            </ul>
            <div class="pagination-container">
                <div class="pagination">
                    <a href="" class="prev">上一页</a>
                    <a href="">1</a>
                    <a href="">2</a>
                    <a href="">3</a>
                    <a href="" class="current">4</a>
                    <a href="">5</a>
                    <a href="">6</a>
                    <a href="">7</a>
                    <a href="">8</a>
                    <a href="" class="next">下一页</a>
                </div>
    
            </div>
        </div>
    </div>
</body>
</html>
  • views/add-item.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="/public/css/css.css" />
</head>
<body> 
    <header id="header">
        <a href="/" id="logo"></a>
        <nav id="nav">
            <a href="">1</a>
            <a href="">笔记本</a>
            <a href="">家居</a>
        </nav>
        <div id="user">
            <a href="">登录</a>
            <a href="">注册</a>
        </div>
    </header>
    <div id="main">
        <!-- 
            application/x-www-form-urlencoded: 把数据组织成 urlencode的格式
                key=value&key=value...
                适用于普通字符内容提交,提交的数据为纯字符
            multipart/form-data:二进制数据格式
                适用于提交的数据为非纯字符,如图片,视频等
         -->
       <div class="panel">
           <h2>添加新商品</h2>
           <form action="" method="post" enctype="multipart/form-data">
                <div class="form-item">
                    <label>
                        <span class="txt">商品分类:</span>
                        <select name="category_id">
                            <option value="">请选择商品分类</option>
                            {%for category in categories%}
                            <option value="{{category.id}}">{{category.name}}</option>
                            {%endfor%}
                        </select>
                    </label>
                </div>
                <div class="form-item">
                    <label>
                        <span class="txt">商品名称:</span>
                        <input type="text" class="form-input" name="name">
                    </label>
                </div>
                <div class="form-item">
                    <label>
                        <span class="txt">价格:</span>
                        <input type="text" class="form-input" name="price">
                    </label>
                </div>
                <div class="form-item">
                    <label>
                        <span class="txt">封面:</span>
                        <input type="file" name="cover" />
                    </label>
                </div>
                <div class="form-item">
                    <label>
                        <span class="txt"></span>
                        <button class="form-button primary">确认添加</button>
                    </label>
                </div>
           </form>
       </div>    
    </div>
</body>
</html>
  • public下的静态文件省略…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/21260.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

嵌入式设备文件系统构建——增加用户登录功能

1、修改inittab文件 #first:run the system script file ::sysinit:/etc/init.d/rcS# 进入命令行 #::askfirst:-/bin/sh#添加执行登录验证 ::sysinit:/bin/login::ctrlaltdel:-/sbin/reboot #umount all filesystem ::shutdown:/bin/umount -a -r #restart init process ::res…

2022-11-16 几种三角函数的图形

为了方便查看几个函数的关系图&#xff0c;记录一下几种三角函数的大致图像。 三角函数&#xff1a;tan⁡(x)\tan(x)tan(x)&#xff0c;cos⁡(x)\cos(x)cos(x)&#xff0c;sin⁡(x)\sin(x)sin(x)。 三角函数&#xff1a;tan⁡(x2)\tan(\dfrac{x}{2})tan(2x​)&#xff0c;cos…

盘点 三款高可用的机器学习模型 web页面化的工具(一)

笔者只是抛砖引玉&#xff0c;把三款看到的在本篇简单的介绍。 如果有其他更好的欢迎留言推荐&#xff0c;后续笔者会对这三款做一一的学习。 文章目录1 streamlit2 Gradio3 codepen1 streamlit 笔者之前写过该专题&#xff1a; python︱写markdown一样写网页&#xff0c;代码…

SpringCloud - 项目搭建

文章目录1.创建父工程项目2.父工程POM配置3.创建RestFul 服务器3.1 支付模块3.1.1 创建module3.1.2 改POM3.1.3 写YML3.1.4 主启动3.1.5 业务类3.2 订单模块3.2.1 创建module3.2.2 改POM3.2.3 写YML3.2.4 主启动3.2.5 业务类4.工程重构1.创建父工程项目 打开IDEA 创建一个Mave…

从零开始的深度学习之旅(1)

目录0.前言1.单层神经网络1.1 单层神经网络基础(线性回归算法)1.2 torch.nn.Linear实现单层回归神经网络的正向传播2.二分类神经网络&#xff1a;逻辑回归2.1 逻辑回归与门代码实现2.2 符号函数2.2.1 sign函数2.2.2 Relu函数2.2.3 tant函数3. 多分类神经网络&#xff1a;Softma…

Vue:实战快速上手

采用实战模式并结合ElementUI 组件库&#xff0c;将所需知识点应用到实际中&#xff0c;以最快速度掌握Vue的使用; 桌面化应用 ElementUI: https://element.eleme.cn/#/zh-CN/ 弹窗 LayUI 的 layer &#xff08;由于官网已下架&#xff0c;在此使用镜像): https://www.layui.s…

【网页设计】基于HTML在线图书商城购物项目设计与实现_(图书商城10页) bootstarp响应式

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 在线商城购物 | 水果商城 | 商城系统建设 | 多平台移动商城 | H5微商城购物商城项目 | HTML期末大学生网页设计作业&#xff0c;Web大学生网页 HTML&a…

[附源码]java毕业设计停车场信息管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

抢购软件使用方法(如何开发抢购软件)

如果做抢购软件的话需要好的协议以及算法&#xff0c;我用的这份协议目前非常稳定&#xff0c;所以今天给大家讲解下抢购软件的流程以及使用方法 01软件设置选项详解 一、无障碍服务 二、使用网路时间 软件第一行一般都是当前设备比XX慢了&#xff08;快了&#xff09;XXms&…

Vue3铺垫知识【ES6 模块化、Promise、async/await、EventLoop、宏任务和微任务、总结】

文章目录ES6 模块化1. 回顾&#xff1a;node.js 中如何实现模块化2. 前端模块化规范的分类3. 什么是 ES6 模块化规范4. 在 node.js 中体验 ES6 模块化5. ES6 模块化的基本语法5.15.1.1 默认导出5.1.2 默认导入5.1.3 默认导出的注意事项5.1.4 默认导入的注意事项5.25.2.1 按需导…

Python:Linux下安装Anaconda,可多人使用(内容几乎完整)

前言 前言属于与内容无关的写作意图。要看正文&#xff0c;请直接跳转至本文主要内容。 很久不见。最近手里有很多事&#xff0c;比如&#xff0c;体检、装机、加班。再加上我现在为了速记&#xff0c;会把东西记到跨平台的笔记软件“OneNote”&#xff08;大画板&#xff0c…

尚医通 (二十六) --------- 科室接口开发

目录一、上传科室接口1. 添加科室基础类2. 上传科室二、查询科室接口三、删除科室接口一、上传科室接口 1. 添加科室基础类 A、添加 model 说明&#xff1a;由于实体对象没有逻辑&#xff0c;我们已经统一导入 com.fancy.yygh.model.hosp.Department B、添加 repository 添…

多元正态分布

最广为使用的基于模型的聚类方法依赖于多元正态分布。多元正态分布是对p个变量正态分布的一种推广。该分布使用一组均值和协方差矩阵∑定义。协方差矩阵是变量间相关性的度量. 协方差矩阵∑由p个方差以及所有变量对的协方差σi,ji≠j&#xff09;构成。矩阵的行和列均用变量表…

闲活一:一步登天

标题不希望能被人搜到&#xff0c;因为目前没有任何技术含量&#xff0c;可行性也偏低&#xff0c;纯纯的预研阶段。 项目起步阶段是最无从下手的阶段&#xff0c;还是先明确大目标。我这个赛车要做什么&#xff0c;怎样去做。 做什么 我脑中蹦出的大方向是这样的 玩家体…

初识Matter协议

初识Matter协议什么是MatterMatter有什么用Matter的核心优势Matter网络的组网方式什么是Matter Matter的概念最初在2019年12月被提出&#xff0c;当时被称为CHIP(Connected Home Over IP)&#xff0c;之后在2021年5月作为全新的连接标准被正式提出。 CHIP是由AWS、Google、App…

1. 算法简介

1.2 二分查找 二分查找是一种算法&#xff0c;其输入是一个有序的元素列表。如果要查找的元素包含在列表中&#xff0c;二分查找返回其位置; 否则返回null 。 使用二分查找时&#xff0c;最多需要检查log n 个元素。 仅当列表是有序的时候&#xff0c;二分查找才管用。 完整…

XCTF1-web php

场景一&#xff1a;simple_php 题目描述 小宁听说php是最好的语言,于是她简单学习之后写了几行php代码。 进入场景 给了php代码&#xff0c;分析一下 GET传入两个参数a,b aaa_GET[“a”];其中的是为了防止没有$_GET[‘a’]出现错误提示 $a0 and a&#xff1a;a等于0,且a是…

Spring之Bean生命周期之二--- Instantiation阶段

在BeanFactory中&#xff0c;主要的流程就是创建Bean的过程&#xff0c; // 核心方法: 创建Bean实列对象,并且生命周期的动作大部分都在这里。Object beanInstance doCreateBean(beanName, mbdToUse, args);Bean的生命周期包括: 实例化设置属性值初始化值销毁 实例化Bean在…

[附源码]java毕业设计网上报销管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

西电计网ARP欺骗实验

ARP欺骗实验 文章目录ARP欺骗实验Cloud云设备连接本机网卡ARP欺骗实验Cain基本设置主机发现ARP欺骗的原理实现Cain干了啥DNS欺骗实验Cain干了啥欺骗转发实验Cloud云设备 想查一下华为官方使用手册,看看云到底是个啥,但是查不到. 在ensp模拟器中云设备这篇博客上这样写的: eNS…