- Nest.js从零开始学习
- Nest.js概述
- 环境搭建
- 基本概念
- 依赖注入(Dependency Injection)
- 中间件与管道
- 路由与请求处理
- Nest.js 框架异常处理
- Nest.js 框架数据库操作
- Nest.js 框架认证与授权
- Nest.js 框架 WebSockets 与实时通信
- Nest.js 框架 GraphQL 支持
- Nest.js 框架微服务架构
- Nest.js 框架测试
- Nest.js 框架性能优化与安全
- Nest.js 项目实战:创建一个完整的用户管理应用
Nest.js 项目实战:创建一个完整的用户管理应用
class 用户管理系统在本项目中,我们将创建一个完整的用户管理应用,具备用户注册、登录、获取用户信息等基本功能。我们将进行需求分析、架构设计与实现,最后讨论部署与维护。
1. 项目需求分析
1.1 功能需求
- 用户注册
- 用户登录(JWT 身份验证)
- 获取用户信息
- 更新用户信息
- 删除用户账户
1.2 非功能需求
- 数据安全(输入验证、加密存储)
- 性能优化(使用缓存)
- 错误处理与日志记录
2. 架构设计与实现
2.1 项目结构
user-management-app/
├── src/
│ ├── auth/
│ │ ├── auth.controller.ts
│ │ ├── auth.module.ts
│ │ ├── auth.service.ts
│ │ └── jwt.strategy.ts
│ ├── users/
│ │ ├── users.controller.ts
│ │ ├── users.module.ts
│ │ ├── users.service.ts
│ │ └── user.entity.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ ├── main.ts
│ └── shared/
│ ├── dto/
│ │ └── create-user.dto.ts
│ └── pipes/
│ └── validation.pipe.ts
├── package.json
├── tsconfig.json
└── .env
2.2 安装依赖
在项目根目录下,初始化项目并安装所需依赖:
npm init -y
npm install @nestjs/core @nestjs/common @nestjs/platform-express @nestjs/jwt @nestjs/passport passport passport-jwt bcrypt class-validator class-transformer typeorm sqlite3
npm install --save-dev @nestjs/testing jest ts-jest @types/jest @types/supertest supertest
2.3 创建应用模块
app.module.ts
import { Module } from '@nestjs/common';
import { AuthModule } from './auth/auth.module';
import { UsersModule } from './users/users.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRoot({
type: 'sqlite',
database: 'db.sqlite',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
}),
AuthModule,
UsersModule,
],
})
export class AppModule {}
2.4 创建用户模块
users/user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
email: string;
@Column()
password: string;
@Column()
name: string;
}
users/users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
import { CreateUserDto } from '../shared/dto/create-user.dto';
import * as bcrypt from 'bcrypt';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {}
async create(createUserDto: CreateUserDto): Promise<User> {
const hashedPassword = await bcrypt.hash(createUserDto.password, 10);
const user = this.usersRepository.create({ ...createUserDto, password: hashedPassword });
return this.usersRepository.save(user);
}
async findOne(email: string): Promise<User | undefined> {
return this.usersRepository.findOne({ where: { email } });
}
async findAll(): Promise<User[]> {
return this.usersRepository.find();
}
async update(id: number, updateUserDto: Partial<CreateUserDto>): Promise<User> {
await this.usersRepository.update(id, updateUserDto);
return this.usersRepository.findOne(id);
}
async remove(id: number): Promise<void> {
await this.usersRepository.delete(id);
}
}
users/users.controller.ts
import { Controller, Post, Body, Get, Param, Put, Delete } from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from '../shared/dto/create-user.dto';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
async create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
@Get(':email')
async findOne(@Param('email') email: string) {
return this.usersService.findOne(email);
}
@Put(':id')
async update(@Param('id') id: number, @Body() updateUserDto: CreateUserDto) {
return this.usersService.update(id, updateUserDto);
}
@Delete(':id')
async remove(@Param('id') id: number) {
return this.usersService.remove(id);
}
}
users/users.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { User } from './user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
2.5 创建身份验证模块
auth/jwt.strategy.ts
import { Injectable } from '@nestjs/common';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { UsersService } from '../users/users.service';
import { User } from '../users/user.entity';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private usersService: UsersService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.JWT_SECRET,
});
}
async validate(payload: any): Promise<User> {
return this.usersService.findOne(payload.email);
}
}
auth/auth.service.ts
import { Injectable } from '@nestjs/common';
import { UsersService } from '../users/users.service';
import { JwtService } from '@nestjs/jwt';
import { User } from '../users/user.entity';
import * as bcrypt from 'bcrypt';
@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService,
) {}
async register(email: string, password: string, name: string): Promise<User> {
const user = await this.usersService.create({ email, password, name });
return user;
}
async login(email: string, password: string): Promise<{ access_token: string }> {
const user = await this.usersService.findOne(email);
if (user && (await bcrypt.compare(password, user.password))) {
const payload = { email: user.email };
return { access_token: this.jwtService.sign(payload) };
}
throw new Error('Invalid credentials');
}
}
auth/auth.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('register')
async register(@Body() createUserDto: { email: string; password: string; name: string }) {
return this.authService.register(createUserDto.email, createUserDto.password, createUserDto.name);
}
@Post('login')
async login(@Body() loginDto: { email: string; password: string }) {
return this.authService.login(loginDto.email, loginDto.password);
}
}
auth/auth.module.ts
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { UsersModule } from '../users/users.module';
import { JwtStrategy } from './jwt.strategy';
@Module({
imports: [
UsersModule,
JwtModule.register({
secret: process.env.JWT_SECRET,
signOptions: { expiresIn: '60m' },
}),
],
providers: [AuthService, JwtStrategy],
controllers: [AuthController],
})
export class AuthModule {}
2.6 创建 DTO 和验证管道
shared/dto/create-user.dto.ts
import { IsEmail, IsString, MinLength } from 'class-validator';
export class CreateUserDto {
@IsEmail()
email: string;
@IsString()
@MinLength(6)
password: string;
@IsString()
name: string;
}
shared/pipes/validation.pipe.ts
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
import {
validate } from 'class-validator';
import { plainToClass } from 'class-transformer';
@Injectable()
export class ValidationPipe implements PipeTransform {
async transform(value: any, metadata: ArgumentMetadata) {
const object = plainToClass(metadata.metatype, value);
const errors = await validate(object);
if (errors.length > 0) {
throw new BadRequestException('Validation failed');
}
return value;
}
}
2.7 主文件
main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from './shared/pipes/validation.pipe';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();
2.8 .env 文件
在项目根目录下创建 .env
文件,添加 JWT 密钥:
JWT_SECRET=your_secret_key
3. 部署与维护
3.1 部署步骤
-
构建项目
使用 Nest.js CLI 或者 npm 脚本构建项目:
npm run build
-
选择云服务
选择合适的云服务平台(如 AWS、Heroku、DigitalOcean)进行部署。
-
运行应用
在目标服务器上安装 Node.js 和相关依赖,然后运行应用:
npm install npm run start:prod
3.2 维护与监控
- 日志记录:使用 Winston 或 Morgan 进行日志记录,监控应用状态。
- 性能监控:使用 APM 工具(如 New Relic 或 Datadog)监控性能。
- 定期更新:保持依赖的更新,定期审查安全性和性能。
4. 总结
在本项目中,我们构建了一个完整的用户管理应用,涵盖了用户注册、登录、信息管理等功能。通过合理的架构设计、代码实现和部署步骤,应用不仅具备基本功能,还考虑了性能和安全。希望这对你的 Nest.js 学习与实践有所帮助!
评论区
评论列表
{{ item.user.nickname || item.user.username }}