koa2路由与mvc搭建初步
接着上一篇《Js全栈开发之koa2初步搭建及基础》来继续学习koa2,上一篇只是简单的了解一下koa原生的web服务搭建,实际的复杂项目需要很多中间件来提升开发效率,和减少编码的复杂度,这篇主要涉及路由拆分与mvc项目结构的初步搭建,包含router路由层,controller控制层及service服务层。
文章目录
1. koa-router路由
使用koa-router中间件来简化路由的配置。先通过 npm管理工具进行安装,先安装koa-router路由包,再安装koa-bodyparser参数解析包,安装顺序随意,但代码中koa-router和koa-bodyparser这两个中间件的加载顺序是有先后关系的,这段代码中是bodyParser在前先加载。
1.1 安装koa-router
npm install koa-router -save
npm install koa-bodyparser -save
1.2 示例代码
使用示例代码
const Koa = require('koa')
const router = require('koa-router')()
const bodyParser = require('koa-bodyparser')
const app = new Koa()
app.use(bodyParser())
// http://localhost:3000/
router.get('/', async(ctx, next) => {
ctx.response.body = `<h1>index page</h1>`
})
// http://localhost:3000/home
router.get('/home', async(ctx, next) => {
console.log(ctx.request.query)
console.log(ctx.request.querystring)
ctx.response.body = '<h1>HOME page</h1>'
})
// http://localhost:3000/home/1/dahlin
router.get('/home/:id/:name', async(ctx, next)=>{
console.log(ctx.params)
ctx.response.body = `Hello ${ctx.params.id}, ${ctx.params.name}`
})
// http://localhost:3000/404
router.get('/404', async(ctx, next) => {
ctx.response.body = '<h1>404 Not Found</h1>'
})
// http://localhost:3000/user
router.get('/user', async(ctx, next)=>{
ctx.response.body =
`
<form action="/user/register" method="post">
<input name="name" type="text" placeholder="请输入用户名:dahlin" value="dahlin"/>
<br/>
<input name="password" type="text" placeholder="请输入密码:123456" value="123456"/>
<br/>
<button>GoGoGo</button>
</form>
`
})
// http://localhost:3000/user/register
// 增加响应表单请求的路由
router.post('/user/register',async(ctx, next)=>{
let {name, password} = ctx.request.body
if( name == 'dahlin' && password == '123456' ){
ctx.response.body = `Hello, ${name}!`
}else{
ctx.response.body = '账号信息错误'
}
})
app.use(router.routes())
app.listen(3000, () => {
console.log('server is running at http://localhost:3000')
})
1.3 postman测试
执行效果
2. mvc架构搭建
mvc的原理就不多说了,Java里的Spring MVC,C#里的Asp.Net MVC,Python里的Django等都采用了MVC的架构,基本主流编程技术栈的web服务框架,基本全是MVC结构,架构设计也都大同小异,理论上只要掌握一种,其他的也能很快掌握。
下面举例koa2的mvc结构,其实都是人为的划分目录和拆分模块。
2.1 mvc项目结构
先在项目根目录下新建controller文件夹及service文件夹,之后在controller目录下新建home.js文件,在service目录下新建home.js文件。
并在根目录下新建router.js文件,用以编写拆分出的路由源码。
简单的mvc项目结构如下:
- controller
--- home.js
- service
--- home.js
- router.js
- app.js
2.2 路由拆分源码
router.js中路由源码。
const router = require('koa-router')()
const HomeController = require('./controller/home')
module.exports = (app) => {
router.get( '/', HomeController.index )
router.get('/home', HomeController.home)
// http://localhost:3000/home/1/dahlin
router.get('/home/:id/:name', HomeController.homeParams)
router.get('/user', HomeController.login)
router.post('/user/register', HomeController.register)
app.use(router.routes())
.use(router.allowedMethods())
}
2.3 控制器拆分源码
controller.js控制器源码。
const HomeService = require('../service/home')
module.exports = {
index: async(ctx, next) => {
ctx.response.body = `<h1>index page</h1>`
},
home: async(ctx, next) => {
console.log(ctx.request.query)
console.log(ctx.request.querystring)
ctx.response.body = '<h1>HOME page</h1>'
},
homeParams: async(ctx, next) => {
console.log(ctx.params)
ctx.response.body = `<h1>Hello ${ctx.params.id}, ${ctx.params.name}</h1>`
},
login: async(ctx, next) => {
ctx.response.body =
`
<form action="/user/register" method="post">
<input name="name" type="text" placeholder="请输入用户名:dahlin" value="dahlin"/>
<br/>
<input name="password" type="text" placeholder="请输入密码:123456" value="123456"/>
<br/>
<button>提交</button>
</form>
`
},
register: async(ctx, next) => {
let {
name,
password
} = ctx.request.body
let data = await HomeService.register(name, password)
ctx.response.body = data
}
}
2.4 服务层拆分源码
service.js服务层源码。
module.exports = {
register: async(name, pwd) => {
let data
if (name == 'dahlin' && pwd == '123456') {
data = `Hello, ${name}!`
} else {
data = '账号信息错误'
}
return data
}
}
2.5 启动入口代码
app.js 为程序启动入口代码,类似Java中的main方法。
const Koa = require('koa')
const bodyParser = require('koa-bodyparser')
const app = new Koa()
const router = require('./router')
app.use(bodyParser())
router(app)
app.listen(3000, () => {
console.log('server is running at http://localhost:3000')
})
总体来讲,就是入口方法app.js调用router层中匹配的路由,router路由调用controller层中对应的方法,controller中的方法再调用service中的单一的业务逻辑功能,当然最后返回的响应还是在controller层中。这里没有用模板把视图层从controller层拆分出来,视图层的分离在下一篇中进行总结。