深知大多数步伐员,想要提升技能,往往是自己探索发展,但自己不成体系的自学结果低效又漫长,而且极易遇到天花板技术停滞不前!
既有适合小白学习的零根本资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部门目录截图出来,全套包含大厂面经、学习条记、源码讲义、实战项目、大纲门路、讲解视频,并且后续会持续更新
需要这份系统化的资料的朋侪,可以戳这里获取
// 浏览器访问:http://localhost:3000/cat/say4/99
// 打印如下: param {id:‘99’}
@Get(‘/say4/:id’)
// Param参数为空
say4(@Param() param: { id: number }) {
console.log(‘param’, param);
return this.catService.say1();
}
// 5.Delete 删除接口
// APIFOX访问:http://localhost:3000/cat/say5/1 接口范例换成elete
// 打印如下: param { id: ‘1’ }
@Delete(‘/say5/:id’)
// Param参数为空
say5(@Param() param: { id: number }) {
console.log(‘param’, param);
return this.catService.say1();
}
// 6.Put 新增接口
// APIFOX访问:http://localhost:3000/cat/say5/1 接口范例换成ut
// 打印如下: param { id: ‘1’ }
@Put(‘/say6/:id’)
// Param参数为空
say6(@Param() param: { id: number }) {
console.log(‘param’, param);
return this.catService.say1();
}
// 7.Post 新增接口
// APIFOX访问:http://localhost:3000/cat 接口范例换成ost
// 参数在接口测试工具的body的json范例加入以下参数: { id: 1, name: ‘萧寂’ }
// 打印如下: cat { id: 1, name: ‘萧寂’ }
@Post()
say7(@Body() cat: any) {
console.log(‘cat’, cat);
return this.catService.say1();
}
}
- ## 提供者(也就是Java中的实体类)
- **在上面创建的cat文件夹内创建interface文件夹,在文件夹内创建cat.interface.ts文件**
- **在上面创建的cat文件夹内创建dto文件夹,在文件夹内创建create-cat.dto.ts文件**
复制代码 // cat.interface.ts
export interface Cat {
name: string;
age: number;
breed: string;
}
// create-cat.dto.ts
import { Cat } from “…/interface/cat.interface”;
export class CreateCatDto implements Cat{
name: string;
age: number;
breed: string;
}
// cat.controller.ts
import {
Body,
Controller,
Post,
} from ‘@nestjs/common’;
import { CatService } from ‘./cat.service’;
import { CreateCatDto } from ‘./dto/create-cat.dto’;
@Controller(‘cat’)
export class CatController {
// 私有的,只读的service
constructor(private readonly catService: CatService) {}
// APIFOX访问:http://localhost:3000/cat 接口范例换成ost
// 参数在接口测试工具的body的json范例加入以下参数: { id: 1, name: ‘萧寂’ }
// 打印如下: cat { id: 1, name: ‘萧寂’ }
@Post()
say(@Body() cat: CreateCatDto) {
console.log(‘cat’, cat); // 在apiFox打印结果和上面一样,只是加了范例校验,但是由于ts只进行范例束缚,并不要求参数限定必须一致,因此这里请求的参数与dao和接口类不一致也可以拿到参数,并不会报错,只是不存在的参数不会对其范例进行校验而已了
return this.catService.say1();
}
}
nest g mi logger
// 安装完成后在目录中会多出一个logger文件夹
//在app.mudule.ts放入以下内容进行注册绑定中心件
import { MiddlewareConsumer, Module } from ‘@nestjs/common’;
import { AppController } from ‘./app.controller’;
import { AppService } from ‘./app.service’;
import { CatController } from ‘./cat/cat.controller’;
import { CatService } from ‘./cat/cat.service’;
import { LoggerMiddleware } from ‘./logger/logger.middleware’;
@Module({
imports: [],
controllers: [AppController, CatController],
providers: [AppService, CatService],
})
export class AppModule {
configure(consumer: MiddlewareConsumer) {
// 下面这段代码代表先绑定中心件再应用到路由上,当访问cat大概带cat子接口时会被拦截到
consumer.apply(LoggerMiddleware).forRoutes(‘cat’);
// 由于同一个接口名可能会有get,put,delete,post等方法,因此可以利用下面方式对指定范例的接口进行拦截
consumer.apply(LoggerMiddleware).forRoutes({path:‘cat’,method:RequestMethod.GET}); // 只拦截get请求的cat接口
// 也可以直接将controller作为参数(如许的话,在当前控制器下面全部的请求都会被拦截到的)
consumer.apply(LoggerMiddleware).forRoutes(CatController);
// 如果当前需要拦截的请求较多,可以将controller作为参数,但又不渴望其中个别接口被拦截到,可以利用下面方式忽略需要拦截的接口
consumer.apply(LoggerMiddleware).exclude({path:‘cat/:id’,method:RequestMethod.GET},{path:‘cat’,method:RequestMethod.POST}).forRoutes(CatController);
}
}
// ------------------------------------------------------------------------------------------------
// 在logger/lagger.middleware.tss中添加如下内容
import { Injectable, NestMiddleware } from ‘@nestjs/common’;
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
// 每次访问cat接口都会被拦截到,并打印出一下日志
console.log(‘正在访问cat接口’);
next();
}
}
- **以上就是中间件基础使用方法了**
- ### 函数式中间件
复制代码 // 在logger/lagger.middleware.tss中添加如下内容
import { Injectable, NestMiddleware } from ‘@nestjs/common’;
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
console.log(‘111222’, 111222);
next();
}
}
// 下面这个是函数式中心件(只有函数式中心件可以注册成为全局中心件)
export function logger(req, res, next) {
console.log(‘Request_logger’);
next();
}
- **注册成为全局中间件,只有函数式中间件可以注册成为全局中间件**
复制代码 // 在main.ts进行注册(代码如下)
import { NestFactory } from ‘@nestjs/core’;
import { AppModule } from ‘./app.module’;
import { logger } from ‘./logger/logger.middleware’;
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 将中心件注册成为全局中心件
app.use(logger);
await app.listen(3000);
}
bootstrap();
- ## 异常处理
- ### 异常抛出
- **例如我们输入了一个不存在的地址,就会响应一个404,这个是框架给我们默认返回的一个异常,有时候我们需要手动去抛出一个异常**
- **Nest提供了一个内置的HttpException类,为基础异常类,可以很好的帮助我们进行异常的处理**
复制代码 // 在controller内其中一个接口如下:
import {Get,HttpException,HttpStatus} from ‘@nestjs/common’;
@Get(‘/xiaoji’)
xiaoji(): string {
throw new HttpException(‘服务器非常’, HttpStatus.FORBIDDEN);
}
// 浏览器访问:localhost:3000/cat/xiaoji
// 返回值为: {“statusCode”:403,“message”:“服务器非常”}
- ### 自定义异常及异常的处理
- #### 创建并配置异常处理器
复制代码 // 创建非常过滤器
nest g f http-exception
// 创建完成后目录会多出一个http-exception文件夹
// 在新创建的http-exception.filter.ts文件放入以下内容(已经处理好的)
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
} from ‘@nestjs/common’;
import { Request, Response } from ‘express’;
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
const status = exception.getStatus();
- response.status(status).json({
- statusCode: status,
- timestamp: new Date().toISOString(),
- path: request.url,
- });
复制代码 }
}
- #### 使用异常处理器
- **在cat.controller.ts内使用**
复制代码 import {
Body,
Controller,
Get,
HttpException,
HttpStatus,
UseFilters,
} from ‘@nestjs/common’;
import { HttpExceptionFilter } from ‘src/http-exception/http-exception.filter’;
// 在接口利用
@Get(‘/xiaoji’)
// 访问到这个接口直接抛出非常(非常的格式为我们上面定制的格式(状态码,时间和接口路径))
@UseFilters(new HttpExceptionFilter())
xiaoji(): string {
// 如果这里不抛出非常,上面这个非常过滤器不会执行,只有手动抛出非常则非常过滤器才会执行
throw new HttpException(‘服务器非常’, HttpStatus.FORBIDDEN);
}
// 例如有的情况有非常,但是我们不能一个个来抛出,例如全局的404非常,因此需要利用全局非常过滤器,方式如下
// main.ts
import { NestFactory } from ‘@nestjs/core’;
import { AppModule } from ‘./app.module’;
import { logger } from ‘./logger/logger.middleware’;
import { HttpExceptionFilter } from ‘./http-exception/http-exception.filter’;
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 将中心件注册成为全局中心件
app.use(logger);
// 全局注册非常过滤器
app.useGlobalFilters(new HttpExceptionFilter());
//
await app.listen(3000);
}
bootstrap();
// 当访问一个不存在的接口会返回404状态码和时间以及非常的接口路径(改写了默认的样式)
管道有两个典型的应用场景:
转换:管道将输入数据转换为所需的数据输出(例如,将字符串转换为整数)
验证:对输入数据进行验证,如果验证乐成继承传递; 验证失败则抛出非常
- Nest 自带九个开箱即用的管道,即
- * ValidationPipe
- * ParseIntPipe
- * ParseFloatPipe
- * ParseBoolPipe
- * ParseArrayPipe
- * ParseUUIDPipe
- * ParseEnumPipe
- * DefaultValuePipe
- * ParseFilePipe
- ### 转换
- **这里以ParseIntPipe为例,进行数据的转化**
复制代码 // 在cat.controller.ts其中一个接口如下内容
import {Get,Param,ParseIntPipe} from ‘@nestjs/common’;
//这个管道可以将吸收的参数转为number范例,否则返回的是{id:“123”},转换之后变成{id:123}
//如果参数给个abc导致不能转化成number,则会抛出400错误的非常,代表转化失败
@Get(‘:id’)
say1(@Param(‘id’, new ParseIntPipe()) id: number) {
return {
id: id,
};
}
- ### 验证(守卫)
- #### 基础使用
- >
- > 守卫在所有中间件之后执行,但在拦截器或管道之前执行。
- >
- >
- >
复制代码 // 创建保卫
nest g gu role
// 在新建的role.guard.ts内放入以下内容
import { CanActivate, ExecutionContext, Injectable } from ‘@nestjs/common’;
import { Observable } from ‘rxjs’;
@Injectable()
export class RoleGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise | Observable {
console.log(‘RoleGuard’);
return true;
}
}
// 再新建一个controller
nest g co user
// controller内放入以下内容
import {
Controller,
Get,
Param,
ParseIntPipe,
UseGuards,
} from ‘@nestjs/common’;
import { RoleGuard } from ‘src/role/role.guard’;
@Controller(‘user’)
@UseGuards(RoleGuard) // 利用保卫,当访问下面恣意接口时就会触发保卫,并打印(‘RoleGuard’)
export class UserController {
@Get(‘:id’)
// @UseGuards(RoleGuard) // 利用保卫,当访问当前接口时就会触发保卫,并打印(‘RoleGuard’)
getUserDetial(@Param(‘id’, ParseIntPipe) id: number) {
return {
id,
};
}
}
// controller.ts内加入下面代码
import {
Controller,
Get,
Param,
ParseIntPipe,
UseGuards,
SetMetadata,
} from ‘@nestjs/common’;
import { RoleGuard } from ‘src/role/role.guard’;
@Controller(‘user’)
export class UserController {
@Get(‘:id’)
@SetMetadata(‘role’, [‘access1’, ‘access2’])
@UseGuards(RoleGuard) // 利用保卫
getUserDetial(@Param(‘id’, ParseIntPipe) id: number) {
return {
id,
};
}
}
// role.guard.ts加入下面代码
import { CanActivate, ExecutionContext, Injectable } from ‘@nestjs/common’;
import { Reflector } from ‘@nestjs/core’;
import { Observable } from ‘rxjs’;
@Injectable()
export class RoleGuard implements CanActivate {
// 加上反射(可以拿到接口对应相关的一些信息)
constructor(private reflector: Reflector) {}
canActivate(
context: ExecutionContext,
): boolean | Promise | Observable {
console.log(‘RoleGuard’);
// 下面的role与controller接口的@SetMetadata(‘role’, [‘access1’,‘access2’])第一个参数保持一致
const roles = this.reflector.get<string[]>(‘role’, context.getHandler());
console.log(‘roles’, roles); // 打印的roles就是[‘access1’,‘access2’],刚刚的第二个参数
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
// 上面那个可以在接口上界说权限,然后拿到界说的权限,这里的user代表用户发请求携带的权限,这里可以进行路由比对,有权限放行,没权限返回false
// 这里是拿到了用户的标识,我们的系统可以查询到用户的权限
console.log(‘user’,user);
return true;
}
}
// 创建装饰器
nest g d role
// 创建完成后会发现多了个role.decorator.ts文件
// controller.ts
import {
Controller,
Get,
UseGuards,
} from ‘@nestjs/common’;
import { Role } from ‘src/role/role.decorator’; // 引入装饰器
import { RoleGuard } from ‘src/role/role.guard’; // 引入保卫
@Controller(‘user’)
@UseGuards(RoleGuard) // 利用保卫,下面的全部接口都会触发保卫
export class UserController {
@Get(‘user/list’)
@Role(‘access1’, ‘access2’,‘access3’, ‘access4’) // 装饰器内的参数就是权限(个人感觉较麻烦不如上面那个)
getUserList() {
return [1, 2, 3, 4];
}
}
// 访问接口得到-----roles [ ‘access1’, ‘access2’, ‘access3’, ‘access4’ ]
// 安装依赖
yarn add --save @nestjs/typeorm typeorm mysql2
// @nestjs/typeorm这个本人运行上面命令不绝安装不上,只好单独安装一下就乐成了(yarn add @nestjs/typeorm)
// 安装完成后在app.module.ts进行导入
import { Module } from ‘@nestjs/common’;
import { TypeOrmModule } from ‘@nestjs/typeorm’;
@Module({
imports: [
TypeOrmModule.forRoot({
type: ‘mysql’,
host: ‘localhost’,
port: 3306,
username: ‘root’,
password: ‘admin’,
database: ‘shop’,
// entities: [], // 实体类文件,下面创建完curd会讲怎么写的
synchronize: true, //是否将实体同步到数据库
retryDelay:500, // 重试毗连数据库的间隔
retryAttempts: 10, // 重试毗连数据库的次数
autoLoadEntities: true, // 主动加载实体(加上这个就不用上面的entities了)
logging: true, // 是否开启日志
logger: ‘advanced-console’, // 日志
}),
],
})
export class AppModule {}
nest g res test
// 选择第一个REST API(遵循rest api的规范)
// 选择y 确定创建curd(增编削查)
// 找到test/entities/test.entity.ts(只要创建了CURD这种文件,一般实体类都是这个位置,那么就可以动态加载实体类了,找到刚刚创建数据库的地方,将entities: [],添补以下内容,用于动态获取实体类),如果autoLoadEntities设置为true了,这个属性可以去掉,autoLoadEntities用于主动加载实体
entities: [__dirname + ‘/**/*.entity{.ts,.js}’],
- #### 在创建完的CURD文件内的实体类编写如下代码
- **test/entities/test.entity.ts**
复制代码 // 界说实体,界说列,界说自增主键
import { Entity, Column, PrimaryGeneratedColumn } from ‘typeorm’;
@Entity() // 界说实体类
export class Test {
@PrimaryGeneratedColumn()
id: number; // 自增id列
@Column()
name: string; // 列名
@Column()
password: string;
@Column()
age: number;
}
- #### 在test/test.model.ts里面编写如下代码
复制代码 import { Module } from ‘@nestjs/common’;
import { TestService } from ‘./test.service’;
import { TestController } from ‘./test.controller’;
// 引入实体
import { Test } from ‘./entities/test.entity’;
// 引入orm框架
import {TypeOrmModule} from ‘@nestjs/typeorm’
@Module({
// 引入注册
imports:[TypeOrmModule.forFeature([Test])],
controllers: [TestController],
providers: [TestService],
})
export class TestModule {}
- **保存重启项目会发现MySQL里面的shop这个数据库多了一个test这张表,表内的字段和实体类一一对应**
- ### 实体类介绍
复制代码 // 界说实体,界说列,界说自增主键
import { Entity, Column, PrimaryGeneratedColumn,CreateDateColumn,Generated } from ‘typeorm’;
@Entity() // 界说实体类
export class Test {
@PrimaryGeneratedColumn(“uuid”) // 自增的uuid
id: number; // 自增id列
@Column({type:“varchar”,length:255}) // 列范例
name: string;
@Column()
password: string;
@Column()
age: number;
// @CreateDateColumn() // 自增日期
@CreateDateColumn({ type: ‘timestamp’ }) // 时间戳范例
createTime: Date;
@Generated(‘uuid’) // 主动生成列
uuid: string;
@Column({ // 界说枚举范例
type: ‘enum’,
enum: [1, 2, 3, 4],
default: 1,
})
xiaoji: number;
}
- [/code] mysql 全部范例
- int, tinyint, smallint, mediumint, bigint, float, double, dec, decimal, numeric, date, datetime, timestamp, time, year, char, varchar, nvarchar, text, tinytext, mediumtext, blob, longtext, tinyblob, mediumblob, longblob, enum, json, binary, geometry, point, linestring, polygon, multipoint, multilinestring, multipolygon, geometrycollection
- [code]
- **列选项**
复制代码- @Column({
- type:"varchar",
- name:"ipaaa", //数据库表中的列名
- nullable:true, //在数据库中使列NULL或NOT NULL。 默认情况下,列是nullable:false
- comment:"注释",
- select:true, //定义在进行查询时是否默认隐藏此列。 设置为false时,列数据不会显示标准查询,适合用于密码。 默认情况下,列是select:true
- default:"xxxx", //加数据库级列的DEFAULT值
- primary:false, //将列标记为主要列。 使用方式和@ PrimaryColumn相同。
- update:true, //指示"save"操作是否更新列值。如果为false,则只能在第一次插入对象时编写该值。 默认值为"true"
- collation:"", //定义列排序规则。
- })
- ip:string
复制代码- **simple-array 列类型
- 有一种称为simple-array的特殊列类型,它可以将原始数组值存储在单个字符串列中。 所有值都以逗号分隔**
复制代码 @Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
- @Column("simple-array")
- names: string[];
复制代码 }
- \*\*simple-json列类型
- 还有一个名为simple-json的特殊列类型,它可以存储任何可以通过 JSON.stringify 存储在数据库中的值。 当你的数据库中没有 json 类型而你又想存储和加载对象,该类型就很有用了。 例如:
- \*\*
复制代码 @Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
- @Column("simple-json")
- profile: { name: string; nickname: string };
复制代码 }
- ## 数据库的增删改查的使用
- ### axios 接口定义
复制代码 import axios from ‘axios’
axios.defaults.baseURL = ‘http://localhost:3000’
// 增
export const addUser = (data) => axios.post(‘/user’,data).then(res => res.data)
// 查
export const getList = (data) => axios.get(‘/user’,{params:data}).then(res => res.data)
// 删
export const delUser = (data) => axios.delete(/user/${data.id}).then(res => res.data)
// 改
export const updateUser = (data) => axios.patch(/user/${data.id},data).then(res => res.data)
import { Entity, Column, PrimaryGeneratedColumn } from ‘typeorm’;
@Entity()
export class CreateUserDto {
@Column()
name:string
@Column()
desc:string
}
import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from ‘@nestjs/common’;
import { UserService } from ‘./user.service’;
import { CreateUserDto } from ‘./dto/create-user.dto’;
import { UpdateUserDto } from ‘./dto/update-user.dto’;
@Controller(‘user’)
export class UserController {
constructor(private readonly userService: UserService) {}
// 增
@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.userService.create(createUserDto);
}
// 查
@Get()
findAll(@Query() query:{keyWord:string,page:number,pageSize:number}) {
return this.userService.findAll(query);
}
// 改
@Patch(‘:id’)
update(@Param(‘id’) id: string, @Body() updateUserDto: UpdateUserDto) {
return this.userService.update(+id, updateUserDto);
}
// 删
@Delete(‘:id’)
remove(@Param(‘id’) id: string) {
return this.userService.remove(+id);
}
}
- ### service代码如下
- >
- > 1.引入 InjectRepository typeOrm 依赖注入 接受一个实体
- > 2.引入类型 Repository 接受实体泛型
- > 3.Like 用于模糊查询
- > 4.save 保存 find 查询 update 更新 delete 删除
- >
- >
- >
复制代码 import { Injectable } from ‘@nestjs/common’;
import { CreateUserDto } from ‘./dto/create-user.dto’;
import { UpdateUserDto } from ‘./dto/update-user.dto’;
import { Repository, Like } from ‘typeorm’;
import { InjectRepository } from ‘@nestjs/typeorm’;
import { User } from ‘./entities/user.entity’;
@Injectable()
export class UserService {
constructor(@InjectRepository(User) private readonly user: Repository) { }
// 增
create(createUserDto: CreateUserDto) {
const data = new User() // 创建实体类对象
data.name = createUserDto.name // 实体类的name赋值为传来的name
data.desc = createUserDto.desc // 实体类的desc赋值为传来的desc
return this.user.save(data) // 生存(每次生存都相当于添加一次)
}
// 查
async findAll(query: { keyWord: string, page: number, pageSize: number }) {
const data = await this.user.find({ // 查询
where: {
name: Like(%${query.keyWord}%) //模糊查询
},
select:[‘id’,‘name’], // 指定查询出来的字段
order: {
id: “DESC” // 倒序
},
skip: (query.page - 1)* query.pageSize, // skip跳过,从0开始
take:query.pageSize, // 需要展示的每页的数量
})
const total = await this.user.count({ // 总数量
where: {
name: Like(%${query.keyWord}%)
},
})
return {
深知大多数步伐员,想要提升技能,往往是自己探索发展,但自己不成体系的自学结果低效又漫长,而且极易遇到天花板技术停滞不前!
既有适合小白学习的零根本资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部门目录截图出来,全套包含大厂面经、学习条记、源码讲义、实战项目、大纲门路、讲解视频,并且后续会持续更新
需要这份系统化的资料的朋侪,可以戳这里获取
where: {
name: Like(%${query.keyWord}%) //模糊查询
},
select:[‘id’,‘name’], // 指定查询出来的字段
order: {
id: “DESC” // 倒序
},
skip: (query.page - 1)* query.pageSize, // skip跳过,从0开始
take:query.pageSize, // 需要展示的每页的数量
})
const total = await this.user.count({ // 总数量
where: {
name: Like(%${query.keyWord}%)
},
})
return {
深知大多数步伐员,想要提升技能,往往是自己探索发展,但自己不成体系的自学结果低效又漫长,而且极易遇到天花板技术停滞不前!
[外链图片转存中…(img-GSInbE2n-1715631105927)]
[外链图片转存中…(img-KTaI3eXo-1715631105927)]
既有适合小白学习的零根本资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部门目录截图出来,全套包含大厂面经、学习条记、源码讲义、实战项目、大纲门路、讲解视频,并且后续会持续更新
需要这份系统化的资料的朋侪,可以戳这里获取
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |