上篇文章分享了简单的三层模式和基础文件夹的创建,本篇将以示例的形式详细具体的展示Router、Controller、Service、Model之间业务处理和数据传输。

1. 班级管理数据模型创建。数据模型是通过Sequelize的ORM技术实现,关于Sequelize技术,将在后续文章中分享。

在上篇文章中的models文件夹中创建班级模型class.ts,数据结构为:ID,班级名称,班级编码,班主任ID。代码如下:

import { Table, Model, Column, DataType, PrimaryKey } from "sequelize-typescript";
import DbSequelize from "../db_config"; @Table({
tableName: 't_class'
})
export default class Class extends Model<Class> {
//唯一标识
@Column({ type: DataType.STRING, primaryKey: true })
id: string; //班级名称
@Column({ type: DataType.STRING, field: 'class_name' })
className: string; //班级编码
@Column({ type: DataType.STRING, field: 'class_code' })
classCode: string; //班主任Id
@Column({ type: DataType.STRING, field: 'head_teacher_id' })
headTeacherId: string;
} DbSequelize.addModels([Class]);

注:由于尚未讲解Sequelize相关技术,所以这里只需要明白班级结构即可。

2.班级管理服务创建。在services文件夹中创建class.ts,实现最基础的增删改查的服务方法。代码如下:

import Class from '../models/class';
var Op = sequelize.Op; //班级管理服务
export default class ClassService {
//获取所有班级
async findClassList() {
try {
return Class.findAll({
attributes: ['id', 'calssName', 'calssCode', 'headTeacherId']
});
}
catch (err) {
throw (err);
}
} //获取单个班级
async findClassById(classId: string) {
try {
return Class.findOne({
attributes: ['id', 'calssName', 'calssCode', 'headTeacherId'],
where: { id: classId }
});
}
catch (err) {
throw (err);
}
} //删除班级
async deleteClass(classId: string) {
try {
return await Class.destroy({ where: { id: classId } });
}
catch (err) {
throw (err);
}
} //修改班级
async editClass(class: any) {
try {
return await Class.update(class, { where: { id: class.id }, individualHooks: true });
}
catch (err) {
throw (err);
}
} //添加班级
async addClass(class: any) {
try {
return await Class.create(class);
}
catch (err) {
throw (err);
}
}
}

注:由于尚未讲解Sequelize相关技术,所以这里只需要明白班级服务中基础的操作就是简单的增删改查即可,有关分页,复杂查询也将在后篇中分享。

3.班级管理控制器创建。在controllers文件夹中创建class.ts,实现最基础的增删改查的业务方法。代码如下:

import ClassService from '../services/class';
const clsService = new ClassService();
//班级管理控制器
export default class ClassController {
    //查找所有班级
    static async findClassList(ctx: any) {
        try {
            //调用查询列表服务,获取结果
            let res = await clsService.findClassList();
            ctx.body = {
                status: 1,//返回码:1操作成功,0操作错误
                data: {
                    classList: res
                }
            }
        }
        catch (err) {
            ctx.throw(err.message);
        }
    }
    //根据班级id获取班级详细信息
    static async findClassById(ctx: any) {
        try {
            let id = ctx.request.query.id;
            if (!id) {
                ctx.body = {
                    status: 0
                }
                return;
            }
            //调用查询详情服务,获取结果
            let res = await clsService.findClassById(id);
            ctx.body = {
                status: 1,
                data: {
                    class: res
                }
            }
        }
        catch (err) {
            ctx.throw(err.message);
        }
    }
    //删除班级
    static async deleteClass(ctx: any) {
        try {
            let id: string = ctx.request.body.id;
            //调用删除服务,获取结果
            let res: any = await clsService.deleteClass(id);
            if (res[0] === 1 && res[1][0].delFlag === 1) {
                ctx.body = {
                    status: 1,
                    data: {
                        classId: res[1][0].id
                    }
                }
            }
            else {
                ctx.body = {
                    status: 0
                }
            }
        }
        catch (err) {
            ctx.throw(err.message);
        }
    }
    //修改班级
    static async editClass(ctx: any) {
        try {
            let obj: any = ctx.request.body;
            //调用修改服务,获取结果
            let res = await clsService.editClass(obj);
            if (res[0] !== 1) {
                ctx.body = {
                    status: 0
                }
            }
            else {
                ctx.body = {
                    status: 1,
                    data: {
                        classId: res[1][0].id
                    }
                }
            }
        }
        catch (err) {
            ctx.throw(err.message);
        }
    }
    //添加班级
    static async addClass(ctx: any) {
        try {
            let obj: any = ctx.request.body;
            //调用添加服务,获取结果
            let res = await clsService.addClass(obj);
            if (!res) {
                ctx.body = {
                    status: 0
                }
            }
            else {
                ctx.body = {
                    status: 1,
                    data: {
                        classId: res.id
                    }
                }
            }
        }
        catch (err) {
            ctx.throw(err.message);
        }
    }
}

