嵌入式Jetty:从代码配置迁移至XML配置的技术咨询
嘿,这个需求我太熟悉了——既要保留自己的自定义业务逻辑,又想复用Jetty现成的HTTP特性,用XML配置+代码混合开发简直是完美方案!我给你一步步拆解怎么做👇
核心思路:分工配置,兼顾灵活与简洁
我们可以把两类配置拆分处理:
- 自定义请求处理器:继续用代码实现(毕竟是业务独有的逻辑,XML写起来不灵活)
- Jetty标准HTTP特性(Basic Auth、重定向、HTTP/2、加密规则):用XML配置文件集中管理,避免代码里堆一堆通用HTTP配置
1. 保留代码中的自定义请求处理器
你的自定义处理器是业务核心,继续用Java代码实现就行,比如:
public class CustomRequestHandler extends AbstractHandler { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // 这里写你的自定义请求处理逻辑 response.setContentType("text/plain"); response.getWriter().write("Custom processed request: " + target); baseRequest.setHandled(true); // 标记请求已处理 } }
2. 编写Jetty XML配置文件,覆盖标准特性
创建jetty-config.xml,把HTTP/2、加密规则、Basic Auth、重定向这些通用特性都配置在这里:
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"> <Configure id="Server" class="org.eclipse.jetty.server.Server"> <!-- 1. 配置线程池 --> <Set name="ThreadPool"> <New class="org.eclipse.jetty.util.thread.QueuedThreadPool"> <Set name="minThreads">10</Set> <Set name="maxThreads">200</Set> </New> </Set> <!-- 2. 配置SSL/TLS:禁用旧协议+强密码套件 --> <New id="sslContextFactory" class="org.eclipse.jetty.server.SslConnectionFactory$SslContextFactory"> <Set name="KeyStorePath">./your-keystore.jks</Set> <Set name="KeyStorePassword">your-keystore-pass</Set> <Set name="KeyManagerPassword">your-key-manager-pass</Set> <!-- 禁用不安全的旧协议 --> <Set name="ExcludeProtocols"> <Array type="java.lang.String"> <Item>TLSv1</Item> <Item>TLSv1.1</Item> </Array> </Set> <!-- 只保留强密码套件 --> <Set name="IncludeCipherSuites"> <Array type="java.lang.String"> <Item>TLS_AES_256_GCM_SHA384</Item> <Item>TLS_CHACHA20_POLY1305_SHA256</Item> <Item>TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384</Item> </Array> </Set> <Set name="Protocol">TLSv1.3,TLSv1.2</Set> </New> <!-- 3. 配置HTTP/2连接器 --> <Call name="addConnector"> <Arg> <New class="org.eclipse.jetty.server.ServerConnector"> <Arg name="server"><Ref refid="Server"/></Arg> <Arg name="factories"> <Array type="org.eclipse.jetty.server.ConnectionFactory"> <Item><Ref refid="sslContextFactory"/></Item> <Item> <New class="org.eclipse.jetty.http2.server.HTTP2CConnectionFactory"> <Arg name="config"><New class="org.eclipse.jetty.server.HttpConfiguration"/></Arg> </New> </Item> <Item> <New class="org.eclipse.jetty.server.HttpConnectionFactory"> <Arg name="config"><New class="org.eclipse.jetty.server.HttpConfiguration"/></Arg> </New> </Item> </Array> </Arg> <Set name="port">8443</Set> </New> </Arg> </Call> <!-- 4. 配置Handler链:Basic Auth → 重定向 → 预留自定义处理器位置 --> <Set name="handler"> <New class="org.eclipse.jetty.server.handler.HandlerCollection"> <Set name="handlers"> <Array type="org.eclipse.jetty.server.Handler"> <!-- Basic Authentication 配置 --> <Item> <New class="org.eclipse.jetty.security.ConstraintSecurityHandler"> <Set name="authenticator"> <New class="org.eclipse.jetty.security.authentication.BasicAuthenticator"/> </Set> <Set name="loginService"> <New class="org.eclipse.jetty.security.HashLoginService"> <Set name="name">AppRealm</Set> <Set name="config">./realm.properties</Set> </New> </Set> <Set name="constraints"> <Array type="org.eclipse.jetty.util.security.Constraint"> <Item> <New class="org.eclipse.jetty.util.security.Constraint"> <Set name="name">auth</Set> <Set name="roles"><Array type="java.lang.String"><Item>user</Item></Array></Set> <Set name="authenticate">true</Set> </New> </Item> </Array> </Set> <!-- 嵌套后续Handler:重定向 + 自定义处理器 --> <Set name="handler"> <New class="org.eclipse.jetty.server.handler.HandlerCollection"> <Set name="handlers"> <Array type="org.eclipse.jetty.server.Handler"> <!-- 重定向示例:HTTP请求转HTTPS --> <Item> <New class="org.eclipse.jetty.server.handler.MovedContextHandler"> <Set name="contextPath">/</Set> <Set name="newContextURL">https://your-domain:8443/</Set> <Set name="statusCode">301</Set> </New> </Item> <!-- 预留自定义处理器的Wrapper,后续在代码中注入 --> <Item> <New id="CustomHandlerWrapper" class="org.eclipse.jetty.server.handler.HandlerWrapper"/> </Item> </Array> </Set> </New> </Set> </New> </Item> </Array> </Set> </New> </Set> </Configure>
补充:Basic Auth的用户配置文件realm.properties
在项目根目录创建这个文件,格式如下:
# 格式:用户名: 密码, 角色 alice: alice123, user bob: bob456, user, admin
3. 在代码中整合XML配置与自定义处理器
现在把两部分拼起来,代码只负责加载XML配置、注入自定义处理器,以及启用调试:
public class EmbeddedJettyApp { public static void main(String[] args) throws Exception { // 1. 从XML加载Jetty Server配置 XmlConfiguration config = new XmlConfiguration( new File("jetty-config.xml").toURI().toURL() ); Server server = (Server) config.configure(); // 2. 找到XML中预留的Wrapper,注入自定义处理器 HandlerWrapper customWrapper = (HandlerWrapper) server.getAttribute("CustomHandlerWrapper"); customWrapper.setHandler(new CustomRequestHandler()); // 3. 启用Server.dump()用于调试/监控:服务器启动时输出完整配置 server.addLifeCycleListener(new AbstractLifeCycleListener() { @Override public void lifeCycleStarted(LifeCycle event) { System.out.println("=== Jetty Server Configuration Dump ==="); server.dump(System.out); System.out.println("=== End of Dump ==="); } }); // 启动服务器 server.start(); server.join(); } }
4. 调试技巧:用好Server.dump()
Server.dump()会输出Jetty的完整运行时配置,你可以重点检查这些内容:
- HTTP/2连接器是否正确初始化
- 加密协议/密码套件是否按预期禁用/启用
- Handler链的顺序(Basic Auth → 重定向 → 自定义处理器)是否正确
- Basic Auth的Realm和用户配置是否加载成功
内容的提问来源于stack exchange,提问作者Michał Niklas
相关产品推荐
相关产品推荐

