1. 概述
Undertow 是 JBoss 出品的超轻量级高性能 Web 服务器。它同时支持阻塞和非阻塞 NIO API。
由于完全由 Java 编写,可作为嵌入式组件集成到任何 JVM 应用中,甚至 JBoss 的 WildFly 服务器内部也使用 Undertow 来提升性能。
本文将带您快速掌握 Undertow 的核心特性及实战用法。
2. 为什么选择 Undertow?
✅ 极致轻量:核心包仅 1MB,嵌入式模式运行时堆内存占用仅需 4MB
✅ Servlet 3.1 完整支持:满足企业级开发需求
✅ WebSocket 原生支持:包括 JSR-356 规范实现
✅ 持久连接优化:默认启用 HTTP keep-alive,显著提升客户端性能
3. Undertow 实战
3.1 Maven 依赖
在 pom.xml
添加核心依赖:
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
<version>1.4.18.Final</version>
</dependency>
构建可执行 JAR 还需添加 shade 插件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
最新版本可通过 Maven 中央仓库 获取
3.2 快速启动服务器
通过 Builder API 创建简单 Web 服务:
public class SimpleServer {
public static void main(String[] args) {
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(exchange -> {
exchange.getResponseHeaders()
.put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender().send("Hello Baeldung");
})
.build();
server.start();
}
}
关键点解析:
- 绑定 8080 端口到 localhost
- 使用 Lambda 表达式定义请求处理器
- 也可用传统匿名类实现(见下文)
⚠️ 核心组件:HttpHandler
是定制行为的关键插件。以下为等效的传统写法:
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(new HttpHandler() {
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
exchange.getResponseHeaders()
.put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender().send("Hello Baeldung");
}
})
.build();
3.3 安全认证实现
3.3.1 身份管理器
实现 IdentityManager
接口处理认证逻辑:
public class CustomIdentityManager implements IdentityManager {
private Map<String, char[]> users;
// 标准构造器
@Override
public Account verify(Account account) {
return account;
}
@Override
public Account verify(Credential credential) {
return null;
}
@Override
public Account verify(String id, Credential credential) {
Account account = getAccount(id);
if (account != null && verifyCredential(account, credential)) {
return account;
}
return null;
}
}
3.3.2 安全链构建
创建安全处理链:
private static HttpHandler addSecurity(
HttpHandler toWrap,
IdentityManager identityManager) {
HttpHandler handler = toWrap;
handler = new AuthenticationCallHandler(handler);
handler = new AuthenticationConstraintHandler(handler);
List<AuthenticationMechanism> mechanisms = Collections.singletonList(
new BasicAuthenticationMechanism("Baeldung_Realm"));
handler = new AuthenticationMechanismsHandler(handler, mechanisms);
handler = new SecurityInitialHandler(
AuthenticationMode.PRO_ACTIVE, identityManager, handler);
return handler;
}
认证模式说明:
PRO_ACTIVE
:所有请求立即触发认证CONSTRAINT_DRIVEN
:仅当约束条件触发时认证
3.3.3 集成到服务器
public static void main(String[] args) {
Map<String, char[]> users = new HashMap<>(2);
users.put("root", "password".toCharArray());
users.put("admin", "password".toCharArray());
IdentityManager idm = new CustomIdentityManager(users);
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(addSecurity(e -> setExchange(e), idm))
.build();
server.start();
}
private static void setExchange(HttpServerExchange exchange) {
SecurityContext context = exchange.getSecurityContext();
exchange.getResponseSender().send("Hello " +
context.getAuthenticatedAccount().getPrincipal().getName(),
IoCallback.END_EXCHANGE);
}
3.4 WebSocket 支持
通过 WebSocketHttpExchange
创建 Socket 通道:
public static void main(String[] args) {
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(path()
.addPrefixPath("/baeldungApp", websocket(
(exchange, channel) -> {
channel.getReceiveSetter().set(getListener());
channel.resumeReceives();
}))
.addPrefixPath("/", resource(new ClassPathResourceManager(
SocketServer.class.getClassLoader(),
SocketServer.class.getPackage()))
.addWelcomeFiles("index.html")))
.build();
server.start();
}
private static AbstractReceiveListener getListener() {
return new AbstractReceiveListener() {
@Override
protected void onFullTextMessage(WebSocketChannel channel,
BufferedTextMessage message) {
String messageData = message.getData();
for (WebSocketChannel session : channel.getPeerConnections()) {
WebSockets.sendText(messageData, session, null);
}
}
};
}
配套 index.html
可通过原生 JavaScript WebSocket API 连接。
3.5 文件服务器
简单粗暴的文件服务实现:
public static void main( String[] args ) {
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(resource(new PathResourceManager(
Paths.get(System.getProperty("user.home")), 100))
.setDirectoryListingEnabled(true))
.build();
server.start();
}
自动生成目录列表页面,无需额外开发
4. Spring Boot 集成
除 Tomcat 和 Jetty 外,Spring Boot 同样支持 Undertow 作为嵌入式容器。添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<version>1.5.6.RELEASE</version>
</dependency>
最新版本见 Maven 中央仓库
5. 总结
本文系统介绍了 Undertow 的核心优势及典型应用场景,包括:
- 基础服务器搭建
- 安全认证实现
- WebSocket 支持
- 文件服务功能
- Spring Boot 集成方案
其轻量级特性和高性能表现,特别适合微服务架构及资源敏感型场景。