注:此处的班级管理控制器,仅仅实现对增删改查服务的调用,后篇慢慢会添加班级对班主任信息的获取等相关业务逻辑的操作。

4. 设置路由

4.1 添加路由中间件

npm i koa-router
npm i @types/koa-router

4.2 在router.ts中,添加如下代码:

import KoaRouter from 'koa-router';
//引入班级管理控制器
import ClassController from './controllers/class';
const router = new KoaRouter();
router.post('/api/class/addClass', ClassController.addClass);
router.post('/api/class/editClass', ClassController.editClass);
router.post('/api/class/deleteClass', ClassController.deleteClass);
router.get('/api/class/findClassById', ClassController.findClassById);
router.get('/api/class/findClassList', ClassController.findClassList);
export default router;

4.3 在app.ts中,添加路由中间件

const Koa = require('koa');
const app = new Koa(); //引入路由
import router from './router';
//添加路由中间件
app.use(router.routes());
app.use(router.allowedMethods()); app.use(async (ctx: any) => {
ctx.body = 'Hello World...Hello LaoLv';
}); console.log('app server start on port 3000...')
app.listen(3000);

这样,整个router--controller--service--model之间的数据调用基本完成,但是由于sequlize没有安装,大家如果直接复制代码会报错,所以,以上代码仅仅是一个熟悉了解整个过程。

下面,大家可以把model,service中的代码都注释掉,修改controller和router,简单运行一个路由作为举例。

controllers-->class.ts

//班级管理控制器
export default class ClassController {
//查找所有班级
static async findClassList(ctx: any) {
try {
ctx.body = {
status: 1,//返回码:1操作成功,0操作错误
data: {
classList: '这是测试数据'
}
}
}
catch (err) {
ctx.throw(err.message);
}
}
}

router.ts:

import KoaRouter from 'koa-router';
//引入班级管理控制器
import ClassController from './controllers/class'; const router = new KoaRouter();
router.get('/api/class/findClassList', ClassController.findClassList); export default router;

这样,代码就不会报错了,然后F5,我们运行一下:

1. 控制台输出成功

2. 浏览器显示成功

3. 浏览器输入  /api/class/findClassList,看看结果

以上三条,证明路由调用成功:调用controller中相关方法。后面再细致分享router,sequelize相关技术知识点。

附:代码结构如下

Vue2+Koa2+Typescript前后端框架教程--04班级管理示例(路由调用控制器)的更多相关文章

  1. Vue2+Koa2+Typescript前后端框架教程--03后端路由和三层模式配置

    昨天将Koa2的基础框架和自动编译调试重启服务完成,今天开始配置路由和搭建基础的三层架构模式. 路由中间件:koa-router,即路由导航,就是我们平时使用最广泛的get/post方法执行的URL路 ...

  2. Vue2+Koa2+Typescript前后端框架教程--05Sequelize的使用(ORM)

    本篇开始分享Node.js后端服务开发中对于数据结构ORM的实现,主要使用的技术栈是:Sequelize. 上一篇文章中讲到班级管理的数据结构:ID,班级名称,班级编码,班主任ID,使用的数据库是My ...

  3. ABP开发框架前后端开发系列---(10)Web API调用类的简化处理

    在较早期的随笔<ABP开发框架前后端开发系列---(5)Web API调用类在Winform项目中的使用>已经介绍了Web API调用类的封装处理,虽然这些调用类我们可以使用代码生成工具快 ...

  4. ABP开发框架前后端开发系列---(5)Web API调用类在Winform项目中的使用

    在前面几篇随笔介绍了我对ABP框架的改造,包括对ABP总体的介绍,以及对各个业务分层的简化,Web API 客户端封装层的设计,使得我们基于ABP框架的整体方案越来越清晰化, 也越来越接近实际的项目开 ...

  5. 快速web开发中的前后端框架选型最佳实践

    这个最佳实践是我目前人在做的一个站点,主要功能: oauth登录 发布文章(我称为"片段"),片段可以自定义一些和内容有关的指标,如“文中人物:12”.支持自定义排版.插图.建立相 ...

  6. com.panie 项目开发随笔_前后端框架考虑(2016.12.8)

    (一) 近日和一同学联系,说了我想要做一个网站的打算.她很感兴趣.于是我们协商了下,便觉得一起合作.她写前端,我写后台.因为我对于前端样式设计并不怎么熟悉. (二) 我们决定先做一个 个人博客. 网上 ...

  7. VSCode 完美整合前后端框架(angular2+.NET core)

    首先打开命令行查看本地.NET版本. 通过命令行安装模板. dotnet new --install Microsoft.AspNetCore.SpaTemplates::* 创建demo目录,并用v ...

  8. ABP开发框架前后端开发系列---(4)Web API调用类的封装和使用

    在前面随笔介绍ABP应用框架的项目组织情况,以及项目中领域层各个类代码组织,以及简化了ABP框架的各个层的内容,使得我们项目结构更加清晰.上篇随笔已经介绍了字典模块中应用服务层接口的实现情况,并且通过 ...

  9. Spring Boot + Vue 前后端分离开发,权限管理的一点思路

    在传统的前后端不分的开发中,权限管理主要通过过滤器或者拦截器来进行(权限管理框架本身也是通过过滤器来实现功能),如果用户不具备某一个角色或者某一个权限,则无法访问某一个页面. 但是在前后端分离中,页面 ...

