上篇文章分享了简单的三层模式和基础文件夹的创建,本篇将以示例的形式详细具体的展示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. LaTeX相关自学文档

    install-latex-guide-zh-cn: lshort-zh-cn: 百度网盘链接:https://pan.baidu.com/s/1cBv9Fu8KFaf0QFZ7_slxmw 提取码: ...

  2. Visual Studio 调试技巧之即时窗口的妙用

    在 Visual Studio 中有一个窗口叫 Immediate 窗口,中文版本应该叫即时窗口.默认会在你启动调试时在 VS 编辑器中弹出来.你也可以通过 Debug | Windows | Imm ...

  3. LeetCode 038 Count and Say

    题目要求:Count and Say The count-and-say sequence is the sequence of integers beginning as follows:1, 11 ...

  4. for循环与while循环

    1.两中循环的语法结构 for循环结构: for(表达式1;表达式2;表达式3) { 执行语句; } while循环结构: while(表达式1) { 执行语句; } 2.两者区别: 应用场景:由于f ...

  5. Java面试专题-多线程篇(2)- 锁和线程池

  6. PyQt(Python+Qt)学习随笔:Model/View中的枚举类 Qt.MatchFlag的取值及含义

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 枚举类 Qt.MatchFlag描述在模型中搜索项时可以使用的匹配类型,它可以在QStandardI ...

  7. Python学习随笔:使用xlwings读取和操作Execl文件

    一.背景 有2种模块可以对Execl文件,一种是xlwt 方式,需要安装三个库文件 xlrd(读Excel)xlwt(写Excel)xlutils(修改Excel),也是网上介绍文章最多的一种方法,一 ...

  8. windows+jenkins+iis 部署

    1.安装jenkins 下载地址:https://www.jenkins.io/download/ 2.需要配置java环境 配置教程:https://www.cnblogs.com/liuxiaoj ...

  9. Libp2p 简介

    这是一个翻译的系列文章,原文参考:Introduction :: libp2p Documentation 欢迎来阅读libp2p相关文档,不论你是刚开始学习如何用libp2p来搭建P2P系统, 还是 ...

  10. Nginx 转发时的一个坑,运维居然让我背锅!!

    最近遇到一个 Nginx 转发的坑,一个请求转发到 Tomcat 时发现有几个 http header 始终获取不到,导致线上出现 bug,运维说不是他的问题,这个锅我背了. 新增的几个 header ...