Controller 开发
Feat Cloud 在设计 Controller 注解时,一定程度上延用了 Spring 的设计理念,使得用户更容易理解和运用。
当然,我们也并非完全复刻 Spring 的 Controller 注解,而是进行了极致的简化,剔除了不必要的灵活性。
相关注解:
- tech.smartboot.feat.cloud.annotation.Controller
- tech.smartboot.feat.cloud.annotation.RequestMapping
- tech.smartboot.feat.cloud.annotation.Param
- tech.smartboot.feat.cloud.annotation.PathParam
- tech.smartboot.feat.cloud.annotation.InterceptorMapping
@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("userApi")public class UserController {
// 支持路径参数 @RequestMapping("/users/:id") public String getUser(@PathParam("id") String id) { return "User: " + id; }
// 支持查询参数 @RequestMapping("/users/search") public String searchUsers(@Param("name") String name, @Param("age") int age) { return "Search users with name: " + name + ", age: " + age; }
// 支持对象参数绑定 @RequestMapping("/users/create") public RestResult<Map<String, String>> createUser(UserParam param) { RestResult<Map<String, String>> result = new RestResult<>(); result.setData(Collections.singletonMap("id", "123")); return result; }}
通过 @InterceptorMapping
注解可以为 Controller 添加拦截器,以实现请求的预处理或后处理逻辑。
// 为用户API添加拦截器@InterceptorMapping({"/users/*"})public Interceptor userApiInterceptor() { return (context, completableFuture, chain) -> { System.out.println("Intercepting user API request..."); // 可以在请求处理前执行前置逻辑
// 继续执行请求链 chain.proceed(context, completableFuture);
// 可以在请求处理后执行后置逻辑 System.out.println("Finished intercepting user API request."); };}
说明与注意事项:
- 拦截路径匹配:
@InterceptorMapping
的value
属性用于指定拦截器生效的路径模式,支持精确匹配(如/user
)和通配符匹配(如/user/*
)。 - 拦截器顺序:多个拦截器按照定义顺序依次执行,形成拦截器链。
- 异步处理:由于 HTTP 请求处理可能是异步的,因此拦截器中应正确处理
CompletableFuture
。 - 避免阻塞:拦截器中的逻辑不应长时间阻塞主线程,建议将耗时操作提交到独立线程池。
- 异常处理:拦截器内部需要自行捕获并处理异常,防止因未处理异常导致请求失败。
与 Spring Boot 相比,Feat Cloud 的注解处理方式有本质区别:
特性 | Feat Cloud | Spring Boot |
---|---|---|
注解处理时机 | 编译期 | 运行时 |
反射使用 | 不需要 | 需要 |
性能 | 更高 | 相对较低 |
灵活性 | 简洁高效 | 更加灵活 |
这种设计使得 Feat Cloud 在保持类似 Spring Boot 开发体验的同时,实现了更好的性能表现。