1. 概述

本文将介绍Jetty库的使用。Jetty提供了一个可嵌入式运行的Web服务器,能轻松集成javax.servlet库。这种设计特别适合需要轻量级HTTP服务的场景,比如微服务集成或单元测试。

2. Maven依赖

启动项目前,先添加两个核心依赖:

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-server</artifactId>
    <version>9.4.3.v20170317</version>
</dependency>
<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-servlet</artifactId>
    <version>9.4.3.v20170317</version>
</dependency>

⚠️ 版本号需保持一致,避免兼容性问题。

3. 启动带Servlet的Jetty服务器

启动Jetty容器非常简单粗暴,只需三步:

  1. 创建Server实例
  2. 配置端口监听
  3. 注册Servlet
public class JettyServer {
    private Server server;

    public void start() throws Exception {
        server = new Server();
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(8090);  // 设置监听端口
        server.setConnectors(new Connector[] {connector});
    }
}

假设我们要创建一个返回JSON的/status接口:

public class BlockingServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
 
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().println("{ \"status\": \"ok\"}");
    }
}

注册Servlet并启动服务器:

servletHandler.addServletWithMapping(BlockingServlet.class, "/status");
server.start();

✅ 测试用例启动服务器:

@Before
public void setup() throws Exception {
    jettyServer = new JettyServer();
    jettyServer.start();
}

发送HTTP请求验证:

String url = "http://localhost:8090/status";
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
 
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);

4. 非阻塞式Servlet

Jetty对异步请求处理支持很到位。当遇到耗时I/O操作时(比如读取大文件),阻塞线程会降低吞吐量。这时可以用AsyncContext实现非阻塞处理:

public class AsyncServlet extends HttpServlet {
    private static String HEAVY_RESOURCE 
      = "This is some heavy resource that will be served in an async way";

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
 
        ByteBuffer content = ByteBuffer.wrap(
          HEAVY_RESOURCE.getBytes(StandardCharsets.UTF_8));

        AsyncContext async = request.startAsync();
        ServletOutputStream out = response.getOutputStream();
        out.setWriteListener(new WriteListener() {
            @Override
            public void onWritePossible() throws IOException {
                while (out.isReady()) {
                    if (!content.hasRemaining()) {
                        response.setStatus(200);
                        async.complete();  // 数据写完通知完成
                        return;
                    }
                    out.write(content.get());
                }
            }

            @Override
            public void onError(Throwable t) {
                getServletContext().log("Async Error", t);
                async.complete();
            }
        });
    }
}

注册异步Servlet:

servletHandler.addServletWithMapping(AsyncServlet.class, "/heavy/async");

测试异步接口:

String url = "http://localhost:8090/heavy/async";
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);

assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);
String responseContent = IOUtils.toString(
  response.getEntity().getContent(), StandardCharsets.UTF_8);
assertThat(responseContent).isEqualTo(
  "This is some heavy resource that will be served in an async way");

⚠️ 使用异步处理时,必须配置线程池(见下一节),否则性能可能更差。

5. Jetty配置优化

生产环境需要调整线程池参数,关键配置项:

参数 说明 推荐值
maxThreads 最大线程数 CPU核心数×8
minThreads 初始线程数 8-16
idleTimeout 线程空闲超时时间(毫秒) 60000

代码配置示例:

int maxThreads = 100;
int minThreads = 10;
int idleTimeout = 120;

QueuedThreadPool threadPool = new QueuedThreadPool(maxThreads, minThreads, idleTimeout);
server = new Server(threadPool);  // 应用线程池

踩坑经验:minThreads不要设得太高,启动时创建过多线程反而拖慢性能。

6. 总结

Jetty作为嵌入式服务器具有: ✅ 轻量级(启动快、内存占用小) ✅ 灵活(支持同步/异步处理) ✅ 易集成(Maven依赖即可)

完整代码可在GitHub获取。


原始标题:Embedded Jetty Server in Java