Skip to content

Router 路由组件

This content is not available in your language yet.

本教程将带你掌握 Feat Router 组件的使用方法,它就像一个聪明的交通警察,能够准确地将每个 HTTP 请求引导到正确的处理程序。

  • 如何创建和配置 Router
  • 使用多种路由匹配模式(精确匹配、路径参数、通配符)
  • 管理 Session 会话状态
  • 使用拦截器实现请求预处理

在开始本教程之前,请确保你已完成:

Router 组件是 Feat 框架中负责 HTTP 请求路由分发的核心组件。它不仅能根据请求路径将请求分发到对应的处理器,还提供了 Session 管理、请求拦截等强大功能。

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 处理器传递给服务器。

Router 支持多种路由匹配模式,让你能够灵活地定义 API 接口。

最简单的匹配方式是精确路径匹配,适用于固定路径的接口:

router.route("/user/profile", ctx -> {
ctx.Response.write("用户档案页面");
});

当需要从 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 会按照以下优先级进行匹配:

  1. 精确路径匹配(最高优先级)
  2. 路径参数匹配
  3. 通配符匹配(最低优先级)

来看一个形象的路由匹配示意图:

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

Router 内置了 Session 管理功能,让你能够轻松地在用户请求之间保持状态。

可以通过 SessionOptions 配置 Session 的行为:

Router router = new Router();
// 设置 Session 最大存活时间(秒)
router.getSessionOptions().setMaxAge(1800); // 30分钟

在请求处理中可以方便地使用 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("请先登录");
}
});
// 销毁 Session
router.route("/logout", ctx -> {
Session session = ctx.session();
if (session != null) {
// 手动使 Session 失效
session.invalidate();
}
ctx.Response.write("已退出登录");
});
Session 的生命周期管理示意图:
```mermaid
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

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 路由解决方案,具有以下优势:

  1. 高性能:基于前缀树的路由匹配算法,提供高效的路由查找性能
  2. 灵活性:支持多种路由匹配模式,满足不同业务场景需求
  3. 易用性:链式调用 API 设计,简化路由配置
  4. 扩展性:支持拦截器机制,方便添加自定义处理逻辑
  5. 内置功能:集成 Session 管理,无需额外配置

通过合理使用 Router 组件,可以快速构建功能丰富、性能优良的 Web 应用。在实际开发中,建议结合具体业务场景,合理规划路由结构,充分发挥 Router 的强大功能。

掌握了这些基础,你就能轻松应对大部分路由场景了。接下来不妨尝试创建一个自己的 Web 服务,体验一下 Router 的强大功能吧!