egg简单的使用

一.egg介绍

      Egg.js简称Egg,它是《阿里旗下产品基于Node.js 和 Koa的一个Nodejs的企业级应用开发框架,它可以帮助开发团队及开发人员降低开发和维护成本。

       Egg.js 基于Es6、Es7以及Typescript、Koa2,使得Nodejs具有更规范的开发模式、更低的学习成本、更优雅的代码、更少的开发成本、更少的维护成本,它是为企业级框架而生!真正用过Node.js开发后端服务的朋友看到Egg.js,绝对都是一种惊喜的感觉,它可以把我们曾经踩过的坑和一直想整合到一起的东西给整合到一起。

官网介绍

MVC: service 【model  模型 :主要处理数据(查询数据库,请求接口数据)】  view【视图,模板 页面展示】 controller【 控制器,负责处理一些业务逻辑】

当用户访问我们这个页面的时候,比如用户访问admin,首先走到路由router,路由匹配控制器controller,控制器controller 需要数据 找 model 【service】 ,然后渲染到 模板中view;比如加载router后,我们需要对角色判断,这时我们需要在中间件middleware【middleware 功能是匹配路由之前,或是之后,处理一系列的操作】

extend 扩展【定义些 在模板view中使用的方法,比如日期】

二.插件

官网集成插件 比如:

  1. 模板渲染:egg-view-nunjucks
  2. 跨域请求:egg-cors 
  3. Token生成:egg-jwt
  4. 访问数据库:egg-sequelize 和 mysql2
  5. MySQL 数据库封装:egg-mysql
  6. 验证码:svg-captcha
  7. 文件上传:await-stream-ready 和 stream-wormhole

await-stream-ready:顾名思义,能够使用await进行文件的读写操作。

stream-wormhole:在文件上传出现异常时能够把流消耗掉。

三.特点

约定大于配置【有自己全套的插件库,文件名字都约定好,比如固定routerjs,controller,service,不能随便写】

 

四.创建项目

安装脚手架egg-init: npm i egg-init  -g  

1.项目地址 cd eggframe
2. npm init egg --type=simple


3. npm i
4.启动项目: npm run dev
$ open: http://localhost:7001

五.项目结构

    // 这是一个 egg 项目的目录结构
	├──app
	│  ├──controller
	│  │   └──home.js
	│  ├──service
	│  │   └──user.js
	│  ├──view
	│  │   └──视图(模板),页面展示
	│  ├──middleware  
	│  │   └──xtoken.js 中间件
	│  ├──public
	│  │    └──css、image、js等静态资源
	│  └──router.js
	│  
	├──config
	│  ├── config.default.js //配置
	│  └── plugin.js  //插件
	│
	├──test
	│
	└──package.json

如上,由框架约定的目录: 

  • app/router.js 用于配置 URL 路由规则,具体参见 Router
  • app/controller/** 用于解析用户的输入,处理后返回相应的结果,具体参见 Controller
  • app/service/** 用于编写业务逻辑层,可选,建议使用,具体参见 Service
  • app/middleware/** 用于编写中间件,可选,具体参见 Middleware
  • app/public/** 用于放置静态资源,可选,具体参见内置插件 egg-static
  • app/extend/** 用于框架的扩展,可选,具体参见框架扩展
  • config/config.{env}.js 用于编写配置文件,具体参见配置
  • config/plugin.js 用于配置需要加载的插件,具体参见插件
  • test/** 用于单元测试,具体参见单元测试
  • app.js 和 agent.js 用于自定义启动时的初始化工作,可选,具体参见启动自定义。关于agent.js的作用参见Agent机制

由内置插件约定的目录:

  • app/public/** 用于放置静态资源,可选,具体参见内置插件 egg-static
  • app/schedule/** 用于定时任务,可选,具体参见定时任务

若需自定义自己的目录规范,参见 Loader API

  • app/view/** 用于放置模板文件,可选,由模板插件约定,具体参见模板渲染
  • app/model/** 用于放置领域模型,可选,由领域类相关插件约定,如 egg-sequelize

(1)路由router 常用:

router.redirect('/', '/news', 302); //重定向

router.get('/news', controller.news.list);

router.post("/admin/user/register", controller.admin.register.userRegister)

传参数:

路由:

1. 路由传参

a. router.js
router.get('/newsList/:id', controller.news.newslist);


b. controller/new.js

 async newslist() {
        const { ctx } = this;
        // koa 获取动态路由传值 ctx.params
        var params = ctx.params;
        console.log("params:", params)
// http://127.0.0.1:7001/newsList/111 输出params: { id: '111' }

        ctx.body = "新闻详情内容2"

    }

2.get 传值

a. router.js
router.get('/newsDetails', controller.news.details);


b. controller/new.js

  async details() {
        const { ctx } = this;
        // koa 获取get传值 ctx.query
        var query = ctx.query;
        console.log("query:", query)
//http://127.0.0.1:7001/newsDetails?ids=11  输出query: { ids: '11' }

        ctx.body = "新闻详情内容1"

    }

 (2)模板渲染使用

安装egg-view-nunjucks

1.配置

config/plugin.js 配置

 

 

然后config.default.js配置

 

2. router.js 路由

router.get('/news', controller.news.list);

3.Controller 控制器

/**
 * 控制器,这边是模块
 * 里面的方法是基于 async ,await的开发
 * 这个this是指这个模块
 */