随机推荐

  1. [BUGCASE]层叠上下文和z-index属性使用不当引发的文本被遮挡的问题

    一.问题描述 在一个fixed-data-table(一个React组件)制作的表格中,需要给表头的字段一个提示的特效,所以做了一个提示层 这个提示层被固定(拖动表格的水平滚动条时固定)的表格列遮住 ...

  2. centos7安装Python的虚拟环境

    1. 安装virtualenv.virtualenvwrapper # pip3 install virtualenv # pip3 install virtualenvwrapper 2. 进入.b ...

  3. Spark SQL解析查询parquet格式Hive表获取分区字段和查询条件

    首先说一下,这里解决的问题应用场景: sparksql处理Hive表数据时,判断加载的是否是分区表,以及分区表的字段有哪些?再进一步限制查询分区表必须指定分区? 这里涉及到两种情况:select SQ ...

  4. Golang 实现 Redis(8): TCC分布式事务

    本文是使用 golang 实现 redis 系列的第八篇, 将介绍如何在分布式缓存中使用 Try-Commit-Catch 方式来解决分布式一致性问题. godis 集群的源码在Github:Godi ...

  5. PyQt(Python+Qt)学习随笔:Qt Designer中主窗口对象的dockOptions属性

    dockOptions属性代表主窗口对浮动部件停靠的反应,其类型为枚举类型QMainWindow.DockOptions.相关取值及含义如下: 这些枚举值可以组合使用,仅控制如何在QMainWindo ...

  6. 扩展Linux网络栈

    扩展Linux网络栈 来自Linux内核文档.之前看过这篇文章,一直好奇,问什么一条网络流会固定在一个CPU上进行处理,本文档可以解决这个疑问.为了更好地理解本文章中的功能,将这篇文章穿插入内. 简介 ...

  7. Jmeter录制脚本-BadBoy

    录制脚本方式: 1)Badboy录制Jmter脚本 2)Jmter代理服务录制脚本 方式一:Badboy录制脚本 安装Badboy 录制脚本 1.双击Badboy 2.输入URL 3.点击" ...

  8. 斜率优化DP复习笔记

    前言 复习笔记2nd. Warning:鉴于摆渡车是普及组题目,本文的难度定位在普及+至省选-. 参照洛谷的题目难度评分(不过感觉部分有虚高,提高组建议全部掌握,普及组可以选择性阅读.) 引用部分(如 ...

  9. NOI Online #1 入门组 魔法

    全网都是矩阵快速幂,我只会倍增DP 其实这题与 AcWing 345. 牛站 还是比较像的,那题可以矩阵快速幂 / 倍增,这题也行. 先 \(Floyd\) 预处理两点之间不用魔法最短距离 \(d_{ ...

  10. SpringCloud 源码系列(4)—— 负载均衡 Ribbon

    一.负载均衡 1.RestTemplate 在研究 eureka 源码上篇中,我们在 demo-consumer 消费者服务中定义了用 @LoadBalanced 标记的 RestTemplate,然 ...