Skip to content
字数
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 方法装饰器。

  1. 路由优先级:

NestJS 会按照定义的顺序匹配路由。在您的例子中,:questionId/:componentFeId 应该定义在 :questionId 之前,以确保更具体的路由先被匹配。

总之,NestJS 的路由系统非常灵活,允许您在一个控制器中定义多个方法,每个方法处理不同的 HTTP 方法和路径。控制器的构造函数在应用启动时执行,而具体的方法则根据请求的路径和 HTTP 方法来执行。

1. 接口类比与请求机制

前端发起请求并不是像调用一个抽象类的方法那样,而是通过 HTTP 请求与后端的 API 进行通信。可以将前端调用后端 API 理解为调用一个远程方法,而不是直接在前端定义抽象类。以下是它的工作方式:

  • 请求发起:前端通过 fetchaxiosXMLHttpRequest 等方式发起 HTTP 请求,指定请求的 URL、HTTP 方法(GET、POST 等)、请求头和请求体。
  • 后端响应:后端 API 定义了具体的 URL 路由和 HTTP 方法处理逻辑,通过注解匹配 URL 路径和方法,比如在 Spring Boot 或 NestJS 中,后端使用注解(如 @GetMapping@PostMapping)定义了具体的路由处理逻辑。

所以,前端并不是像调用类方法那样调用接口,而是通过 HTTP 请求 发起到后端的 URL,对应的后端方法在注解中定义了请求路径和处理逻辑。

前端发起请求是远程调用后端一个抽象类的实例, 每次发起的请求地址在类中的注解中被匹配到, 就执行被注入的类中的匹配到的注解下的方法, 一个注解下只能有一个方法

你描述的过程大致正确,但需要更准确地解释前后端交互的细节。

在前端通过 HTTP 请求(例如 fetchaxios)发起的请求,通常是发送到一个特定的 URL(API 接口)。这个 URL 对应的是后端的某个控制器(controller)或服务(service)中的方法。

后端处理请求的过程(以 Java Spring Boot 为例):

  1. 注解映射请求:后端通常使用如 @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");
    }
}
  1. 注解映射规则

    • 每个注解对应一个方法:一个注解(如 @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();
    }
}
  1. 请求处理流程

    • 前端发送的请求会被后端的路由系统根据 URL 和请求类型(GET/POST 等)匹配到具体的控制器方法。
    • 注解(如 @GetMapping)会决定请求如何被路由到具体的方法,并执行该方法中的业务逻辑。
    • 控制器中的方法会调用被注入的服务类,服务类可以是抽象类的实现类,来完成具体的业务操作。

总结:

  • 前端发起的请求会根据 URL 和请求类型被映射到后端控制器类中的具体方法。
  • 注解用于路由请求,每个注解下通常只有一个方法来处理特定类型的请求。
  • 控制器可以通过依赖注入调用服务层,服务层可以是抽象类的实例化实现。

贡献者

The avatar of contributor named as sunchengzhi sunchengzhi

文件历史

撰写