前提:此篇文章是基于node.js—基于Egg框架的简单后端搭建(包含传参数据库操作)_北木南-的博客-CSDN博客_egg node.js的基础上写的,安装简单的接口你看一看这篇文章。
Gitee仓库地址:Moon Painting后端_egg: 自己第一次用egg,写后端接口
这是自己写基于egg框架写的一个后台服务,有需要练习的小伙伴可以自行下载参考,注释都是很详细的,自己结合官网看是没有什么问题egg - 为企业级框架和应用而生 - Egg
先给看看成品实例:
体会:
这是第二次使用node写后端接口,也是第一次使用egg,我发现这个后端写起来其实也不难,首先你先得吧框架结构以及基础对象搞清楚,这样写的接口你自己项目的用完全是没有问题的。
项目结构:
router.js:毫无疑问就是路由,就是前台请求的URL和请求方法在这里写
controller:控制层,接收前端参数,处理参数,通过调用service对象调用service层方法进行下一步操作
service:进行数据库交互的(增删查改)
public:里面放的是一些静态资源,如图片
utils:这里面是自己后来加的,配置的是Response
config:是项目参数插架配置的,如jwt(登录鉴权,签发token)一系列
package.json:就是项目依赖名单
常用的也就是这几个。
基础对象:
Application:Application 是全局应用对象,在一个应用中,只会实例化一个,它继承自 Koa.Application,在它上面我们可以挂载一些全局的方法和对象。我们可以轻松的在插件或者应用中扩展 Application 对象。在框架运行时,会在 Application 实例上触发一些事件,应用开发者或者插件开发者可以监听这些事件做一些操作。作为应用开发者,我们一般会在启动自定义脚本中进行监听。
Context:Context 是一个请求级别的对象,继承自 Koa.Context。在每一次收到用户请求时,框架会实例化一个 Context 对象,这个对象封装了这次用户请求的信息,并提供了许多便捷的方法来获取请求参数或者设置响应信息。框架会将所有的 Service 挂载到 Context 实例上,一些插件也会将一些其他的方法和对象挂载到它上面(egg-sequelize 会将所有的 model 挂载在 Context 上)。
Request:Request 是一个请求级别的对象,继承自 Koa.Request。封装了 Node.js 原生的 HTTP Request 对象,提供了一系列辅助方法获取 HTTP 请求常用参数。
Response:Response 是一个请求级别的对象,继承自 Koa.Response。封装了 Node.js 原生的 HTTP Response 对象,提供了一系列辅助方法设置 HTTP 响应。
项目开始常遇到问题:
跨域:这种问题本就是后端来处理的,可以使用cors中间件配置白名单解决,这个去官网搜直接就有教程
jwt登录鉴权:jwt干啥的呢?给大家将一个流程,在你登录时jwt会给你签发一个token,你将拿到的token存储到客户端本地,下次再请求后端的时候带着token,token验证通过你才能进行登录之后的一系列操作,等你退出浏览器token就会失效。
这个自己配置不太好配置,这里记录一下我的配置:
1、npm 下载
2、plugin.js中
3、config.defaults.js中
4、登录验证成功后,expiresIn设置的是token过期时间,我这里设置的是1200s不操作就失效,失效你就只能登录后才能访问其他接口
获取参数
一般前端请求分为很多类别,比如最基础的post、get请求,post请求是将请求参数放在请求体里面,不会跟在接口后面的,这样参数不是明文传输就比较安全。
get请求则是明文请求,就是将参数放在请求接口后面,用户直接在url后面就能看到,这样数据是比较危险的。所以一般隐私信息就用post请求比较好,相对安全,get请求就放一些不重要的参数请求。还有一些删除等等一系列请求方式,对应不同功能,但是初学者用的比较少,感兴趣可以自己去查查。
当然不同请求后端就会有不同接受参数的方式,这里给大家整理一下常用的:
query(get)
获取 url 的 ?后面的数据,通过 ctx.query
拿到数据:
// GET /posts?category=egg&language=node
class PostController extends Controller {
async listPosts() {
const query = this.ctx.query;
// {
// category: 'egg',
// language: 'node',
// }
}
}
Router params(get)
获取 Router 上也可以申明参数,通过 ctx.params
拿到数据:
// app.get('/projects/:projectId/app/:appId', 'app.listApp');
// GET /projects/1/app/2
class AppController extends Controller {
async listApp() {
// assert.equal 相当于 ==
assert.equal(this.ctx.params.projectId, '1');
assert.equal(this.ctx.params.appId, '2');
// 或用解构赋值
const { projectId, appId } = this.ctx.params
}
}
body(post)
也就是 post、put、delete 等方法,框架内置了 bodyParser 中间件来对这两类格式的请求 body 解析成 object 挂载到 ctx.request.body
上。
// POST /api/posts HTTP/1.1
// Host: localhost:3000
// Content-Type: application/json; charset=UTF-8
//
// {"title": "controller", "content": "what is controller"}
class PostController extends Controller {
async listPosts() {
assert.equal(this.ctx.request.body.title, 'controller');
assert.equal(this.ctx.request.body.content, 'what is controller');
}
}
可以在 config/config.default.js
配置解析请求的大小,会覆盖框架默认值 100kb:
module.exports = {
bodyParser: {
jsonLimit: '1mb',
formLimit: '1mb',
},
};
egg的file模式
1、在 config 文件中启用 file 模式:
// config/config.default.js
exports.multipart = {
mode: 'file',
};
2、上传 / 接收文件:
前端:
<form method="POST" action="/upload?_csrf={{ ctx.csrf | safe }}" enctype="multipart/form-data">
title: <input name="title" />
file: <input name="file" type="file" />
<button type="submit">Upload</button>
</form>
后端:
// app/controller/upload.js
const Controller = require('egg').Controller;
const fs = require('mz/fs');
module.exports = class extends Controller {
async upload() {
const { ctx } = this;
const file = ctx.request.files[0];
const name = 'egg-multipart-test/' + path.basename(file.filename);
let result;
try {
// 处理文件,比如上传到云端
result = await ctx.oss.put(name, file.filepath);
} finally {
// 需要删除临时文件
await fs.unlink(file.filepath);
}
ctx.body = {
url: result.url,
// 获取所有的字段值
requestBody: ctx.request.body,
};
}
};
上传多个文件可以看 egg 官网 传送门
stream模式获取file
const path = require('path');
const sendToWormhole = require('stream-wormhole');
const Controller = require('egg').Controller;
class UploaderController extends Controller {
async upload() {
const ctx = this.ctx;
const stream = await ctx.getFileStream();
const name = 'egg-multipart-test/' + path.basename(stream.filename);
// 文件处理,上传到云存储等等
let result;
try {
result = await ctx.oss.put(name, stream);
} catch (err) {
// 必须将上传的文件流消费掉,要不然浏览器响应会卡死
await sendToWormhole(stream);
throw err;
}
ctx.body = {
url: result.url,
// 所有表单字段都能通过 `stream.fields` 获取到
fields: stream.fields,
};
}
}
module.exports = UploaderController;
通过 ctx.getFileStream
获取文件的前提:
- 只支持上传一个文件。
- 上传文件必须在所有其他的 fields 后面,否则在拿到文件流时可能还获取不到 fields。
stream 模式上传多个文件使用 ctx.multipart()
获取header值
ctx.headers
,ctx.header
,ctx.request.headers
,ctx.request.header
等价ctx.get(name)
,ctx.request.get(name)
获取 header 某一个字段
service层
数据库操作官网很详细 ,自己看非常简单Mygg
基于上一篇文章你就能写自己需要的接口了
上线接口地址:
我的这个接口已经上线,部署在服务器了,服务器接口地址:39.108.229.103:7001
出现hi,egg你就算能访问了,有需要就扣使用文档的可以私聊或者留言,有需要人需要处使用文档,没有就不出了