wastnet 是一款零依赖、自研的 Java Web 服务器,核心基于 JDK 原生 NIO 构建 Reactor 多路复用模型,不依赖 Netty、Tomcat 等任何第三方网络库。其 HTTP/2(h2 / h2c)协议栈从 HPACK、Huffman 到 ALPN 均为完全自研实现,是框架的核心特色之一;在基准测试中吞吐对标 Undertow。
本文介绍 wastnet 的路由分发组件 HttpRouterHandler。它是一个高性能、支持链式配置的 HTTP 路由 Handler,能力覆盖 精确匹配、前缀匹配、正则匹配、HTTP 方法过滤、反向代理、静态资源、SSE、WebSocket / h2c 升级,并内置上下文路径(context path)自动前缀与路由级拦截器链。
本文从 API 形态到匹配优先级、再到实战示例,完整介绍它的使用方式。
为什么需要 HttpRouterHandler
HTTPServer 的 requestHandler 接受一个 HttpRequestHandler,但原生 Handler 只有一个 handle(request, response) 入口,所有路径判断要自己写。当接口变多,你需要一个「按路径分发」的组件:
HTTPServer.of(8080)
.requestHandler(router)
.start();
HttpRouterHandler 自身也实现 HttpRequestHandler,可直接挂到 HTTPServer 上,内部再把请求派发给各个子路由。
创建与上下文路径
// 根上下文("/"),所有路由直接挂在根下
HttpRouterHandler router = new HttpRouterHandler();
// 带上下文路径,例如部署在 /api 下
HttpRouterHandler router = new HttpRouterHandler("/api");
-
上下文路径规则:
-
必须以 / 开头,否则自动补 /;
-
尾部多余的 / 会被自动裁剪(/api/ → /api);
-
所有通过 route / exactRoute / get / post / ws / h2c 注册的子路由,匹配时都会自动叠加该上下文路径;
-
访问根 / 且配置非空 contextPath 时,默认 301 重定向到 contextPath/(可用 autoRedirect(false) 关闭)。
匹配类型
HttpRouterHandler 提供三种匹配语义,按注册方式区分:
1. 精确匹配 exactRoute
路径完全一致才命中,无正则开销,性能最好。
router.exactRoute("/user", (path, req, resp) -> resp.status(200).body("User".getBytes()));
router.exactRoute("/user", route, HttpMethod.GET, HttpMethod.POST);
2. 前缀匹配 route
router.route("/api", apiHandler);
3. 正则匹配
以 ^ 开头即视为正则;以 $ 结尾表示严格全匹配,否则自动追加 .* 作为前缀匹配。
// 严格全匹配 /v1/resource、/v2/resource,不匹配 /v1/resource/abc
router.route("^/v\\d+/resource$", regexHandler);
// 正则前缀:匹配 /articles/2026 及之后任意内容
router.route("^/articles/.*", articleHandler);
4. HTTP 方法快捷注册
除 exactRoute 的方法重载外,还提供语义化快捷方法,自动约束方法并精确匹配:
router.get("/user", getHandler);
router.post("/user", postHandler);
router.put("/user", putHandler);
router.delete("/user", deleteHandler);
router.patch("/user", patchHandler);
匹配优先级
一次请求进入 handle() 后的判定顺序:
-
上下文路径校验:不匹配 contextPath 直接 404(或根路径重定向);
-
路由级拦截器:返回 false 可短路请求;
-
精确匹配 exactRoutes(最高优先级,含 get/post/... 注册项);
-
健康检查路由 /health(可被精确路由覆盖);
-
前缀 / 正则匹配 routes(按注册顺序,第一个命中即返回);
-
兜底 404(默认 404 Not Found,或自定义 notFoundHandler)。
反向代理
// 简单代理(不重写路径)
router.proxy("/rest", "http://192.168.1.226:19028");
// 带路径重写
router.proxy("/rest", "http://192.168.1.226:19028", true);
// 完整配置:升级、读超时、自定义 rewrite 函数
HttpProxyConfig config = HttpProxyConfig.target("http://192.168.1.226:19028")
.upgrade(true)
.readTimeout(5000)
.rewrite(path -> path.replaceFirst("^/rest", ""));
router.proxy("/rest", config);
静态资源
HttpResourceRoute 负责静态文件服务(ETag、Last-Modified、GZIP 等由框架处理):
router.resource(new HttpResourceRoute("/", "./dist"));
routePath 为资源挂载路径,框架会自动叠加 contextPath 作为 base path。
SSE 服务端推送
router.sse("/events", emitter -> {
executor.submit(() -> {
emitter.emit("hello");
emitter.close();
});
});
// 自定义超时(毫秒)
router.sse("/events", 60_000, emitter -> { /* ... */ });
WebSocket 升级
继承 DefaultUpgradeHandler,注册时自动叠加 contextPath:
router.ws("/ws", webSocketResource);
路由级拦截器
在上下文解析之后、路由分发之前运行,可形成有序链;任一返回 false 即短路请求(例如鉴权、跨域、日志):
router.interceptor((path, request, response) -> {
String token = request.getHeader("Authorization");
if (token == null) {
response.status(401).body("unauthorized".getBytes());
return false;
}
return true;
});
404 兜底
router.notFoundHandler((request, response) -> {
response.status(404).body("Custom 404".getBytes());
});
另外,针对 OPTIONS * 的 RFC 7230 星号请求,框架默认直接返回 200(查询服务器能力),不进入 404。
完整示例
参考 wastnet-test 中的 RouterHandlerTest:
HttpRoute userHandler = (path, req, resp) -> resp.status(200).body(("User path: " + path).getBytes());
HttpRoute apiHandler = (path, req, resp) -> resp.status(200).body("OK".getBytes());
HttpRoute regexHandler = (path, req, resp) -> resp.status(200).body(("Regex path: " + path).getBytes());
HttpRouterHandler router = new HttpRouterHandler("/api");
router.exactRoute("/user", userHandler);
router.route("/api", apiHandler); // 实际匹配 /api + 子路径
router.route("^/v\\d+/resource$", regexHandler); // 正则严格匹配
router.resource(new HttpResourceRoute("/", "./dist"));
router.notFoundHandler((req, resp) -> resp.status(404).body("Custom 404".getBytes()));
HTTPServer.of(8080).requestHandler(router).start();
-
启动后可用以下 URL 验证:
-
精确匹配:/api/user
-
前缀匹配:/api/api/xxx
-
正则匹配:/api/v1/resource
-
静态资源:/api/index.html
小结
HttpRouterHandler 把路由、代理、静态资源、SSE、WebSocket 收敛到一个链式 API 中,零依赖、易组合。核心要点:
相关链接
wastnet 基于 Apache 2.0 协议完全开源、免费使用,欢迎体验与反馈。