搭建一個egg項目:
代碼地址:demo
結合node搭建本地服務器的框架有很多,今天選擇的是egg這個框架,他是koa框架的封裝形式,用起來會比較小白一點。由於本人用的是MongoDB搭建本地的數據庫,所以選擇了egg的egg-mongoose模塊來搭建項目
安裝egg的初始化框架
$ npm i egg-init -g
$ egg-init egg-example --type=simple
$ cd egg-example
$ npm i
啓動項目
$ npm run dev
$ open localhost:7001
鏈接到本地的MongoDB:
安裝mongoose
並引入到項目中
npm install egg-mongoose -S
- 在config文件中找到 config.default.js 文件
// 引入egg-mongoose
const mongoose = require('mongoose');
module.exports = appInfo => {
const config = exports = {};
config.keys = appInfo.name + '_1539588102822_7832'; // 此處的字符是自己設定的cookie加密碼
// 添加 view 配置,nunjucks是一個用來在服務器端渲染HTML的插件,用npm 安裝即可
exports.view = {
defaultViewEngine: 'nunjucks',
mapping: {
'.tpl': 'nunjucks',
},
};
exports.mongoose = {
url: 'mongodb://127.0.0.1:27017/mongoTest',
// 鏈接到本地的MongoDB,mongoTest是我本地數據庫的名字,根據自己數據庫名字進行填寫即可
options: {},
};
// add your config here
config.middleware = [];
return config;
};
介紹項目目錄分配
在egg 項目的app文件中,有系統默認的幾個文件夾
- controller : 是用來分發路由接口請求的文件夾,指定了不同的路由對應的操作
- middleware : 是用來存放中間件的文件夾
- model : 是用來定義數據庫中表單的數據類型的文件夾
- service : 是用來操作數據庫的文件存放的地方,他是從controller中細化出來的,主要用來寫一些sql語言,保持 Controller 中的邏輯更加簡潔。
- view : 是用來存放一些需要服務器渲染的頁面的
.html
或.tpl
文件的地方 - router :是用來分配接口路由的文件
- router.js :爲了讓router 文件夾中的路由文件看起來整潔有明確的分類,在外層用router.js這樣一個文件做一個入口和索引的作用
介紹了以上的文件夾的作用,就可以開始寫自己的後臺項目了,每個模塊對應的命名有一定的要求,比如我現在要創建一個關於學生選修課的接口,我先創建一個學生的數據庫表格,我給文件命名爲student
,那麼我就需要在controller
,service
,model
中創建一個student.js
,入門級的使用方式可以參照 egg快速入門
第一步:分配路由:(在router.js文件中)
module.exports = app => {
const { router, controller } = app;
router.get('/getStudentList', controller.student.list);
// 1、我定義這個接口是獲取表格中所有學生的信息, 這是一個get請求
// 2、對應的是controller下面的student.js文件裏面的list方法
router.post('/add', controller.student.add);
// 這是一個post請求,調用的是controller裏面的add方法
};
那麼我就需要在controller文件夾下面創建一個student.js文件,並在裏面創立一個list方法,因爲controller對應的是不同路由的操作的文件夾,所以這裏當我們接收到對應的路由請求之後,對數據路進行對應的操作
// app/controller/student.js
const Controller = require('egg').Controller;
class UserController extends Controller {
// 這裏的 list 就是上面 controller.student.list 裏面的 list
async list() {
const ctx = this.ctx;
var aa = await ctx.service.student.list()
// 爲了方便文件的管理,當後續controller的方法變多的時候,操作數據庫的語言就不適合都擠在一個文件裏面,所以egg框架的service文件夾就起到了分配壓力的作用,所有具體的sql操作會寫在service文件夾中,我也是爲了方便操作的複用。
// 此處我們調用的是 service 文件夾裏面的student.js 文件裏面的 list方法
// 調用玩這個方法後,會返回一個數據庫中查找出來的數據,我們用變量 aa 來接收
ctx.body = aa
// 將接收到返回的數據渲染出來,也可以用return的方式放回給前端
}
}
module.exports = UserController;
在上面的操作中我們需要調用service文件夾裏面的student.js裏面的list方法,那麼我們就要在service文件夾裏面創建一個student.js
文件
// app/service/student.js
const Service = require('egg').Service;
class UserService extends Service {
async list() {
const ctx = this.ctx;
return ctx.model.Student.find({})
// ctx.model.Student.find({"title":"111"}) 表示在數據庫中查找title 爲111的對應數據
}
}
module.exports = UserService;
現在controller
,service
裏面都有student.js
文件了,還有model
裏面需要,我們需要在model中規定數據庫的數據類型,防止錯誤格式的儲存
// app/model/student.js
module.exports = app => {
const mongoose = app.mongoose;
const Schema = mongoose.Schema;
const UserSchema = new Schema({
studentName: { type: String, required: true },
age: { type: Number},
gender:{type : String, enum:['男','女']},
phone:{
type:String,
validate: {
validator: function(v) {
if(v.length < 8){
return false
}
},
message: '${v} is not a valid phone number!'
},
}
});
// 以上定義了表數據的類型
return mongoose.model('student', UserSchema,'studentInfo');
// model(參數1,參數2,參數3)參數3是你數據表中需要操作的表的名字,
// 比如我現在要操作的是名字叫mongoTest裏面的叫studentInfo的表
}
npm run dev 運行項目~
可以利用 postman 進行請求的模擬:
我的數據庫表單裏面有三條信息:(這是mongodb的一個可視化工具,叫Mongo compass,可以百度一下具體使用方法。
這就是你本地數據庫裏面獲取到的信息,也可以寫一個增加數據
這個是查詢的功能,我們還會有增刪改,其中增刪改都會涉及到數據操作是成功還是失敗的信息的返回,我們就以增加數據來舉例:
還是第一步:分配路由
module.exports = app => {
const { router, controller } = app;
router.get('/getStudentList', app.controller.student.list);
// 添加學生信息
router.post('/add', app.controller.student.add);
// 學生信息更新
router.post('/edit', app.controller.student.edit);
};
然後是去controller的user.js裏面添加add方法:
// app/controller/user.js
const Controller = require('egg').Controller;
class UserController extends Controller {
// 這裏的 list 就是上面 controller.user.list 裏面的 list
async list() {
const ctx = this.ctx;
var aa = await ctx.service.student.list()
// 此處我們將操作數據庫,所以調用的是 service 文件夾裏面的user.js 文件裏面的 list方法
// 調用玩這個方法後,會返回一個數據,我們用 aa 來接收
ctx.body = aa
// 將接收到返回的數據渲染出來
}
// 添加用戶
async add() {
const ctx = this.ctx;
const req = ctx.request.body
// 獲取請求體的內容
ctx.body = await ctx.service.student.add(req);
}
}
module.exports = UserController;
然後是service文件夾:
// app/service/user.js
const Service = require('egg').Service;
class UserService extends Service {
async list() {
const ctx = this.ctx;
return ctx.model.Student.find({})
// ctx.model.User.find({"title":"111"}) 表示在數據庫中查找title 爲111的對應數據
}
// 添加用戶
async add(req) {
const ctx = this.ctx
return ctx.model.Student.create(req).then(res => {
return { success: true, msg: res, code: 0 };
}).catch(err => {
return { success: false, err };
});
}
}
module.exports = UserService;
發送請求,然後報錯,gg
請教了一下同行,說是需要在 config 文件夾的 config.default.js 中加上這個:
const config = exports = {
security: {
csrf: {
enable: false
}
}
};
因爲之前在model中已經定義了數據表的數據類型,這裏就不需要再定義,直接上postman測試:
拿到自定義的返回內容,表示插入成功!再打開Mongo compass 查看一下數據表:
如果在真正的項目開發中,需要寫的接口特別的多,需要對路由進行分配和歸類,我們可以在 app 文件夾下創建一個子文件,叫做 route
此時更改一下router.js文件內容:
'use strict';
/**
* @param {Egg.Application} app - egg application
*/
module.exports = app => {
const { router, controller } = app;
require('./route/student')(app)
// 我將之前所有跟用戶信息相關的路由操作都放在一個類別中
};
在route文件夾中創建一個user.js的文件
// app/route/student.js
module.exports = app => {
//
app.router.get('/getStudentList', app.controller.student.list);
// 添加用戶信息
app.router.post('/add', app.controller.student.add);
};
運行一次,得到之前同樣的效果。這樣寫在遇到大量接口的時候會更加清晰簡潔