Jetty使用教程(四:21-22)—Jetty开发指南
Posted 已往之不谏
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jetty使用教程(四:21-22)—Jetty开发指南相关的知识,希望对你有一定的参考价值。
二十一、嵌入式开发
21.1 Jetty嵌入式开发HelloWorld
本章节将提供一些教程,通过Jetty API快速开发嵌入式代码
21.1.1 下载Jetty的jar包
Jetty目前已经把所有功能分解成小的jar包,用户可以根据需要选择合适的jar包,来实现需要的功能。通常建议用户使用maven等管理工具来管理jar包,然而本教程使用一个包含所有功能的合集jar包来演示,用户可以使用curl或者浏览器下载jetty-all.jar包。
jetty-all.jar下载地址:http://central.maven.org/maven2/org/eclipse/jetty/aggregate/jetty-all/9.3.11.v20160721/jetty-all-9.3.11.v20160721-uber.jar
注意:
Maven中央仓库已经开始拒绝使用wget命令获得资源(因为一些工具的滥用),所以Maven中央仓库建议使用curl命令来获得jar包。
使用curl 命令如下(Windows用户可以将上面的地址复制到浏览器来下载):
> mkdir Demo
> cd Demo
> curl -o jetty-all-uber.jar http://central.maven.org/maven2/org/eclipse/jetty/aggregate/jetty-all/9.3.11.v20160721/jetty-all-9.3.11.v20160721-uber.jar
21.1.2 写一个HelloWorld例子
这个Jetty嵌入式教程章节包含很多通过Jetty API的例子,这个教程在main方法里运行一个Helloworld的handler来实现一个服务,可以自己写或者复制以下代码:
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; public class HelloWorld extends AbstractHandler { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // 声明response的编码和文件类型 response.setContentType("text/html; charset=utf-8"); // 声明返回状态码 response.setStatus(HttpServletResponse.SC_OK); // 请求的返回值 response.getWriter().println("<h1>Hello World</h1>"); // 通知Jettyrequest使用此处理器处理请求 baseRequest.setHandled(true); } public static void main(String[] args) throws Exception { //创建一个应用服务监听8080端口 Server server = new Server(8080); server.setHandler(new HelloWorld()); //启动应用服务并等待请求 server.start(); server.join(); } }
21.1.3 编译helloworld例子
使用如下命令编译生成class文件
> mkdir classes
> javac -d classes -cp jetty-all-uber.jar HelloWorld.java
21.1.4 运行服务
使用如下命令运行服务,启动服务器。(建议使用开发工具进行学习,如eclipse)
> java -cp classes:jetty-all-uber.jar org.eclipse.jetty.embedded.HelloWorld
运行成功后会输出如下内容:
2016-09-02 11:44:48.851:INFO::main: Logging initialized @214ms
2016-09-02 11:44:48.915:INFO:oejs.Server:main: jetty-9.3.z-SNAPSHOT
2016-09-02 11:44:49.049:INFO:oejs.AbstractConnector:main: Started ServerConnector@5436b246{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2016-09-02 11:44:49.050:INFO:oejs.Server:main: Started @417ms
此时可以访问http://localhost:8080 ,查看结果:
21.1.5 后续步骤
为了更好的学习Jetty,可以按如下步骤进行:
- 跟着例子学习嵌入式Jetty开发比直接看Jetty API要好
- 把Jetty javadoc完全看一遍
- 使用Maven来管理所有jar包和依赖
21.2 Jetty的嵌入式开发
Jetty有一个口号:不要把应用部署到Jetty上,要把Jetty部署到你的应用里。这句话的意思是把应用打成一个war包部署到Jetty上,不如将Jetty作为应用的一个组件,它可以实例化并像POJO一样。换种说法,在嵌入式模块中运行Jetty意味着把HTTP模块放到你的应用里,这种方法比把你的应用放到一个HTTP服务器里要好。
这个教程将一步一步的教你如何通过简单的Jetty服务运行多个web应用。大多数例子的源代码都是Jetty项目的一部分。
21.2.1 概述
本教程中嵌入一个Jetty的典型步骤如下:
- 创建一个server实例
- 新增/配置连接
- 新增/配置处理程序,或者Contexts,或者Servlets
- 启动Server
- 等待连接或者在当前线程上做一些其他的事
21.2.2 创建一个server实例
下面的代码实例化并运行了一个Jetty Server
import org.eclipse.jetty.server.Server; /** * The simplest possible Jetty server. */ public class SimplestServer { public static void main( String[] args ) throws Exception { Server server = new Server(8080); server.start(); server.dumpStdErr(); server.join(); } }
在8080端口运行了一个HTTP服务,因为没有处理程序,所以这不是一个有效的server,所有请求将会返回404错误信息。
21.2.3 使用处理器处理请求
为了针对请求产生一个相应,Jetty要求用户为服务创建一个处理请求的处理器,一个处理器可以做的工作有:
- 检测或修改一个请求
- 一个完整的HTTP响应
- 处理转发(详见:HandlerWrapper)
- 处理转发到多个其它处理器上(详见:HandlerCollection)
21.2.3.1 处理器的HelloWorld
接下来的代码HelloHandler.java,表示一个简单的处理程序
// // ======================================================================== // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // // You may elect to redistribute this code under either of these licenses. // ======================================================================== // package org.eclipse.jetty.embedded; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; public class HelloHandler extends AbstractHandler { final String greeting; final String body; public HelloHandler() { this("Hello World"); } public HelloHandler( String greeting ) { this(greeting, null); } public HelloHandler( String greeting, String body ) { this.greeting = greeting; this.body = body; } public void handle( String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException { response.setContentType("text/html; charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK); PrintWriter out = response.getWriter(); out.println("<h1>" + greeting + "</h1>"); if (body != null) { out.println(body); } baseRequest.setHandled(true); } }
传入到处理程序方法handle的参数有:
- target - 目标请求,可以是一个URI或者是一个转发到这的处理器的名字
- baseRequest - Jetty自己的没有被包装的请求,一个可变的Jetty请求对象
- request - 被filter或者servlet包装的请求,一个不可变的Jetty请求对象
- response - 响应,可能被filter或者servlet包装过
处理程序会设置状态码,content-type,并调用write向response输出内容。
21.2.3.2 运行HelloWorldHandler
为了让处理器处理HTTP请求,你必须将处理程序添加到server实例上,接下来的代码OneHandler.java展示了一个serve实例如何调用处理出现来处理请求:
// // ======================================================================== // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // // You may elect to redistribute this code under either of these licenses. // ======================================================================== // package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.Server; public class OneHandler { public static void main( String[] args ) throws Exception { Server server = new Server(8080); server.setHandler(new HelloHandler()); server.start(); server.join(); } }
一个或多个处理器将处理Jetty所有的请求。一些处理器会转发请求到其他处理器(例如: ContextHandlerCollection 会根据路径选择匹配的ContextHandler),另一些将根据逻辑判断来生成相应的响应(例如:ServletHandler 将把request转发到servlet),还有的处理器将处理和请求无关的操作(例如:RequestLogHandler 或者StatisticsHandler)。
后面的章节将介绍如何在切面调用一个处理器,你可以到org.eclipse.jetty.server.handler 包下看看当前可用的处理器。
21.2.3.3 处理器的集合及封装
复杂的请求可以由多个处理器来完成,你可以通过不同的方式把它们结合起来,Jetty有几个HandlerContainer接口的实现:
HandlerCollection:
一个包含多个处理器的集合,按照顺序依次处理。这在响应请求的同时进行统计和日志记录特别有用。
HandlerList:
一个包含多个处理器的集合,按照顺序处理,与HandlerCollection不同的是,当处理器出现异常或者响应被提交或者request.isHandled()方法返回true时,后续将不再被调用。一般用来匹配不同的主机,用来进行不同的处理。
HandlerWrapper:
一个处理器的基类用来进行切面编程。例如,一个标准的web应用会由context,session,安全和servlet处理器构成。
ContextHandlerCollection:
一个特殊的HandlerCollection,使用完整的URI前缀来选择匹配的ContextHandler对请求进行处理。
21.2.3.4 处理器的作用域
在Jetty中,很多标准的服务器会继承HandlerWrappers,用来进行链式处理,比如从请求从ContextHandler 到SessionHandler ,再到SecurityHandler 最后到ServletHandler。然而,因为servlet规范的性质,外部处理器不能在没有调用内部处理器的时候得知内部处理器的信息,例如:ContextHandler调用应用监听请求的context时,它必须已经知道ServletHandler将要转发请求到哪个servlet,以确保servletPath方法返回正确的值。
ScopedHandler是HandlerWrapper 一个抽象实现类,用来提供链式调用时作用域的支持。例如:一个ServletHandler内嵌在一个ContextHandler中,方法嵌套调用的顺序为:
Server.handle(...)
ContextHandler.doScope(...)
ServletHandler.doScope(...)
ContextHandler.doHandle(...)
ServletHandler.doHandle(...)
SomeServlet.service(...)
因此ContextHandler处理请求时,它内嵌的ServletHandler已经建立了。
21.2.3.5 资源处理器
下面这个FileServer例子,展示了你可以使用ResourceHandler 来处理当前工作路径下的静态资源。
import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.server.handler.gzip.GzipHandler; public class FileServer { public static void main(String[] args) throws Exception { //创建一个基础的Jetty服务监听8080端口 //若设置端口为0,则随机一个可用的端口,端口信息可以从日志中获取也可以写测试方法获取 Server server = new Server(8080); //创建一个ResourceHandler,它处理请求的方式是提供一个资源文件 //这是一个Jetty内置的处理器,所以它非常适合与其他处理器构成一个处理链 ResourceHandler resource_handler = new ResourceHandler(); //配置ResourceHandler,设置哪个文件应该被提供给请求方 //这个例子里,配置的是当前路径下的文件,但是实际上可以配置长任何jvm能访问到的地方 resource_handler.setDirectoriesListed(true); resource_handler.setWelcomeFiles(new String[] { "index.html" }); resource_handler.setResourceBase("."); // 将resource_handler添加到GzipHandler中,然后将GzipHandler提供给Server GzipHandler gzip = new GzipHandler(); server.setHandler(gzip); HandlerList handlers = new HandlerList(); handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() }); gzip.setHandler(handlers); server.start(); server.join(); } }
请注意,例子中的HandlerList 包含ResourceHandler 和DefaultHandler,DefaultHandler 将会为不能匹配到资源的生成一个格式良好的404回应。
21.2.4 嵌入式的连接
在前面的例子中,通过在Server实例通过传入一个端口号,让Server创建一个默认的连接来监听指定的端口。然而,通常编写嵌入式代码希望显式的配置一个或者多个连接器。
21.2.4.1 一个连接
下面的例子, OneConnector.java,实例化、配置、新增一个HTTP连接到server上
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; /** * 有一个连接的Server */ public class OneConnector { public static void main(String[] args) throws Exception { Server server = new Server(); // 创建一个HTTP的连接,配置监听主机,端口,以及超时时间 ServerConnector http = new ServerConnector(server); http.setHost("localhost"); http.setPort(8080); http.setIdleTimeout(30000); // 将此连接添加到Server server.addConnector(http); // 设置一个处理器 server.setHandler(new HelloHandler()); // 启动Server server.start(); server.join(); } }
在这个例子中,连接将处理http的请求,这个也是默认的ServerConnector连接类。
21.2.4.2 多个连接
当配置多个连接(例如:HTTP和HTTPS),它们可能是共同分享HTTP设置的参数。为了显式的配置ServerConnector 需要使用ConnectionFactory ,并提供一个常用的HTTP配置。
下面这个 ManyConnectors例子,给一个Server配置了两个ServerConnector ,http连接有一个HTTPConnectionFactory 实例,https连接有一个SslConnectionFactory 实例在HttpConnectionFactory里面。两个HttpConnectionFactory 都是基于同一个HttpConfiguration实例,然而https使用包装过的配置信息,因此SecureRequestCustomizer 可以被添加进去。
import java.io.File; import java.io.FileNotFoundException; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.util.ssl.SslContextFactory; /** * 一个有多个连接的Jetty例子 */ public class ManyConnectors { public static void main(String[] args) throws Exception { //这个例子会展示如何配置SSL,我们需要一个秘钥库,会在jetty.home下面找 String jettyDistKeystore = "../../jetty-distribution/target/distribution/demo-base/etc/keystore"; String keystorePath = System.getProperty("example.keystore", jettyDistKeystore); File keystoreFile = new File(keystorePath); if (!keystoreFile.exists()) { throw new FileNotFoundException(keystoreFile.getAbsolutePath()); } //创建一个不指定端口的Server,随后将直接配置连接和端口 Server server = new Server(); //HTTP配置 //HttpConfiguration是一个配置http和https属性的集合,默认的配置是http的 //带secured的ui配置https的, HttpConfiguration http_config = new HttpConfiguration(); http_config.setSecureScheme("https"); http_config.setSecurePort(8443); http_config.setOutputBufferSize(32768); //HTTP连接 //第一个创建的连接是http连接,传入刚才创建的配置信息,也可以重新设置新的配置,如端口,超时等 ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(http_config)); http.setPort(8080); http.setIdleTimeout(30000); //使用SslContextFactory来创建http //SSL需要一个证书,所以我们配置一个工厂来获得需要的东西 SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(keystoreFile.getAbsolutePath()); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); //HTTPS的配置类 HttpConfiguration https_config = new HttpConfiguration(http_config); SecureRequestCustomizer src = new SecureRequestCustomizer(); src.setStsMaxAge(2000); src.setStsIncludeSubDomains(true); https_config.addCustomizer(src); //HTTPS连接 //创建第二个连接, ServerConnector https = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), new HttpConnectionFactory(https_config)); https.setPort(8443); https.setIdleTimeout(500000); // 设置一个连接的集合 server.setConnectors(new Connector[] { http, https }); // 设置一个处理器 server.setHandler(new HelloHandler()); // 启动服务 server.start(); server.join(); } }
21.2.5 嵌入式的Servlets
Servlets是处理逻辑和HTTP请求的标准方式。Servlets 类似于Jetty的处理器,request对象不可变且不能被修改。在Jetty中servlet将有ServletHandler进行负责调用。它使用标准的路径匹配一个请求到servlet,设置请求的路径和请求内容,将请求传递到servlet,或者通过过滤器产生一个响应。
下面这个MinimalServlets例子,创建一个ServletHandler 实例,并配置一个简单的servlet
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; public class MinimalServlets { public static void main(String[] args) throws Exception { Server server = new Server(8080); //ServletHandler通过一个servlet创建了一个非常简单的context处理器 //这个处理器需要在Server上注册 ServletHandler handler = new ServletHandler(); server.setHandler(handler); //传入能匹配到这个servlet的路径 //提示:这是一个未经处理的servlet,没有通过web.xml或@WebServlet注解或其他方式配置 handler.addServletWithMapping(HelloServlet.class, "/*"); server.start(); server.join(); } @SuppressWarnings("serial") public static class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("<h1>Hello from HelloServlet</h1>"); } } }
21.2.6 嵌入式Context
ContextHandler是一种ScopedHandler,只用来响应配匹配指定URI前缀的请求,
- 一个Classloader 当在一个请求作用域里的时候处理当前线程的请求
- 一个ServletContext有小属性的集合
- 通过ServletContext获得的初始化参数的集合
- 通过ServletContext 获得的基础资源的集合
- 一个虚拟主机名称的集合
下面这个OneContext例子,包含一个HelloHandler处理器,用来处理指定路径下的请求
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; public class OneContext { public static void main(String[] args) throws Exception { Server server = new Server(8080); //在/hello路径上增加一个处理器 ContextHandler context = new ContextHandler(); context.setContextPath("/hello"); context.setHandler(new HelloHandler()); //可以通过http://localhost:8080/hello访问 server.setHandler(context); server.start(); server.join(); } }
当有很多有效的contexts 时,可以创建一个ContextHandlerCollection 集合存储这些处理器,下面的这个ManyContexts例子展示多个context的使用:
import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; public class ManyContexts { public static void main( String[] args ) throws Exception { Server server = new Server(8080); ContextHandler context = new ContextHandler("/"); context.setContextPath("/"); context.setHandler(new HelloHandler("Root Hello")); ContextHandler contextFR = new ContextHandler("/fr"); contextFR.setHandler(new HelloHandler("Bonjoir")); ContextHandler contextIT = new ContextHandler("/it"); contextIT.setHandler(new HelloHandler("Bongiorno")); ContextHandler contextV = new ContextHandler("/"); contextV.setVirtualHosts(new String[] { "127.0.0.2" }); contextV.setHandler(new HelloHandler("Virtual Hello")); ContextHandlerCollection contexts = new ContextHandlerCollection(); contexts.setHandlers(new Handler[] { context, contextFR, contextIT, contextV }); server.setHandler(contexts); server.start(); server.join(); } }
21.2.7 嵌入式ServletContexts
ServletContextHandler是一种特殊的ContextHandler,它可以支持标准的sessions 和Servlets。下面例子的OneServletContext 实例化了一个 DefaultServlet为/tmp/ 和DumpServlet 提供静态资源服务,DumpServlet 创建session并且应答请求信息
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; public class OneServletContext { public static void main(String[] args) throws Exception { Server server = new Server(8080); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); context.setResourceBase(System.getProperty("java.io.tmpdir")); server.setHandler(context); // 增加一个 dump servlet context.addServlet(DumpServlet.class, "/dump/*"); // 增加一个默认的servlet context.addServlet(DefaultServlet.class, "/"); server.start(); server.join(); } }
21.2.8 嵌入一个web应用
WebAppContext是ServletContextHandler 的扩展,使用标准的web应用组件和web.xml,通过web.xml和注解配置servlet,filter和其它特性。下面这个OneWebApp例子部署了一个简单的web应用。Web应用程序可以使用容器提供的资源,在这种情况下需要一个LoginService并配置:
import java.io.File; import java.lang.management.ManagementFactory; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker; import org.eclipse.jetty.webapp.WebAppContext; public class OneWebApp { public static void main(String[] args) throws Exception { Server server = new Server(8080); // 设置 JMX MBeanContainer mbContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer()); server.addBean(mbContainer); //下面这个web应用是一个完整的web应用,在这个例子里设置/为根路径,web应用所有的配置都是有效的, WebAppContext webapp = new WebAppContext(); webapp.setContextPath("/"); File warFile = new File("../../jetty-distribution/target/distribution/test/webapps/test/"); webapp.setWar(warFile.getAbsolutePath()); webapp.addAliasCheck(new AllowSymLinkAliasChecker()); //将web应用设置到server里 server.setHandler(webapp); server.start(); server.join(); } }
21.2.9 使用Jetty XML配置
通常配置Jetty实例是通过配置jetty.xml和其它关联的配置文件,然而Jetty 配置信息都可以用简单的代码进行配置,下面的例子将从配置文件中获得相关信息:
- jetty.xml
- jetty-jmx.xml
- jetty-http.xml
- jetty-https.xml
- jetty-deploy.xml
- jetty-stats.xml
- jetty-requestlog.xml
- jetty-lowresources.xml
- test-realm.xml
import java.io.File; import java.io.FileNotFoundException; import java.lang.management.ManagementFactory; import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.deploy.PropertiesConfigurationManager; import org.eclipse.jetty.deploy.bindings.DebugListenerBinding; import org.eclipse.jetty.deploy.providers.WebAppProvider; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.rewrite.handler.CompactPathRule; import org.eclipse.jetty.rewrite.handler.RewriteHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.server.ConnectorStatistics; import org.eclipse.jetty.server.DebugListener; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.LowResourceMonitor; import org.eclipse.jetty.server.NCSARequestLog; import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.RequestLogHandler; import org.eclipse.jetty.server.handler.StatisticsHandler; import org.eclipse.jetty.util.ssl.SslContextFactory; import<以上是关于Jetty使用教程(四:21-22)—Jetty开发指南的主要内容,如果未能解决你的问题,请参考以下文章