Controller 开发实践
Feat Cloud 在设计 Controller 注解时,借鉴了 Spring 的设计理念,降低学习成本的同时进行了极致简化,专注于高性能和易用性。
Feat Cloud 提供以下核心注解:
@Controller
- 标记控制器类@RequestMapping
- 定义请求路由@Param
- 绑定查询参数@PathParam
- 绑定路径参数@InterceptorMapping
- 配置拦截器@PostConstruct
- 初始化回调@PreDestroy
- 销毁回调
@Controller
Section titled “@Controller”@Controller
用于标记一个类为控制器,作为 Spring 风格的注解设计,降低学习成本。
通常与 @RequestMapping
一起使用来定义请求映射路径。
定义:
@Target({ElementType.TYPE})@Retention(RetentionPolicy.SOURCE)@Documentedpublic @interface Controller { String value() default "";}
value 参数说明:
value()
定义了 Controller 的基础路径,其他方法级别的请求路径会基于这个基础路径。- 默认情况下,value 是一个空字符串,意味着没有基础路径前缀。
- 示例:如果设置
@Controller("/user")
,那么该 Controller 下的所有方法将通过/user
路径前缀访问。
@RequestMapping
Section titled “@RequestMapping”@RequestMapping
用于标记方法,表示该方法处理特定的 HTTP 请求路径。
支持指定HTTP请求方法,有效类型:GET
, HEAD
, POST
, PUT
, PATCH
, DELETE
, OPTIONS
, TRACE
定义:
@Target({ElementType.METHOD})@Retention(RetentionPolicy.SOURCE)@Documentedpublic @interface RequestMapping { String value() default "";
RequestMethod[] method() default {};}
参数说明:
- value: 指定与该方法关联的 URL 路径,默认为空字符串,意味着使用 Controller 级别的路径前缀(如果有)。
- method: 指定该方法支持的 HTTP 请求类型,默认不限制请求方法,即所有类型都可以访问该方法。
@Param
Section titled “@Param”@Param
用于绑定请求中的查询参数(Query Parameters)到方法参数上。当方法参数为自定义POJO类型时,可无需使用@Param
注解,框架会自动进行参数绑定。
定义:
@Target({ElementType.PARAMETER})@Retention(RetentionPolicy.SOURCE)@Documentedpublic @interface Param { /** * 指定要绑定的查询参数的名称。 * * @return 参数名称 */ String value();}
value 参数说明:
- 如果 HTTP 请求中没有与
value
匹配的查询参数,则方法参数将被赋予默认值(如 null、0 或 false,取决于类型)。 - 示例:若方法定义为
@Param("id") int userId
,则会尝试从请求中获取名为id
的参数并转换为整数赋值给userId
。
@PathParam
Section titled “@PathParam”@PathParam
用于绑定请求中的路径参数(Path Parameters)到方法参数上。
定义:
@Target({ElementType.PARAMETER})@Retention(RetentionPolicy.SOURCE)@Documentedpublic @interface PathParam { /** * 参数名称 * * @return 参数名称 */ String value();}
value 参数说明: 指定要绑定的路径参数的名称,该名称必须与路由中定义的占位符名称一致。
- 示例:若 URL 定义为
/user/{id}
,则应使用@PathParam("id")
来绑定路径中的id
值到方法参数。 - 如果 HTTP 请求路径中没有匹配的参数名,则框架会抛出异常或自动赋予默认值(如 null、0 等),具体行为取决于框架实现和参数类型。
@InterceptorMapping
Section titled “@InterceptorMapping”@InterceptorMapping
用于为特定的请求路径添加拦截器逻辑,在请求到达目标方法之前执行一些操作。
定义:
@Target({ElementType.METHOD})@Retention(RetentionPolicy.SOURCE)@Documentedpublic @interface InterceptorMapping {
String[] value() default "";}
value 参数说明: 指定拦截器应用的 URL 路径模式数组。
- 支持精确匹配(如
/path
)和通配符匹配(如/path/*
)。 - 如果未指定,默认为空数组,表示拦截器不匹配任何请求。
- 示例:若设置
@InterceptorMapping({"/user", "/api/*"})
,则该拦截器会作用于所有/user
和/api
下的请求路径。
基于项目中的实际示例,创建一个简单的 Controller:
@Controller("demo2")public class Demo2Controller {
// 基础路径映射 @RequestMapping("") public String test1() { return "hello world"; }
// 支持查询参数 @RequestMapping("/param1") public String test2(@Param("param") String param) { return "hello " + param; }
// 多个查询参数 @RequestMapping("/param2") public String test3(@Param("param1") String param1, @Param("param2") String param2) { return "hello " + param1 + " " + param2; }
// 支持对象参数绑定 @RequestMapping("/param3") public String test4(TestParam param) { return "hello " + param.getParam1() + " " + param.getParam2(); }
// 命名参数对象 @RequestMapping("/param4") public String test5(@Param("param") TestParam param) { return "hello param is " + param; }}
对应的参数对象:
public class TestParam { private String param1; private String param2;
// getters and setters public String getParam1() { return param1; } public void setParam1(String param1) { this.param1 = param1; }
public String getParam2() { return param2; } public void setParam2(String param2) { this.param2 = param2; }}
生命周期管理
Section titled “生命周期管理”Feat Cloud 支持 Bean 生命周期注解,可以在适当的时机执行初始化和清理逻辑:
@Controllerclass Demo1Controller {
@PostConstruct public void init() { System.out.println("Controller 初始化完成"); }
@RequestMapping public String test1() { return "hello"; }
@PreDestroy public void destroy() { System.out.println("Controller 正在销毁"); }}
通过 @InterceptorMapping
注解可以为特定路径添加拦截器:
@Controller("api")public class ApiController {
@RequestMapping("/users") public String getUsers() { return "用户列表"; }
// 为API路径添加拦截器 @InterceptorMapping({"/api/users/*", "/api/admin/*"}) public Interceptor authInterceptor() { return (context, completableFuture, chain) -> { // 前置处理:权限验证 String token = context.Request.getHeader("Authorization"); if (token == null || !isValidToken(token)) { context.Response.setStatus(401); context.Response.write("Unauthorized".getBytes()); completableFuture.complete(null); return; }
// 继续执行请求链 chain.proceed(context, completableFuture);
// 后置处理:记录访问日志 System.out.println("API 访问完成: " + context.Request.getRequestURI()); }; }
private boolean isValidToken(String token) { // 实际的 token 验证逻辑 return "valid-token".equals(token); }}
拦截器使用注意事项:
- 路径匹配:支持精确匹配和通配符匹配(
*
) - 执行顺序:多个拦截器按定义顺序执行
- 异步处理:正确处理
CompletableFuture
以支持异步请求 - 异常处理:拦截器内需要处理可能的异常情况