const Controller = require('egg').Controller;

class NewsController extends Controller {
    async list() {
          const { ctx, service } = this;
        // 调用服务器里面的方法  注意异步:await
        const list = await service.news.getNewsList();
        //render 渲染模板
        await ctx.render('news/index.html', list);
    }

}

module.exports = NewsController;

4.拿取数据 service/news.js

'use strict';

const Service = require('egg').Service;

class NewsService extends Service {
    async getNewsList() {
        // 新闻的数据
        const dataList = {
            list: [
                { id: 1, title: '新闻1', url: '/news/1' },
                { id: 2, title: '新闻2', url: '/news/2' }
            ]
        };

        return dataList;
    }
}

module.exports = NewsService;

5.创建静态资源

6.模板 view/new/index.html

<html>

<head>
    <title>new 案例</title>
</head>
<link rel="stylesheet" href="/public/css/common.css" />

<body>
    <h1>新闻 案例 </h1>
    <ul class="news-view view">
        {% for item in list %}
        <li class="item">
            <a href="{{ item.url }}">{{ item.title }}</a>
        </li>
        {% endfor %}
    </ul>
    <img src="/public/images/cat.jpg" />
</body>

</html>

(3).框架扩展 extend

application.js —— this指向:app对象 【对象指的是 Koa 的全局应用对象,全局只有一个,在应用启动时被创建】

调用:this.app
 

context.js —— this指向:ctx对象【指的是 Koa 的请求上下文,这是 请求级别 的对象】
调用:this.ctx
 

request.js —— this指向:ctx.request对象【对象和 Koa 的 Request 对象相同,是 请求级别 的对象】
调用:this.ctx.request
 

response.js —— this指向:ctx.response对象【对象和 Koa 的 Response 对象相同,是 请求级别 的对象】
调用:this.ctx.response
 

helper.js —— this指向:ctx.helper对象【提供一些实用的 utility 函数,就是工具类】
调用:this.ctx.helper

小案例 :在视图模板中调用extend方法: 时间转换 momentJS

安装moment :npm i --save moment

1.在extend/helper.js

const moment = require('moment');
moment.locale('zh-cn');
module.exports = {
    //时间的转换
    formatDate(param) {
        // this 是 helper 对象,在其中可以调用其他 helper 方法
        // this.ctx => context 对象
        // this.app => application 对象
        return moment(param).format('YYYY-MM-DD');
    }
};

 2.view/news/index.html

<a>{{helper.formatDate(item.dateTime)}}</a>

 注意:也可以在controller,service 里调用

(4)中间件middleware

 Egg 是基于 Koa 实现的,所以 Egg 的中间件形式和 Koa 的中间件形式是一样的,都是基于洋葱圈模型。 

一个js文件就是一个中间件

config.default.js:中间件配置

config.middleware = ['forbidip'];
	config.forbidip = {
		forbidipList: [
			"127.0.0.1"
		]
	}

中间件编写middleware/ forbidip.js【禁止一些ip地址访问】

