Jetty 开发指南:Jetty 内嵌开发
Jetty的口号是“不要在Jetty中部署你的应用程序,在你的应用程序中部署Jetty!” 这意味着,作为将应用程序捆绑为要部署在Jetty中的标准WAR的替代方案,Jetty旨在成为一个软件组件,可以像任何POJO一样在Java程序中实例化和使用。 换句话说,在嵌入模式下运行Jetty意味着将HTTP模块放入应用程序,而不是将应用程序放入HTTP服务器。
本教程将逐步介绍从最简单的Jetty服务器实例化到使用基于标准的部署描述符运行多个Web应用程序。 大多数这些示例的来源是标准Jetty项目的一部分。
1. 概述
要嵌入Jetty服务器,以下典型的步骤,本教程中的示例说明了这些步骤:
- 创建一个Server实例。
- 添加/配置连接器(Connectors)。
- 添加/配置处理器(Handlers)、上下文(Contexts)、Servlets。
- 启动服务器。
- 等待连接或用线程做其他事情。
2. 创建Server
SimplestServer.java中的以下代码为实例化并运行最简单的Jetty服务器:
package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Server; /**
* 最简单的 Jetty 服务器
*/
public class SimplestServer
{
public static void main( String[] args ) throws Exception
{
Server server = new Server(8080);
server.start();
server.dumpStdErr();
server.join();
}
}
上面程序运行一个http server在8090端口。但是这个server没有任何用处,因为它没有任何handler,因此不管任何的请求都会返回404.
3. 使用 Handlers
要生成对请求的响应,Jetty要求您在服务器上设置Handler。 处理程序可以:
- 检查/修改HTTP请求。
- 生成完整的HTTP响应。
- 调用另一个Handler(参见HandlerWrapper)。
- 选择一个或多个要调用的处理程序(请参阅HandlerCollection)。
3.1 HelloWorld Handler
以下HelloHandler.java的代码显示了一个简单的hello world处理程序:
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;
} @Override
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可变请求对象,没有被包装的request对象。
- request - 不可变请求对象,可能已被filter或servlet包装。
- response- 响应,可能已被过滤器或servlet包装。
handler设置响应状态,内容类型,并在使用writer生成响应主体之前将请求标记为已处理。
3.2 运行 HelloWorldHandler
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中一般有一个或者多个handler来处理所有的请求。有些handler会选择其他指定的handler去做处理(例如ContextHandlerCollection会通过context path来选择ContextHandler); 还有一些handler通过应用程序逻辑生成响应(例如,ServletHandler将请求传递给应用Servlet),其他的handler则执行与生成响应无关的任务(例如,RequestLogHandler或StatisticsHandler)。
后面的章节描述了你可以像切面一样组合多个handler。 您可以在org.eclipse.jetty.server.handler包中看到Jetty中的一些可用的Handlers。
4. Handler Collections and Wrappers
复杂请求处理通常由多个Handler构建,您可以通过各种方式进行组合。 Jetty有几个HandlerContainer接口的实现:
HandlerCollection
保存其他 handler 集合并按顺序调用每个handler。这对于将统计信息和日志记录 handler 与生成响应的 handler 相结合非常有用。
HandlerList
一个Handler 集合,它依次调用每个 handler,直到抛出异常,响应被提交或request.isHandled() 返回true。您可以使用它来组合handler有选择的处理请看清,例如调用多个Context上下文直到与虚拟主机匹配。
HandlerWrapper
一个Handler基类,可用于以面向切面编程的方式将处理程序连接在一起。例如,标准Web应用程序由上下文,会话,安全性和servlet处理程序链实现。
ContextHandlerCollection
一个专门的HandlerCollection,它使用请求URI的最长前缀(contextPath)来选择一个包含的ContextHandler来处理请求。
5. Scoped Handlers
Jetty中的大部分标准Servlet容器都是使用HandlerWrappers实现的,它们将handler 以链式组合在一起:ContextHandler --> SessionHandler --> SecurityHandler --> ServletHandler。 但是,由于servlet规范,这种 handler 链不能是纯粹的嵌套,因为外部 handler 有时需要内部 handler 的处理信息。 例如,当ContextHandler调用某些应用程序listener以通知它们进入上下文的请求时,它必须已经知道ServletHandler将向哪个servlet分派请求,以便servletPath方法返回正确的值。
HandlerWrapper是ScopedHandler抽象类,它支链式链scopes。 例如,如果ServletHandler嵌套在ContextHandler中,则方法执行的顺序和嵌套是:
Server.handle(...)
ContextHandler.doScope(...)
ServletHandler.doScope(...)
ContextHandler.doHandle(...)
ServletHandler.doHandle(...)
SomeServlet.service(...)
6. Resource Handler
FileServer示例显示如何使用ResourceHandler从当前工作目录提供静态内容:
package org.eclipse.jetty.embedded; 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; /**
* 简单的 Jetty 文件服务器
* 这是一个Jetty 文件服务器配置的简单示例
*/
public class FileServer
{
public static void main(String[] args) throws Exception
{
// 创建一个将在8080端口侦听的基本的服务器对象,注意,如果将端口设置为0
// server 将会被分配一个随机可用的端口,你可以在日志中看到分配的端口,
// 或者则测试用例中通过编程方式获取。
Server server = new Server(8080); // 创建 ResourceHandler. 它是实际处理给定文件请求的对象。
// 它是一个 Jetty Handler 对象,因此你将在其他示例中看到它能够和其他 handlers 进行链式处理。
ResourceHandler resource_handler = new ResourceHandler(); // 配置 ResourceHandler。设置提供文件服务的资源根目录。
// 在这个例子中是当前目录,也可以配置成jvm有权限访问的任何目录。
resource_handler.setDirectoriesListed(true);
resource_handler.setWelcomeFiles(new String[]{ "index.html" });
resource_handler.setResourceBase("."); // 将 ResourceHandler 添加至 server。
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
server.setHandler(handlers); // 启动服务,通过使用 server.join() server 线程将 join 当前线程
// 在"http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" 了解更多细节.
server.start();
server.join();
}
}
注意我们使用了ResourceHandler和DefaultHandler,所以DefaultHandler对于没有匹配的请求会友好的返回404。
7. 内嵌 Connectors
在前面的示例中,Server实例通过构造方法传递了一个端口号,它在内部创建一个Connector的默认实例,用于侦听该端口上的请求。 但是,通常在嵌入Jetty时,需要为Server实例显式实例化和配置一个或多个连接器。
7.1 单个 Connector
以下OneConnector.java,实例化、配置并向服务器添加单个HTTP connector 实例:
package org.eclipse.jetty.embedded; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector; /**
* 只有一个 Connector 的 Jetty server
*/
public class OneConnector
{
public static void main( String[] args ) throws Exception
{
// Server
Server server = new Server(); // HTTP connector
ServerConnector http = new ServerConnector(server);
http.setHost("localhost");
http.setPort(8080);
http.setIdleTimeout(30000); // 设置 connector
server.addConnector(http); // 设置 handler
server.setHandler(new HelloHandler()); // 启动 Server
server.start();
server.join();
}
}
在这个例子里connector处理http协议,因为这是ServerConnetor默认的配置。
7.2 多 Connectors
配置多个连接器(例如,HTTP和HTTPS)时,可能需要共享HTTP的公共参数的配置。 要实现此目的,您需要使用ConnectionFactory实例显式配置ServerConnector类,并为它们提供常见的HTTP配置。
ManyConnectors示例使用两个ServerConnector实例配置服务器:http连接器具有HTTPConnectionFactory实例; https连接器有一个链接到HttpConnectionFactory的SslConnectionFactory。 两个HttpConnectionFactory都是基于相同的HttpConfiguration实例配置的,但HTTPS工厂使用包装配置,以便可以添加SecureRequestCustomizer。
8. 内嵌 Servlets
Servlet是提供处理HTTP请求的应用程序逻辑的标准方法。 Servlet类似于Jetty Handler,但请求对象不可变,因此无法修改。 Servlet由ServletHandler在Jetty中处理。 它使用标准路径映射来将Servlet与请求进行匹配; 设置请求servletPath和pathInfo; 将请求传递给servlet,可能通过 Filters 生成响应。
MinimalServlets示例创建一个ServletHandler实例并配置一个HelloServlet:
package org.eclipse.jetty.embedded; 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 是创建 context handler 的简单方法,
// 由 Servlet 实力支持。
// 这个 handler 对象需要被注册给 Server 对象。
ServletHandler handler = new ServletHandler();
server.setHandler(handler); // 传递的 Servlet 类允许 jetty 实例化并且挂载到给定的上下文路径上。// 重要:
// 这是一个原始的 Servlet, 不是一个通过 web.xml 或者 @WebServlet注解或者其他类似方式配置的servlet。
handler.addServletWithMapping(HelloServlet.class, "/*"); // 启动服务
server.start(); // 使用 server.join() 加入当前线程// 在 http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join() 查看更多。
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>");
}
}
}
9. 内嵌 Contexts
ContextHandler是一个ScopedHandler,它只响应具有与配置的上下文路径匹配的URI前缀的请求。 与上下文路径匹配的请求会相应地更新其路径方法,并且上下文范围可用,可选择:
- 在请求处理期间为Thread context 设置
Classloader
。 - 一组可通过ServletContext API获得的属性。
- 一组可通过ServletContext API获得的init参数。
- 基本资源,通过ServletContext API用作静态资源请求的文档根。
- 一组虚拟主机名。
以下OneContext示例显示了正在建立的包装HelloHandler的上下文:
package org.eclipse.jetty.embedded; 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 ); // 增加一个唯一的 handler 给 context "/hello"
ContextHandler context = new ContextHandler();
context.setContextPath( "/hello" );
context.setHandler( new HelloHandler() ); // 在 http://localhost:8080/hello 访问服务 server.setHandler( context ); // 启动服务
server.start();
server.join();
}
}
当存在许多上下文时,您可以嵌入ContextHandlerCollection以有效地检查请求URI,然后为请求选择匹配的ContextHandler。 ManyContexts示例展示了配置多个Context:
package org.eclipse.jetty.embedded; 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();
}
}
10. 内嵌 ServletContexts
ServletContextHandler是ContextHandler的一个专门实例,用来支持标准Session和Servlet。 以下OneServletContext示例将DefaultServlet实例化,为/ tmp /目录下的静态资源提供服务,以及一个DumpServlet,用于创建会话并转储有关请求的基本详细信息:
package org.eclipse.jetty.embedded; 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/*");
// 添加 default servlet
context.addServlet(DefaultServlet.class, "/"); server.start();
server.join();
}
}
11. 内嵌 Applications
WebAppContext是ServletContextHandler的扩展,它使用 standard layout和web.xml从web.xml和/或注释配置servlet,filter和其他功能。 以下OneWebApp示例配置Jetty测试webapp。 Web应用程序可以使用容器提供的资源,在这种情况下,还需要LoginService并进行配置:
package org.eclipse.jetty.embedded; 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); // WebAppContext 是一个控制 web 应用生存环境的实体,
// 在这个例子中 context path 设置为 “/”,因此它能够处理 root 上下文请求,然后我们能看到它设置war包路径。// 还有许多其他配置, 从支持webapp注解扫描(通过PlusConfiguration)到选择webapp的解压位置。
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
File warFile = new File(
"../../tests/test-jmx/jmx-webapp/target/jmx-webapp");
webapp.setWar(warFile.getAbsolutePath()); // WebAppContext 是一个 ContextHandler,因此它需要设置给 server,从而能够将请求发送到合适的位置sts.
server.setHandler(webapp); // 启动服务
server.start(); server.dumpStdErr();// 在 http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join() 查看更多
server.join();
}
}
12. Like Jetty XML
配置Jetty服务器实例的典型方法是通过jetty.xml和相关配置文件。 但是,Jetty XML配置格式只是对代码中可以执行的操作的简单呈现; 编写完全符合jetty.xml配置功能的嵌入式代码非常简单。 以下LikeJettyXml示例在代码中呈现从配置文件中获取的行为:
- 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
package org.eclipse.jetty.embedded; 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.RewriteHandler;
import org.eclipse.jetty.security.HashLoginService;
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.ServerConnectionStatistics;
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 org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.webapp.Configuration; /**
* Starts the Jetty Distribution's demo-base directory using entirely
* embedded jetty techniques.
*/
public class LikeJettyXml
{
public static void main( String[] args ) throws Exception
{
// Path to as-built jetty-distribution directory
String jettyHomeBuild = "../../jetty-distribution/target/distribution"; // Find jetty home and base directories
String homePath = System.getProperty("jetty.home", jettyHomeBuild);
File start_jar = new File(homePath,"start.jar");
if (!start_jar.exists())
{
homePath = jettyHomeBuild = "jetty-distribution/target/distribution";
start_jar = new File(homePath,"start.jar");
if (!start_jar.exists())
throw new FileNotFoundException(start_jar.toString());
} File homeDir = new File(homePath); String basePath = System.getProperty("jetty.base", homeDir + "/demo-base");
File baseDir = new File(basePath);
if(!baseDir.exists())
{
throw new FileNotFoundException(baseDir.getAbsolutePath());
} // Configure jetty.home and jetty.base system properties
String jetty_home = homeDir.getAbsolutePath();
String jetty_base = baseDir.getAbsolutePath();
System.setProperty("jetty.home", jetty_home);
System.setProperty("jetty.base", jetty_base); // === jetty.xml ===
// Setup Threadpool
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(500); // Server
Server server = new Server(threadPool); // Scheduler
server.addBean(new ScheduledExecutorScheduler()); // HTTP Configuration
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(8443);
http_config.setOutputBufferSize(32768);
http_config.setRequestHeaderSize(8192);
http_config.setResponseHeaderSize(8192);
http_config.setSendServerVersion(true);
http_config.setSendDateHeader(false);
// httpConfig.addCustomizer(new ForwardedRequestCustomizer()); // Handler Structure
HandlerCollection handlers = new HandlerCollection();
ContextHandlerCollection contexts = new ContextHandlerCollection();
handlers.setHandlers(new Handler[] { contexts, new DefaultHandler() });
server.setHandler(handlers); // Extra options
server.setDumpAfterStart(false);
server.setDumpBeforeStop(false);
server.setStopAtShutdown(true); // === jetty-jmx.xml ===
MBeanContainer mbContainer = new MBeanContainer(
ManagementFactory.getPlatformMBeanServer());
server.addBean(mbContainer); // === jetty-http.xml ===
ServerConnector http = new ServerConnector(server,
new HttpConnectionFactory(http_config));
http.setPort(8080);
http.setIdleTimeout(30000);
server.addConnector(http); // === jetty-https.xml ===
// SSL Context Factory
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(jetty_home + "/../../../jetty-server/src/test/config/etc/keystore");
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
sslContextFactory.setTrustStorePath(jetty_home + "/../../../jetty-server/src/test/config/etc/keystore");
sslContextFactory.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA", "SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"); // SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer()); // SSL Connector
ServerConnector sslConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https_config));
sslConnector.setPort(8443);
server.addConnector(sslConnector); // === jetty-deploy.xml ===
DeploymentManager deployer = new DeploymentManager();
DebugListener debug = new DebugListener(System.err,true,true,true);
server.addBean(debug);
deployer.addLifeCycleBinding(new DebugListenerBinding(debug));
deployer.setContexts(contexts);
deployer.setContextAttribute(
"org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$"); WebAppProvider webapp_provider = new WebAppProvider();
webapp_provider.setMonitoredDirName(jetty_base + "/webapps");
webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml");
webapp_provider.setScanInterval(1);
webapp_provider.setExtractWars(true);
webapp_provider.setConfigurationManager(new PropertiesConfigurationManager()); deployer.addAppProvider(webapp_provider);
server.addBean(deployer); // === setup jetty plus ==
Configuration.ClassList classlist = Configuration.ClassList
.setServerDefault( server );
classlist.addAfter(
"org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.plus.webapp.PlusConfiguration"); classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration"); // === jetty-stats.xml ===
StatisticsHandler stats = new StatisticsHandler();
stats.setHandler(server.getHandler());
server.setHandler(stats);
ServerConnectionStatistics.addToAllConnectors(server); // === Rewrite Handler
RewriteHandler rewrite = new RewriteHandler();
rewrite.setHandler(server.getHandler());
server.setHandler(rewrite); // === jetty-requestlog.xml ===
NCSARequestLog requestLog = new NCSARequestLog();
requestLog.setFilename(jetty_home + "/logs/yyyy_mm_dd.request.log");
requestLog.setFilenameDateFormat("yyyy_MM_dd");
requestLog.setRetainDays(90);
requestLog.setAppend(true);
requestLog.setExtended(true);
requestLog.setLogCookies(false);
requestLog.setLogTimeZone("GMT");
RequestLogHandler requestLogHandler = new RequestLogHandler();
requestLogHandler.setRequestLog(requestLog);
handlers.addHandler(requestLogHandler); // === jetty-lowresources.xml ===
LowResourceMonitor lowResourcesMonitor=new LowResourceMonitor(server);
lowResourcesMonitor.setPeriod(1000);
lowResourcesMonitor.setLowResourcesIdleTimeout(200);
lowResourcesMonitor.setMonitorThreads(true);
lowResourcesMonitor.setMaxConnections(0);
lowResourcesMonitor.setMaxMemory(0);
lowResourcesMonitor.setMaxLowResourcesTime(5000);
server.addBean(lowResourcesMonitor); // === test-realm.xml ===
HashLoginService login = new HashLoginService();
login.setName("Test Realm");
login.setConfig(jetty_base + "/etc/realm.properties");
login.setHotReload(false);
server.addBean(login); // Start the server
server.start();
server.join();
}
}
上一节:Jetty 开发指南:(1) 嵌入式开发之HelloWorld
下一节:
参考资料:http://www.eclipse.org/jetty/documentation/9.4.x/embedding-jetty.html
PlusConfiguration
Jetty 开发指南:Jetty 内嵌开发的更多相关文章
- 3.MVC框架开发(Razor内嵌函数)
1.建立没有返回值的Razor内嵌函数(但是能直接输出内容) 必须以@符号开头,没有返回值但能直接输出内容,比如: @helper showTitle(string strTitle){ ){ @(s ...
- 【C/C++开发】STL内嵌数据类型: value_type
使用stl库的时候一直对value_type这个东西理解的不是很好,可以说就是不理解.今天看了<STL源码剖析>才恍然大悟.这里稍作记录. 每个STL中的类都有value_type这种东西 ...
- spring-boot开发:使用内嵌容器进行快速开发及测试
一.简述一下spring-boot微框架 1.spring-boot微框架是什么? 大家都知道,在使用spring框架进行应用开发时需要很多*.xml的初始化配置文件,而springBoot就是用来简 ...
- 【浏览器-Safari-网页开发指南】官方Sarari开发指南译文
Safari是一个功能比较完整的浏览器.它支持所有按照W3C标准HTML,CSS,Javascript开发的网页. 当然,让网站正常访问只是我们的初级目标.开发者应该致力于给用户提供更好的用户体验.比 ...
- Jetty 开发指南: 嵌入式开发之HelloWorld
Jetty 嵌入式之 HelloWorld 本节提供一个教程,演示如何快速开发针对Jetty API的嵌入式代码. 1. 下载 Jar 包 Jetty被分解为许多jar和依赖项,通过选择最小的jar集 ...
- Jetty使用教程(四:21-22)—Jetty开发指南
二十一.嵌入式开发 21.1 Jetty嵌入式开发HelloWorld 本章节将提供一些教程,通过Jetty API快速开发嵌入式代码 21.1.1 下载Jetty的jar包 Jetty目前已经把所有 ...
- Jetty使用教程(四:24-27)—Jetty开发指南
二十四.处理器(Handler ) 24.1 编写一个常用的Handler Jetty的Handler组件用来处理接收到的请求. 很多使用者不需要编写Jetty的Handler ,而是通过使用Serv ...
- Jetty使用教程(四:23)—Jetty开发指南
二十三.Maven和Jetty 这一章节将说明如何通过Maven管理Jetty和使用Jetty的Maven插件. 23.1 使用Maven Apache Maven是一个款软件项目管理工具.基于项目对 ...
- Jetty使用教程(四:28-30)—Jetty开发指南
二十八.延续机制支持 28.1 延续简介 延续是一种机制用来实现类似于Servlet 3.0异步功能的异步Servlet,但提供了一个简单易操作的接口. 28.1.1 为什么使用异步Servlets ...
随机推荐
- go 使用 c接口
在使用go语言时, 有时为了方便可以直接调用c语言的接口与库, 不需要重复编写. 那就来说说在go语言里面如何调用c的接口 首先编写好c语言的源文件与头文件,这里举一个简单的例子,实现一个字符串大小写 ...
- 解决localdb中文智能的问题
declare @database nvarchar(100) declare tmpCur cursor for select DB_NAME() open tmpCur fetch next fr ...
- [Swift]LeetCode1025. 除数博弈 | Divisor Game
Alice and Bob take turns playing a game, with Alice starting first. Initially, there is a number N o ...
- Java中 Linux下安装Redis
1.连接上虚拟机之后,选择/usr/local目录,将redis-4.0.6.tar.gz放入/usr/local目录. 1.1:使用Xftp将redis-4.0.6.tar.gz放入/usr/loc ...
- .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
本篇我将带着大家一起来对Dapper进行下封装并实现基本的增删改查.分页操作的同步异步方法的实现(已实现MSSQL,MySql,PgSQL).同时我们再实现一下仓储层的代码生成器,这样的话,我们只需要 ...
- ReentrantLock 实现原理
使用 synchronize 来做同步处理时,锁的获取和释放都是隐式的,实现的原理是通过编译后加上不同的机器指令来实现. 而 ReentrantLock 就是一个普通的类,它是基于 AQS(Abstr ...
- SpringCloud(6)---熔断降级理解、Hystrix实战
SpringCloud(6)---熔断降级理解.Hystrix实战 一.概念 1.为什么需要熔断降级 (1)需求背景 它是系统负载过高,突发流量或者网络等各种异常情况介绍,常用的解决方案. 在一个分布 ...
- Kafka分区与消费者的关系
1. 前言 我们知道,生产者发送消息到主题,消费者订阅主题(以消费者组的名义订阅),而主题下是分区,消息是存储在分区中的,所以事实上生产者发送消息到分区,消费者则从分区读取消息,那么,这里问题来了, ...
- 在使用 Git pull 时候报错 error: inflate
在使用 Git pull 时候报错 error: inflate 具体的错误是 这样的 error: inflate: data stream error (unknown compression m ...
- Solr04 - 在Jetty和Tomcat上部署Solr单机服务
目录 1 准备安装环境 2 通过内部Jetty服务器启动 3 通过配置Tomcat服务器启动 3.1 删除不需要的应用 3.2 修改服务端口 3.3 部署solr.war 3.4 扩展: 虚拟目录发布 ...