Koa项目总结一(koa路由与配置)

1. Koa 路由
路由(Routing)是由一个URI(或者叫路径)和一个特定的HTTP 方法(GET、POST 等)组成的,涉及到应用如何响应客户端对某个网站节点的访问。
通俗的讲:路由就是根据不同的URL 地址,加载不同的页面实现不同的功能。
1.1 Koa 中我们需要安装koa-router 路由模块来实现路由配置:

  • 安装koa-router:
npm install --save koa-router

  • 简单的koa-router配置路由的代码:
/*app.js*/ const Koa = require('koa'); const router = require('koa-router')(); //注意:引入的方式 const app = new Koa(); router.get('/', function (ctx, next) { ctx.body="Hello koa"; }) router.get('/news',(ctx,next)=>{ ctx.body="新闻page" }); app.use(router.routes()); //作用:启动路由 app.use(router.allowedMethods()); /* 作用: 这是官方文档的推荐用法,我们可以看到router.allowedMethods()用在了路由匹配 router.routes()之后,目的在于:根据ctx.status 设置response 响应头 */ app.listen(3000,()=>{ console.log('starting at port 3000'); });

1.2 Koa 路由get 传值 【Koa项目总结一(koa路由与配置)】在koa2 中GET 传值通过request 接收,但是接收的方法有两种:queryquerystring
  • query:返回的是格式化好的参数对象。
  • querystring:返回的是请求字符串。
  • 获取get请求参数的代码:
