跳转到内容

编写 Feat Cloud 控制器

这篇教程假设你已经完成 Feat Cloud 快速入门,并且已经能跑起一个最小控制器。现在我们进一步把它写成更像真实项目的接口层。

  • 使用 @Controller 定义控制器和基础路径
  • 使用 @RequestMapping 映射不同的 URL 和 HTTP 方法
  • 使用 @Param 读取查询参数
  • 使用 @PathParam 读取路径参数
  • 了解 SessionContextAsyncResponse 这几类常见注入参数

下面是一个最小但足够真实的控制器示例:

UserController.java
import tech.smartboot.feat.cloud.annotation.Controller;
import tech.smartboot.feat.cloud.annotation.Param;
import tech.smartboot.feat.cloud.annotation.PathParam;
import tech.smartboot.feat.cloud.annotation.RequestMapping;
import tech.smartboot.feat.cloud.annotation.RequestMethod;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@Controller("users")
public class UserController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() {
return "hello controller";
}
@RequestMapping(value = "/search", method = RequestMethod.GET)
public String search(@Param("keyword") String keyword) {
return "search: " + keyword;
}
@RequestMapping(value = "/:username", method = RequestMethod.GET)
public Map<String, Object> profile(@PathParam("username") String username) {
Map<String, Object> data = new HashMap<>();
data.put("username", username);
data.put("roles", Collections.singletonList("user"));
return data;
}
}

如果你的启动类和控制器不在同一个根包下,启动时要显式指定扫描范围:

Bootstrap.java
import tech.smartboot.feat.cloud.FeatCloud;
public class Bootstrap {
public static void main(String[] args) {
FeatCloud.cloudServer(opts -> opts.setPackages("com.example")).listen();
}
}

步骤 2:理解三种最常见的映射方式

Section titled “步骤 2:理解三种最常见的映射方式”

@Controller("users") 表示这个控制器下的方法都会挂在 /users 之下。

例如:

  • @Controller("users") + @RequestMapping("/hello")
  • 最终路径就是 /users/hello

@Param("keyword") 用于读取 URL 查询参数:

@RequestMapping(value = "/search", method = RequestMethod.GET)
public String search(@Param("keyword") String keyword) {
return "search: " + keyword;
}

调用方式:

Terminal window
curl "http://localhost:8080/users/search?keyword=feat"

@PathParam("username") 用于读取 URL 路径中的变量:

@RequestMapping(value = "/:username", method = RequestMethod.GET)
public String profile(@PathParam("username") String username) {
return "hello " + username;
}

调用方式:

Terminal window
curl http://localhost:8080/users/smartboot

如果你按上面的例子运行控制器,可以依次验证:

Terminal window
curl http://localhost:8080/users/hello
curl "http://localhost:8080/users/search?keyword=feat"
curl http://localhost:8080/users/smartboot

预期结果大致如下:

hello controller
search: feat
{"username":"smartboot","roles":["user"]}

这里顺便能看到 Feat Cloud 的一个重要特征:

  • 返回 String 时,直接输出文本
  • 返回对象或集合时,会自动序列化为 JSON

如果同一路径要区分 GETPOST,显式指定 RequestMethod

import tech.smartboot.feat.cloud.annotation.RequestMethod;
@Controller("articles")
public class ArticleController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String list() {
return "list articles";
}
@RequestMapping(value = "/", method = RequestMethod.POST)
public String create() {
return "create article";
}
}

这比只写一个宽泛映射更清晰,也更适合真实 API 设计。

除了 @Param@PathParam,控制器方法里还有几类常见参数可直接注入。

import tech.smartboot.feat.core.server.Session;
@RequestMapping("/session")
public String session(Session session) {
return session.getSessionId();
}

适合读取或写入会话信息。

import tech.smartboot.feat.router.Context;
@RequestMapping("/context")
public String context(Context context) {
return context.Request.getRequestURI();
}

适合拿到底层请求上下文,做更细的控制。

import tech.smartboot.feat.cloud.AsyncResponse;
@RequestMapping("/async")
public AsyncResponse async() {
return new AsyncResponse();
}

适合后续做异步返回或延迟完成响应。真正的异步处理细节建议放到专门的异步教程里学。

优先检查:

  1. 控制器类是否在 Feat Cloud 的扫描范围内
  2. @Controller@RequestMapping 是否都已加上
  3. 实际访问路径是否等于“控制器路径 + 方法路径”

优先检查 URL 里参数名是否与 @Param("...") 完全一致。

优先检查:

  1. 路由模板是否写成 /:username
  2. @PathParam("username") 的名字是否和模板保持一致