node 搭建基于 koa 的简单服务

Koa 是基于 node.js 平台平台的 web 开发框架,如今也被广泛地运用,中文官方地址:Koa

本文将介绍 Koa 的简单应用,并且依托 Koa 搭建一个简单的 web 服务

首先,我们需要先通过 npm i koa 安装 koa,然后在项目中引入:

const Koa = require("koa");
const app = new Koa();

app.use(async (ctx) => {
  ctx.body = "Hello World";
});

app.listen(3000);

配置模板引擎

如下:

//配置模板引擎
//引入koa-views  并且配置模板引擎
const views = require("koa-views");
app.use(
  views("views", {
    // 模板放在views文件夹中,当调用 await ctx.render('index') 则到views文件夹中去对应的模板
    extension: "ejs", //这样配置,模板的后缀名是ejs
  })
);

app.use(
  views("views", {
    map: { html: "ejs" }, //这样配置,模板的后缀名是html,模板引擎是ejs
  })
);

session 与 cookies

要在 koa 中使用session,需要先引入koa-session,设置 app.keys 作为 session 对应 cookie 的签名,如下配置:

// 引入 koa-session
const session = require("koa-session");
//配置session中间件
app.keys = ["some secret hurr"]; // cookie的签名
const CONFIG = {
  key: "koa:sess", // cookie 的key(session_id是储存在cookie中的)
  maxAge: 846400000, //  过期时间
  overwrite: true,
  httpOnly: true, // true 表示只有服务器端可以获取cookie
  signed: true, // 默认 签名
  rolling: false, // 表示每次访问都重新设置
  renew: false, // 当用户访问时,快要过期时重设
};
app.use(session(CONFIG, app));

要在 koa 中使用cookies,则直接通过ctx.cookies.set()ctx.cookies.get()使用即可,如下:

//设置cookies
ctx.cookies.set("userinfo", "lili", {
  maxAge: 60 * 1000 * 60, // 经过多长时间过期
  path: "/news", // 配置可以访问的地址,只有对应的路由地址可以访问
  /*
        domain:'.baidu.com' ,            // 配置可以访问的域名,默认是当前域可以访问
        httpOnly:true                // true 表示这个cookie只有服务器端可以访问,false 表示客户端也可以访问
        */
});

//设置中文的cookie , 使用base64编码
let username = new Buffer("马玉祥").toString("base64");
ctx.cookies.set("username", username, {
  maxAge: 60 * 1000 * 60,
});

//获取cookies
let username_cookie = ctx.cookies.get("username");

获取 post 数据

原始方法中,我们需要先封装一个异步方法接收数据:

exports.getPostData = function (ctx) {
  //获取数据,异步

  return new Promise((resolve, reject) => {
    try {
      let str = "";
      ctx.req.on("data", (chunk) => {
        str += chunk;
      });

      ctx.req.on("end", (chunk) => {
        resolve(str);
      });
    } catch (err) {
      reject(err);
    }
  });
};

然后在 koa 中使用:

//原生node.js方法 :
var common = require("./module/common.js"); //封装的异步方法,返回的是一个Promise
router.post("/post_form", async (ctx) => {
  //获取表单数据
  var data = await common.getPostData(ctx);

  console.log(data);
  ctx.body = data;
});

而我们可以通过bodyparser中间件更轻松地实现:

//使用koa中的bodyparser中间件获取post表单的数据 :
//引入并配置
var bodyParser = require("koa-bodyparser");
app.use(bodyParser());
//在路由匹配中使用
router.post("/post_form_koa", async (ctx) => {
  //获取表单数据
  let data = ctx.request.body;

  console.log(data);
});

静态资源服务

通常,将静态资源放在 static 文件夹中,然后通过以下配置静态文件:

//koa-static 静态web服务
const static = require("koa-static");
app.use(static(__dirname + "/static")); // 到static目录中去找对应静态文件  请求的url不用包含static,如 href='css/basic.css'

//也可以配置多个静态服务对应的文档,则静态资源可以分别放在不同的文件夹
app.use(static(__dirname + "/public"));

中间件

中间件的使用在 node 中十分重要,用好中间件可以极大提高我们的开发效率以及项目的性能
中间件通过app.use(async (ctx,next)={...}) 的方式定义,ctx是当前请求的上下文,包含当前信息,而next则是定义继续向下匹配中间价以及路由,在中间件中一定要调用await next()

//配置中间件,把公共的数据放到ctx.state中,则公共数据可在所有模板中使用
app.use(async (ctx, next) => {
  ctx.state = {
    username: "li_car",
    age: 19,
  };

  await next();
});

// 中间件的使用
// 中间件类似于捕获冒泡形式依次触发,如果不执行 await next() 则不会继续向下匹配中间件或路由,在该中间件终止程序
app.use(async (ctx, next) => {
  console.log("中间件01");
  await next();

  if (ctx.status == 404) {
    ctx.status = 404;
    ctx.body = "路由错误,404";
  } else {
    console.log("匹配到路由之后再执行到这里,这里是中间件01");
  }
});

app.use(async (ctx, next) => {
  console.log("中间件02");
  await next();

  console.log("匹配到路由之后再执行到这里,这里是中间件02");
});

配置路由

配置匹配路由的操作,通过以下方式:

var Router = require("koa-router");
var router = new Router();

//  配置路由
// ctx  上下文context,包含了req,res等信息
router
  .get("/", async (ctx) => {
    //设置cookies
    ctx.cookies.set("userinfo", "lili", {
      maxAge: 60 * 1000 * 60, // 经过多长时间过期
      path: "/news", // 配置可以访问的地址,只有对应的路由地址可以访问
      /*
        domain:'.baidu.com' ,            // 配置可以访问的域名,默认是当前域可以访问
        httpOnly:true                // true 表示这个cookie只有服务器端可以访问,false 表示客户端也可以访问
        */
    });

    //设置中文的cookie , 使用base64编码
    let username = new Buffer("马玉祥").toString("base64");
    ctx.cookies.set("username", username, {
      maxAge: 60 * 1000 * 60,
    });

    //设置session
    ctx.session.user = "张三";

    ctx.body = "首页"; //返回数据,相当于原生里的res.writeHead  res.end()
  })
  .get("/news", async (ctx) => {
    //获取cookies
    let userinfo = ctx.cookies.get("userinfo");
    console.log(userinfo);

    //获取设置了base64编码的cookie
    let username_cookie = ctx.cookies.get("username");
    let username = new Buffer(username_cookie, "base64").toString();
    console.log(username);

    //获取session
    console.log(ctx.session.user);

    ctx.body = "这是一个新闻界面";
  })
  .get("/packages", async (ctx) => {
    //    ctx.query   获取到 url? 后传的query值      ctx.querystring 则获取到query字符串
    let query = ctx.query;
    console.log(query);

    ctx.body = "packages";
  })
  .get("/pages/:id/:comment", async (ctx) => {
    //    ctx.params  获取到 动态路由事先设置好的占位符值, :id 这样的形式设置动态路由占位符
    let params = ctx.params;
    console.log(params);

    ctx.body =
      "pages    " + String(params.id) + "     " + String(params.comment);
  });

启动服务

设置好路由后,需要启动路由并且监听端口,如下:

//启动路由
app
  .use(router.routes()) //启动路由
  .use(router.allowedMethods()); //如果出错了,根据status自动设置响应头

//监听端口
app.listen(8081);
console.log("Server running at http://127.0.0.1:8081/");

结语

本文介绍 koa 的基础用法,供参考

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容