切换主题
字数
1581 字
阅读时间
7 分钟
tsx
import { Controller, Get, Param, Query } from '@nestjs/common';
import { StatService } from './stat.service';
// import { QuestionService } from 'src/question/question.service';
@Controller('stat')
export class StatController {
constructor(
private readonly statService: StatService,
// private readonly questionService: QuestionService, // 注入 QuestionService
) {}
@Get(':questionId')
async getQuestionStat(
@Param('questionId') questionId: string,
@Query('page') page: number = 1,
@Query('pageSize') pageSize: number = 10,
) {
// const q = await this.questionService.findOne(questionId); // 现在可以使用 questionService
// console.log('问卷信息:', q);
return await this.statService.getQuestionStatListAndCount(questionId, {
page,
pageSize,
});
}
@Get(':questionId/:componentFeId')
async getComponentStat(
@Param('questionId') questionId: string,
@Param('componentFeId') componentFeId: string,
) {
const stat = await this.statService.getComponentStat(
questionId,
componentFeId,
);
return { stat };
}
}
对代码的分析
一个注解下只能写一个方法
您的理解基本正确,但有一些细节需要澄清。让我详细解释一下:
- 控制器实例化:
当应用启动时,NestJS 会创建 StatController 的实例,而不是在每次请求时都创建。构造函数只在控制器首次实例化时执行一次。
路由匹配:
当前端发起对应 /stat 路径的请求时,NestJS 会根据路由规则将请求导向 StatController。
具体执行哪个方法取决于请求的 HTTP 方法和路径。
方法执行:
如果匹配到 /stat/:questionId,会执行 getQuestionStat 方法。
如果匹配到 /stat/:questionId/:componentFeId,会执行 getComponentStat 方法。
装饰器和方法:
一个装饰器(一个装饰器是指一个@Injectable或者@Controller)下可以有多个方法,但每个方法通常有自己的路由装饰器。例如:
@Controller('stat')
export class StatController {
@Get(':questionId')
getQuestionStat()
@Get(':questionId/:componentFeId')
getComponentStat()
@Post(':questionId')
createQuestionStat()
}
这里,@Controller('stat') 定义了基础路径,而每个方法都有自己的 @Get 或其他 HTTP 方法装饰器。
- 路由优先级:
NestJS 会按照定义的顺序匹配路由。在您的例子中,:questionId/:componentFeId 应该定义在 :questionId 之前,以确保更具体的路由先被匹配。
总之,NestJS 的路由系统非常灵活,允许您在一个控制器中定义多个方法,每个方法处理不同的 HTTP 方法和路径。控制器的构造函数在应用启动时执行,而具体的方法则根据请求的路径和 HTTP 方法来执行。
1. 接口类比与请求机制
前端发起请求并不是像调用一个抽象类的方法那样,而是通过 HTTP 请求与后端的 API 进行通信。可以将前端调用后端 API 理解为调用一个远程方法,而不是直接在前端定义抽象类。以下是它的工作方式:
- 请求发起:前端通过
fetch
、axios
、XMLHttpRequest
等方式发起 HTTP 请求,指定请求的 URL、HTTP 方法(GET、POST 等)、请求头和请求体。 - 后端响应:后端 API 定义了具体的 URL 路由和 HTTP 方法处理逻辑,通过注解匹配 URL 路径和方法,比如在 Spring Boot 或 NestJS 中,后端使用注解(如
@GetMapping
或@PostMapping
)定义了具体的路由处理逻辑。
所以,前端并不是像调用类方法那样调用接口,而是通过 HTTP 请求 发起到后端的 URL,对应的后端方法在注解中定义了请求路径和处理逻辑。
前端发起请求是远程调用后端一个抽象类的实例, 每次发起的请求地址在类中的注解中被匹配到, 就执行被注入的类中的匹配到的注解下的方法, 一个注解下只能有一个方法
你描述的过程大致正确,但需要更准确地解释前后端交互的细节。
在前端通过 HTTP 请求(例如 fetch
或 axios
)发起的请求,通常是发送到一个特定的 URL(API 接口)。这个 URL 对应的是后端的某个控制器(controller)或服务(service)中的方法。
后端处理请求的过程(以 Java Spring Boot 为例):
- 注解映射请求:后端通常使用如
@Controller
或@RestController
类来处理来自前端的 HTTP 请求。这些类中的方法通常使用@RequestMapping
、@GetMapping
、@PostMapping
等注解来匹配不同的请求路径和请求类型(如 GET、POST)。
java
@RestController
@RequestMapping("/api")
public class MyController {
@GetMapping("/example")
public ResponseEntity<String> getExample() {
return ResponseEntity.ok("Example response");
}
@PostMapping("/example")
public ResponseEntity<String> postExample(@RequestBody MyData data) {
// 处理请求
return ResponseEntity.ok("Data received");
}
}
注解映射规则:
每个注解对应一个方法:一个注解(如
@GetMapping
或@PostMapping
)下只能有一个方法,因为它是根据请求路径和请求类型来匹配唯一的处理函数。例如,/example
的 GET 请求只能由@GetMapping("/example")
的方法处理。依赖注入:后端的控制器通常依赖于服务层或其他业务逻辑层,这些服务类是通过依赖注入的方式注入到控制器中的。被注入的类可能是抽象类的实例或实现类,这取决于具体的设计模式。
java
@Service
public class MyServiceImpl implements MyService {
// 实现业务逻辑
}
@RestController
public class MyController {
private final MyService myService;
@Autowired
public MyController(MyService myService) {
this.myService = myService;
}
@GetMapping("/service-call")
public String serviceCall() {
return myService.performAction();
}
}
请求处理流程:
- 前端发送的请求会被后端的路由系统根据 URL 和请求类型(GET/POST 等)匹配到具体的控制器方法。
- 注解(如
@GetMapping
)会决定请求如何被路由到具体的方法,并执行该方法中的业务逻辑。 - 控制器中的方法会调用被注入的服务类,服务类可以是抽象类的实现类,来完成具体的业务操作。
总结:
- 前端发起的请求会根据 URL 和请求类型被映射到后端控制器类中的具体方法。
- 注解用于路由请求,每个注解下通常只有一个方法来处理特定类型的请求。
- 控制器可以通过依赖注入调用服务层,服务层可以是抽象类的实例化实现。
贡献者
sunchengzhi