module.exports = (option, app) => {
    return async function forbidip(ctx, next) {
        //获取客服端的ip
        const clientIp = ctx.request.ip;
        let hasIp = option.forbidipList.some(function (val) {
            if (val == clientIp) {
                return true;
            }
        })
        if (hasIp) {
            //屏蔽
            ctx.status = 403;
            ctx.body = '您的ip已经被屏蔽';
        } else {
            await next()
        }

    }
}

(5)安全机制(post请求)

Web 应用中存在很多安全风险,egg框架针对 Web 端常见的安全风险内置了丰富的解决方案。

比如post 请求,不能直接提交数据,需要认证csrf

view/new/index.html表单

<form action="/add?_csrf={{csrf}}" method="POST">
        用户名: <input type="text" name="name" />
        <br><br>
        密 码:<input type="password" name="password" />
        <br><br>
        <button type="submit">提交</button>
    </form>
const Controller = require('egg').Controller;

class NewsController extends Controller {
    async list() {
        const { ctx, service } = this;
        // 调用服务器里面的方法  注意异步:await
        const list = await service.news.getNewsList();

        const catInfos = await service.cat.getCatInfos();
        console.log('csrf:', this.ctx.csrf)
        //render 渲染模板
        await ctx.render('news/index.html', {
            list: list,
            catInfos: catInfos,
            csrf: this.ctx.csrf // 获取 csrf 的值
        });
    }

  
    // 表单post 请求
    async add() {
        console.log('表单提交的数据:', this.ctx.request.body)
        this.ctx.body = this.ctx.request.body //获取表单提交的数据
    }
}

module.exports = NewsController;

csrf会自动验证

但是这个很神奇,我测试的时候 不需要csrf 也可以,所以安全机制 csrf 有待讨论,是否我项目配置了

(6)Cookie 与 Session

session 也是基于cookie的基础上

(7)数据库

egg-sequelize mysql2

 

六.编写接口

1.router.js

'use strict';
/*
Router 主要用来描述请求 URL 和具体承担执行动作的 Controller 的对应关系,
*/
/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
	const { router, controller } = app;
	router.get('/home', controller.home.index);
};

2.controller 控制器/home

'use strict';
//控制器

const Controller = require('egg').Controller;

class HomeController extends Controller {
	async index() {
		const ctx = this.ctx;
		const sfzjhm = ctx.query.sfzjhm;
		//请求数据接口
		const newsList = await ctx.service.home.list(sfzjhm);
		ctx.body = newsList;
	}
}

module.exports = HomeController;

3.配置接口地址:config/config.default.js

// 增加配置

    const userConfig = {

        // news 模块的配置

        news: {

            serverUrl: 'http://114.11****:85/',

        }

    };

4.service/home.js

egg.js中请求外部接口,this.ctx.curl()

const Service = require('egg').Service;

class NewsService extends Service {
    async list(names) {
        const { serverUrl } = this.config.news;
        let data = {
            name: names,
            password: "123"
        };
        // 注意:异步请求,记得加上await
        var resultData = await this.ctx.curl(`${serverUrl}sysUserInfo/login`, {
            data: data,
            method: 'POST',
            dataType: 'json',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            }
        });
        return resultData.data;
    }
}

module.exports = NewsService;

 

5.运行

npm run dev

open:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在egg.js中使用jwt中间件,首先需要进行全局安装egg-jwt插件。您可以使用以下命令进行安装:npm install egg-jwt -S。 然后,在项目的config/plugin.js文件中添加jwt插件的配置: jwt: { enable: true, package: 'egg-jwt', }[3。 完成以上配置后,您可以在需要使用jwt的地方引入jwt中间件,并进行相关的鉴权操作。可以根据您的需求,在egg.js中实现简单登录、用户信息获取、图片上传、增删改查等功能。 请注意,以上提供的是使用jwt中间件的基本步骤,具体实现还需要根据您的项目需求进行相应的配置和编码。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Egg.js使用jwt](https://blog.csdn.net/LizequaNNN/article/details/120457405)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [egg.js 配合 jwt 进行鉴权](https://blog.csdn.net/weixin_38992765/article/details/123754845)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值