Router 路由组件
本教程将带你掌握 Feat Router 组件的使用方法,它就像一个聪明的交通警察,能够准确地将每个 HTTP 请求引导到正确的处理程序。
- 如何创建和配置 Router
- 使用多种路由匹配模式(精确匹配、路径参数、通配符)
- 管理 Session 会话状态
- 使用拦截器实现请求预处理
在开始本教程之前,请确保你已完成:
- Feat Server 快速入门 - 了解基本的 HTTP 服务器创建
- JDK 8 或更高版本
- 熟悉 Java Lambda 表达式
Router 简介
Section titled “Router 简介”Router 组件是 Feat 框架中负责 HTTP 请求路由分发的核心组件。它不仅能根据请求路径将请求分发到对应的处理器,还提供了 Session 管理、请求拦截等强大功能。
想象一下,当你的应用程序有成百上千个不同的 API 接口时,如果没有一个好的路由机制,代码将会变得多么混乱!而 Router 正是解决这个问题的利器。
让我们从一个简单的例子开始,看看如何使用 Router 创建一个基础的 Web 服务:
// 实践导向的示例:展示如何创建带有路由的HTTP服务public class RouterDemo { public static void main(String[] args) { // 创建路由管理器 Router router = new Router();
// 配置一个简单的路由 router.route("/", ctx -> { ctx.Response.write("欢迎来到 Feat Router 世界!"); });
// 启动服务器并使用路由管理器 Feat.httpServer() .httpHandler(router) .listen(8080); }}这段代码展示了 Router 的基本用法。我们创建了一个 Router 实例,配置了一个处理根路径 / 的路由,然后将其作为 HTTP 处理器传递给服务器。
路由匹配详解
Section titled “路由匹配详解”Router 支持多种路由匹配模式,让你能够灵活地定义 API 接口。
精确路径匹配
Section titled “精确路径匹配”最简单的匹配方式是精确路径匹配,适用于固定路径的接口:
router.route("/user/profile", ctx -> { ctx.Response.write("用户档案页面");});路径参数匹配
Section titled “路径参数匹配”当需要从 URL 中提取参数时,可以使用路径参数匹配:
router.route("/user/:id", ctx -> { // 从路径中提取 id 参数 String userId = ctx.pathParam("id"); ctx.Response.write("用户ID: " + userId);});对于需要匹配多个路径的情况,可以使用通配符:
// 匹配 /static/ 下的所有路径router.route("/static/*", ctx -> { ctx.Response.write("静态资源处理");});当多个路由规则可能匹配同一个请求时,Router 会按照以下优先级进行匹配:
- 精确路径匹配(最高优先级)
- 路径参数匹配
- 通配符匹配(最低优先级)
来看一个形象的路由匹配示意图:
graph TD
A[根路径 /] --> B[api]
A --> C[user]
A --> D[*]
B --> E[v1]
C --> F[:id]
E --> G[用户API处理器]
F --> H[用户详情处理器]
D --> I[默认处理器]
style A fill:#4CAF50
style B fill:#2196F3
style C fill:#2196F3
style D fill:#2196F3
style E fill:#FF9800
style F fill:#FF9800
style G fill:#E91E63
style H fill:#E91E63
style I fill:#E91E63
会话管理(Session)
Section titled “会话管理(Session)”Router 内置了 Session 管理功能,让你能够轻松地在用户请求之间保持状态。
配置 Session
Section titled “配置 Session”可以通过 SessionOptions 配置 Session 的行为:
Router router = new Router();// 设置 Session 最大存活时间(秒)router.getSessionOptions().setMaxAge(1800); // 30分钟使用 Session
Section titled “使用 Session”在请求处理中可以方便地使用 Session:
// 创建 Session 并存储数据router.route("/login", ctx -> { // 获取或创建 Session Session session = ctx.session(); // 设置 Session 属性 session.put("userId", "12345"); session.put("username", "张三"); ctx.Response.write("登录成功");});
// 读取 Session 数据router.route("/profile", ctx -> { Session session = ctx.session(); // 获取 Session 但不创建 if (session != null) { String username = session.get("username"); ctx.Response.write("欢迎," + username); } else { ctx.Response.setHttpStatus(HttpStatus.UNAUTHORIZED); ctx.Response.write("请先登录"); }});
// 销毁 Sessionrouter.route("/logout", ctx -> { Session session = ctx.session(); if (session != null) { // 手动使 Session 失效 session.invalidate(); } ctx.Response.write("已退出登录");});Session 的生命周期管理示意图:
graph LR
A[创建Session] --> B[访问/更新]
B --> C[重置超时]
C --> B
B --> D[超时]
D --> E[销毁]
C --> D
style A fill:#4CAF50
style B fill:#FFC107
style C fill:#FFC107
style D fill:#FF5722
style E fill:#F44336
拦截器允许你在请求处理前后执行自定义逻辑,比如权限验证、日志记录等。这就像在请求处理流水线上设置检查点一样。
实现 Interceptor 接口创建自定义拦截器:
public class LogInterceptor implements Interceptor { @Override public void intercept(Context ctx, CompletableFuture<Void> completableFuture, Chain chain) throws Throwable { System.out.println("请求开始: " + ctx.Request.getRequestURI()); try { // 继续执行后续的拦截器或目标处理器 chain.proceed(ctx, completableFuture); } finally { System.out.println("请求结束: " + ctx.Request.getRequestURI()); } }}通过 addInterceptor 方法为特定路径模式配置拦截器:
Router router = new Router();// 为所有 /api 路径下的请求添加日志拦截器router.addInterceptor("/api/*", new LogInterceptor());
// 为管理接口添加权限验证拦截器router.addInterceptor("/admin/*", new AuthInterceptor());拦截器执行流程如下:
graph LR
A[客户端请求] --> B[拦截器1前置处理]
B --> C[拦截器2前置处理]
C --> D[目标路由处理]
D --> E[拦截器2后置处理]
E --> F[拦截器1后置处理]
F --> G[响应客户端]
style A fill:#4CAF50
style B fill:#2196F3
style C fill:#2196F3
style D fill:#FF9800
style E fill:#2196F3
style F fill:#2196F3
style G fill:#4CAF50
让我们通过一个完整的示例来看看 Router 的各种功能是如何协同工作的:
public class CompleteRouterDemo { public static void main(String[] args) { Router router = new Router();
// 配置 Session router.getSessionOptions().setMaxAge(1800); // 30分钟
// 添加日志拦截器 router.addInterceptor("/*", (ctx, future, chain) -> { long start = System.currentTimeMillis(); System.out.println("开始处理请求: " + ctx.Request.getRequestURI()); try { chain.proceed(ctx, future); } finally { long end = System.currentTimeMillis(); System.out.println("请求处理完成,耗时: " + (end - start) + "ms"); } });
// 配置路由 router.route("/", ctx -> { ctx.Response.write("欢迎使用 Feat Router!"); });
// Session 示例 router.route("/login", ctx -> { Session session = ctx.session(); session.put("loginTime", String.valueOf(System.currentTimeMillis())); session.put("username", "张三"); ctx.Response.write("登录成功"); });
router.route("/user/:id", ctx -> { String id = ctx.pathParam("id"); Session session = ctx.session(); // 获取 Session 但不创建 if (session != null) { String loginTime = session.get("loginTime"); ctx.Response.write("用户 " + id + ",登录时间: " + loginTime); } else { ctx.Response.setHttpStatus(HttpStatus.UNAUTHORIZED); ctx.Response.write("请先登录"); } });
// 通配符匹配示例 router.route("/api/*", ctx -> { ctx.Response.write("API 接口处理: " + ctx.Request.getRequestURI()); });
// 启动服务器 Feat.httpServer() .httpHandler(router) .listen(8080); }}有关完整示例,请参见 RouterSessionDemo.java
HTTP 方法支持
Section titled “HTTP 方法支持”Router 还支持针对不同 HTTP 方法的路由配置:
// 为 GET 请求配置路由router.route("/user", "GET", ctx -> { ctx.Response.write("获取用户列表");});
// 为 POST 请求配置路由router.route("/user", "POST", ctx -> { ctx.Response.write("创建新用户");});
// 为多个 HTTP 方法配置同一个处理器router.route("/user/:id", new String[]{"PUT", "PATCH"}, ctx -> { String userId = ctx.pathParam("id"); ctx.Response.write("更新用户: " + userId);});Feat Router 组件提供了一套完整的 HTTP 路由解决方案,具有以下优势:
- 高性能:基于前缀树的路由匹配算法,提供高效的路由查找性能
- 灵活性:支持多种路由匹配模式,满足不同业务场景需求
- 易用性:链式调用 API 设计,简化路由配置
- 扩展性:支持拦截器机制,方便添加自定义处理逻辑
- 内置功能:集成 Session 管理,无需额外配置
通过合理使用 Router 组件,可以快速构建功能丰富、性能优良的 Web 应用。在实际开发中,建议结合具体业务场景,合理规划路由结构,充分发挥 Router 的强大功能。
掌握了这些基础,你就能轻松应对大部分路由场景了。接下来不妨尝试创建一个自己的 Web 服务,体验一下 Router 的强大功能吧!