/*app.js*/ const Koa = require('koa'); const Router = require('koa-router'); const app = new Koa(); const router = new Router(); router.get('/', (ctx, next) => { ctx.body="Hello koa"; }) router.get('/newscontent',(ctx,next)=>{ let url =ctx.url; //从request 中获取GET 请求 let request =ctx.request; let req_query = request.query; let req_querystring = request.querystring; //从上下文中直接获取 let ctx_query = ctx.query; let ctx_querystring = ctx.querystring; ctx.body={ url, req_query, req_querystring, ctx_query, ctx_querystring } }); app.use(router.routes()); //作用:启动路由 app.use(router.allowedMethods()); //作用: 当请求出错时的处理逻辑 app.listen(3000,()=>{ console.log('starting at port 3000'); });

1.3 Koa 动态路由
//请求方式http://域名/product/123 router.get('/product/:aid',async (ctx)=>{ console.log(ctx.params); //{ aid: '123' } //获取动态路由的数据 ctx.body='这是商品页面'; });

2. post提交数据的路由配置
2.1 koa-bodyparser获取post提交的数据: router.post('/uri')用于配置POST路由,koa-bodyparser中间件,用来解析POST请求通过表单提交的数据,让我们很方便的获取解析的POST数据,下面是表单页面提交数据和对POST数据解析的示例代码:
/*表单页面,提交地址为/user/login*/ router.get('/user', async (ctx, next)=>{ ctx.body = `


` }); /**router.post()配置post路由 */ router.post('/user/login', async (ctx, next)=>{ /**ctx.request.body为解析的post数据对象 */ /**{name:'joyitsai', password:'123456'} */ let {name, password} = ctx.request.body; if(name == 'joyitsai' && password=='123456'){ ctx.body = `Hello ${name}`; }else{ ctx.body = '账号信息错误' } })

访问localhost:3000/user如下图:

Koa项目总结一(koa路由与配置)
文章图片
登录页面
3. Koa项目中的router路由分离:
以上所有的路由配置代码都集中在app.js文件中,随着项目复杂度增加、业务需求变更,这种做法会给后期的维护工作带来很大的麻烦。我们应该利用MVC模式思路来优化代码。
3.1 分离Router: 路由部分的代码可以分离成独立的文件,并根据项目结构放在合适的位置和命名,方便管理。在本示例代码中,将上面的登录页面和提交登录数据的代码独立在login.js文件中,结构如下:
|——app.js |——routes |——login.js

路由部分的文件代码:
/*login.js*/ const router = require('koa-router')(); module.exports = (app) => { /**表单页面,提交地址为/user/login */ router.get('/user', async (ctx, next)=>{ ctx.body = `


` }); /**router.post()配置post路由 */ router.post('/user/login', async (ctx, next)=>{ /**ctx.request.body为解析的post数据对象 */ //{name:'joyitsai', password:'123456'} console.log(ctx.request.body); let {name, password} = ctx.request.body; if(name == 'joyitsai' && password=='123456'){ ctx.body = `Hello ${name}`; }else{ ctx.body = '账号信息错误' } }) app.use(router.routes()).use(router.allowedMethods()); }

路由部分的代码提取成功后,需要在app.js中引入login.js
// 引入Koa const Koa = require('koa'); const router = require('koa-router')(); /**引入并实例化koa-router */ const bodyParser = require('koa-bodyparser'); const app = new Koa(); app.use(bodyParser()); /*如果有多个路由文件,按照下面同样的方式引入,并应用在app上*/ const loginRouter = require('./routes/login'); loginRouter(app); app.listen(3000, ()=>{ console.log('cake app running at port 3000') })

现在项目中只有一个路由文件,并且对HTTP请求的处理函数也很简单,然而随着项目变更,login.js同样会变得臃肿起来,这时就需要进一步优化分离:
3.2 分离controller 对login.js再次进行优化分离,将对应路由的相应函数提取出来,防止在单独的文件controller/login.js中,结构如下:
|——app.js |——routes ||——login.js |——controller |——login.js

controller/login.js,存放响应routes/login.js中配置的路由的业务逻辑代码:
module.exports = { user: async (ctx, next) => { ctx.body = `


` },login: async (ctx, next)=>{ /**ctx.request.body为解析的post数据对象 */ console.log(ctx.request.body); let {name, password} = ctx.request.body; if(name == 'joyitsai' && password=='123456'){ ctx.body = `Hello ${name}`; }else{ ctx.body = '账号信息错误' } } }

业务逻辑代码分离之后,需要修改该routes/login.js文件,在文件中引入controller/login.js,并以其中的函数作为路由的响应函数,代码如下:
const router = require('koa-router')(); const LoginController = require('../controller/login'); module.exports = (app) => { /**表单页面,提交地址为/user/login */ router.get('/user', LoginController.user); /**router.post()配置post路由 */ router.post('/user/login', LoginController.login); app.use(router.routes()).use(router.allowedMethods()); }

经过上面两次代码分离之后,此时项目结构已经比价清晰了。但实际开发中,Koa需要进行一些数据访问层的操作,如操作数据库、调用第三方接口获取数据等,这些操作需要分离出Service层进行处理。相应的,Controller层只需进行业务逻辑部分的处理。
3.3 分离Service: 在service/login.js中,用于抽离controller/login.js中的数据访问相关的代码,结构如下:
|——app.js |——routes ||——login.js |——controller ||——login.js |——service |——login.js

service/login.js代码如下:
module.exports = { getUserdata: async (username)=>{ /**这里结合数据库操作,通过username获取数据库中的用户数据,省略相关代码*/ let userdata = https://www.it610.com/article/{username:'joyitsai', password:'123456'} /**查询到了userdata,返回 */ return userdata; } }

在controller/login.js中引入service/login.js:
const LoginService = require('../service/login'); module.exports = { // .....省略表单页面代码 login: async (ctx, next)=>{ /**ctx.request.body为解析的post数据对象 */ let {name, password} = ctx.request.body; /*通过name去数据库查询用户数据*/ let userdata = https://www.it610.com/article/LoginService.getUserdata(name); if(name == userdata.username && password == userdata.password){ ctx.body = `Hello ${name}`; }else{ ctx.body ='账号信息错误' } } }

    推荐阅读