Nest 簡(jiǎn)介
Nest是一個(gè)NodeJS的服務(wù)端框架,與JAVA對(duì)照的話,其功能相當(dāng)于SpringMVC(國(guó)產(chǎn)也有類似框架,如阿里開源的EggJS)市咆。對(duì)于熟悉JAVA的開發(fā)者,Nest極易上手再来,Nest有著與SpringMVC如出一轍的分層架構(gòu)和注解標(biāo)簽蒙兰,以及依賴注入磷瘤、控制反轉(zhuǎn)、生命周期等實(shí)現(xiàn)搜变,官網(wǎng)傳送門采缚。
NeDB簡(jiǎn)介
NeDB是一個(gè)NodeJS實(shí)現(xiàn)的輕量級(jí)、嵌入式挠他、NoSQL數(shù)據(jù)庫(kù)扳抽,可用作內(nèi)存數(shù)據(jù)庫(kù),也可以持久化殖侵。使用簡(jiǎn)單贸呢、速度快,適合數(shù)據(jù)量小拢军、業(yè)務(wù)簡(jiǎn)單的場(chǎng)景(https://www.npmjs.com/package/nedb)楞陷。
創(chuàng)建項(xiàng)目,添加依賴
創(chuàng)建Nest項(xiàng)目茉唉,添加NeDB依賴固蛾,并將初始化項(xiàng)目按業(yè)務(wù)模塊調(diào)整。
創(chuàng)建Nest項(xiàng)目
創(chuàng)建項(xiàng)目nest-demo:
nest new nest-demo
安裝NeDB:
cd nest-demo
npm i nedb -S
調(diào)整初始化項(xiàng)目
將初始化的項(xiàng)目結(jié)構(gòu)按業(yè)務(wù)模塊調(diào)整度陆,調(diào)整后的結(jié)構(gòu)如下(包含兩個(gè)模塊艾凯,book和library):
app.module.ts
import { Module } from '@nestjs/common';
import { BookModule } from './book/book.module';
import { LibraryModule } from './library/library.module';
@Module({
imports: [BookModule, LibraryModule],
controllers: [],
providers: [],
})
export class AppModule {}
整合NeDB,實(shí)現(xiàn)CRUD
book.entity.ts坚芜,book模型
export interface BookEntity {
_id: string;
name: string;
price: number;
author: string;
createdAt: number;
updatedAt: number;
}
book.controller.ts
import { Body, Controller, Get, Post } from '@nestjs/common';
import { BookService } from './book.service';
import { BookEntity } from './book.entity';
@Controller('book')
export class BookController {
constructor(private readonly bookService: BookService) {
this.bookService = bookService;
}
/**
* list all books
*/
@Get()
async list(): Promise<Array<BookEntity>> {
return this.bookService.list();
}
@Get(':id')
async detail(@Param('id') _id: string): Promise<BookEntity> {
return this.bookService.detail(_id);
}
/**
* save new book
* @param book new book data
*/
@Post()
async save(@Body() book: BookEntity): Promise<BookEntity> {
return this.bookService.save(book);
}
}
book.service.ts
import { Injectable } from '@nestjs/common';
import { BookEntity } from './book.entity';
const Nedb = require('nedb');
@Injectable()
export class BookService {
private readonly nedb;
constructor() {
this.nedb = new Nedb({
filename: './db/book.db',
autoload: true,
timestampData: true,
});
}
/**
* find all books
*/
async list(): Promise<Array<BookEntity>> {
return new Promise((resolve, reject) => {
this.nedb.find({}, (error, docs) => {
if (error) reject(error);
resolve(docs);
});
});
}
async detail(_id: string): Promise<BookEntity> {
return new Promise((resolve, reject) => {
this.nedb.find({ _id }, (error, docs) => {
if (error) reject(error);
resolve(docs[0]);
});
});
}
/**
* save new book
* @param book new book
*/
async save(book: BookEntity): Promise<BookEntity> {
return new Promise((resolve, reject) => {
this.nedb.insert(book, (error, doc) => {
if (error) reject(error);
resolve(doc);
});
});
}
}
重構(gòu)代碼览芳,封裝公共基礎(chǔ)類,通過(guò)繼承實(shí)現(xiàn)復(fù)用和擴(kuò)展
業(yè)務(wù)與數(shù)據(jù)分離鸿竖,repository處理數(shù)據(jù)
app.repository.ts沧竟,基礎(chǔ)repository,實(shí)現(xiàn)CRUD操作
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Nedb = require('nedb');
export class AppRepository<T> {
protected readonly nedb;
constructor(dbName: string) {
this.nedb = new Nedb({
filename: dbName,
autoload: true,
timestampData: true,
});
}
/**
* find all
*/
async findAll(): Promise<Array<T>> {
return this.find({});
}
/**
* find by primary key
* @param _id primary key
*/
async findById(_id: string): Promise<T> {
return new Promise((resolve, reject) => {
this.find({ _id })
.then(res => resolve(res[0]))
.catch(error => reject(error));
});
}
/**
* find by options
* @param options search options
*/
async find(options): Promise<Array<T>> {
return new Promise((resolve, reject) => {
this.nedb.find(options, (error, docs) => {
if (error) {
reject(error);
}
resolve(docs);
});
});
}
/**
* insert new data
* @param data new data
*/
async insert(data: T): Promise<T> {
return new Promise((resolve, reject) => {
this.nedb.insert(data, (error, doc) => {
if (error) {
reject(error);
}
resolve(doc);
});
});
}
/**
* delete by id
* @param _id
*/
async deleteById(_id: string): Promise<number> {
return new Promise((resolve, reject) => {
this.nedb.remove({ _id }, (error, removedNum) => {
if (error) {
reject(error);
}
resolve(removedNum);
});
});
}
}
book.repository.ts缚忧,實(shí)現(xiàn)復(fù)雜數(shù)據(jù)操作
import { Injectable } from '@nestjs/common';
import { AppRepository } from '../app.repository';
import { BookEntity } from './book.entity';
@Injectable()
export class BookRepository extends AppRepository<BookEntity>{
constructor() {
super('./db/book.db');
}
//其他復(fù)雜數(shù)據(jù)操作
// ... ...
}
重寫service悟泵,封裝基礎(chǔ)service類并將repository作為依賴引入
app.service.ts,service基類闪水,依賴repository基類
import { AppRepository } from './app.repository';
export class AppService<T> {
constructor(private readonly appRepository: AppRepository<T>) {
this.appRepository = appRepository;
}
/**
* list all
*/
async list(): Promise<Array<T>> {
return this.appRepository.findAll();
}
/**
* get detail
* @param _id
*/
async detail(_id: string): Promise<T> {
return this.appRepository.findById(_id);
}
/**
* save new data
* @param data
*/
async save(data: T): Promise<T> {
return this.appRepository.insert(data);
}
/**
* delete by id
* @param _id
*/
async delete(_id: string): Promise<number> {
return this.appRepository.deleteById(_id);
}
}
重寫book.service.ts糕非,依賴book.repository.ts
import { Injectable } from '@nestjs/common';
import { AppService } from '../app.service';
import { BookEntity } from './book.entity';
import { BookRepository } from './book.repository';
@Injectable()
export class BookService extends AppService<BookEntity>{
constructor(private readonly bookRepository: BookRepository) {
super(bookRepository);
this.bookRepository = bookRepository;
}
// 除CRUD外復(fù)雜業(yè)務(wù)邏輯
// ... ...
}
同理,重寫controller球榆,封裝controller基類
app.controller.ts
import { AppService } from './app.service';
import { Body, Delete, Get, Param, Post } from '@nestjs/common';
export class AppController<T> {
constructor(private readonly appService: AppService<T>) {
this.appService = appService;
}
@Get()
async list(): Promise<Array<T>> {
return this.appService.list();
}
@Get(':id')
async detail(@Param('id') _id: string): Promise<T> {
return this.appService.detail(_id);
}
@Post()
async save(@Body() data: T): Promise<T> {
return this.appService.save(data);
}
@Delete(':id')
async delete(@Param('id') id: string): Promise<number> {
return this.appService.delete(id);
}
}
重寫book.controller.ts朽肥,繼承controller基類
import { Controller } from '@nestjs/common';
import { AppController } from '../app.controller';
import { BookEntity } from './book.entity';
import { BookService } from './book.service';
@Controller('book')
export class BookController extends AppController<BookEntity>{
constructor(private readonly bookService: BookService) {
super(bookService);
this.bookService = bookService;
}
// 其他復(fù)雜邏輯
// ... ...
}
book.module.ts,將book.repository引入
import { Module } from '@nestjs/common';
import { BookController } from './book.controller';
import { BookService } from './book.service';
import { BookRepository } from './book.repository';
@Module({
imports: [],
controllers: [BookController],
providers: [BookService, BookRepository],
})
export class BookModule {}
至此持钉,book模塊調(diào)整完成衡招,terminal執(zhí)行
npm run start
啟動(dòng)服務(wù)便可通過(guò)http://127.0.0.1:300/book訪問(wèn)相關(guān)API。
library模塊實(shí)現(xiàn)每强,只需繼承app.controller.ts始腾,app.service.ts和app.repository.ts基類便可完成CRUD功能
library.module.ts
import { Module } from '@nestjs/common';
import { LibraryController } from './library.controller';
import { LibraryService } from './library.service';
import { LibraryRepository } from './library.repository';
@Module({
imports: [],
controllers: [LibraryController],
providers: [LibraryService, LibraryRepository],
})
export class LibraryModule {}
library.controller.ts
import { Controller, Injectable } from '@nestjs/common';
import { AppController } from '../app.controller';
import { LibraryEntity } from './library.entity';
import { LibraryService } from './library.service';
@Controller('library')
export class LibraryController extends AppController<LibraryEntity> {
constructor(private readonly libraryService: LibraryService) {
super(libraryService);
this.libraryService = libraryService;
}
// other code ...
}
library.service.ts
import { Injectable } from '@nestjs/common';
import { AppService } from '../app.service';
import { LibraryEntity } from './library.entity';
import { LibraryRepository } from './library.repository';
@Injectable()
export class LibraryService extends AppService<LibraryEntity> {
constructor(private readonly libraryRepository: LibraryRepository) {
super(libraryRepository);
this.libraryRepository = libraryRepository;
}
// other code ...
}
library.repository.ts
import { AppRepository } from '../app.repository';
import { LibraryEntity } from './library.entity';
import { Injectable } from '@nestjs/common';
@Injectable()
export class LibraryRepository extends AppRepository<LibraryEntity> {
constructor() {
super('./db/library.db');
}
// other code ...
}
啟動(dòng)服務(wù)州刽,訪問(wèn)http://127.0.0.1/library即可調(diào)用library CRUD API。
工程源碼請(qǐng)?jiān)L問(wèn)https://github.com/louie-001/nestjs-nedb-demo.git