首页 > 代码库 > Jetty开发指导:嵌入
Jetty开发指导:嵌入
Jetty嵌入的HelloWorld
这节提供一个指导展示你怎么使用Jetty API快速开发嵌入的代码。
下载Jars
Jetty被分解到多个jars和依赖,方便你选择自己需要的最小jar集合。通常使用Maven是最好的,然而这里使用了一个聚集的jar,包含了所有的Jetty类。你能手动的下载聚集的jetty-all jar和servlet api jar,通过使用wget或者类似的命令(例如:curl)或者浏览器。用wget如下:
mkdir Demo cd Demo wget -O jetty-all.jar -U none http://central.maven.org/maven2/org/eclipse/jetty/aggregate/jetty-all/9.0.0-RC1/jetty-all-9.0.0-RC1.jar wget -O servlet-api.jar -U none http://central.maven.org/maven2/org/eclipse/jetty/orbit/javax.servlet/3.0.0.v201112011016/javax.servlet-3.0.0.v201112011016.jar
写一个HelloWorld例子
这里用一个简单的带有main方法的HelloWorld Handler运行server:
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.setContentType("text/html;charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK); baseRequest.setHandled(true); response.getWriter().println("<h1>Hello World</h1>"); } public static void main(String[] args) throws Exception { Server server = new Server(8080); server.setHandler(new HelloWorld()); server.start(); server.join(); } }
编译HelloWorld例子
下面是使用命令编译HelloWorld类:
javac -cp servlet-api.jar:jetty-all.jar HelloWorld.java
运行Handler和Server
下面的命令运行HelloWorld例子:
java -cp .:servlet-api.jar:jetty-all.jar HelloWorld
你现在能在浏览器中输入http://localhost:8080看hello world页。
下一步
为了学习更多关于Jetty,采取这些接下来的步骤:
1)看下一节的例子更好的理解Jetty API;
2)学习完整的Jetty Javadoc(http://download.eclipse.org/jetty/stable-9/apidocs/);
3)考虑使用Maven管理你的Jar和依赖。
嵌入的Jetty
Jetty有一个标语:“不要在Jetty中部署你的应用,在你的应用中部署Jetty!”这个意思是与其打包你的应用作为一个标准WAR被部署在Jetty中,Jetty更倾向于被作为一个软件组件像任何POJO一样被实例化并且用在Java程序中。换句话说,在嵌入模式中运行Jetty意味着放一个HTTP模块到你的应用中,而不是放你的应用到一个HTTP server中。
这里将带你一步一步从最简单的Jetty server实例化到使用基于标准的部署描述符运行多个web应用。这些例子的大部分都来自标准Jetty项目的一部分。
概览
为了嵌入一个Jetty server,通常需要下面的步骤:
1)创建一个Server实例;
2)添加/配置连接器;
3)添加/配置Handlers和/或Contexts和/或Servlets;
4)启动Server;
5)在server上等待或者使用你的线程做其它事。
创建Server
下面的代码包含实例化SimplestServer.java,运行该Jetty Server:
// // ======================================================================== // Copyright (c) 1995-2014 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.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(); } }
这里运行一个HTTP server在端口8080.它没有实际用处,因为它没有handlers,因此所有的请求都会返回一个404错误。
用Handlers
为了对一个请求产生一个响应,Jetty要求你在server上设置一个handler。一个handler可以:
1)测试/修改HTTP请求;
2)产生完整的HTTP响应;
3)调用另一个Handler(看HandlerWrapper);
4)选择一个或多个Handlers调用(看HandlerCollection)。
HelloWorld Handler
下面的HelloHandler.java展示了一个简单的hello world handler:
// // ======================================================================== // Copyright (c) 1995-2014 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 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() { _greeting="Hello World"; _body=null; } public HelloHandler(String greeting) { _greeting=greeting; _body=null; } public HelloHandler(String greeting,String body) { _greeting=greeting; _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); baseRequest.setHandled(true); response.getWriter().println("<h1>"+_greeting+"</h1>"); if (_body!=null) response.getWriter().println(_body); } }
传递给handle方法的参数是:
1)target:请求的目标,一个URI或者一个来自指定的分发器的名称;
2)baseRequest:Jetty易变的请求对象,总是被拆开;
3)request:不变的请求对象,可以被一个filter或者servlet包装;
4)response:响应,可以被一个filter或者servlet包装。
handler设置响应状态、content-type、并在使用writer产生响应的body前将请求设置为handled(表示处理完成,不再传递到下一个handler处理)。
运行HelloWorldHandler
为了允许一个Handler处理HTTP请求,你必须添加它到一个Server实例。下面的OneHandler.java展示一个Jetty Server怎么使用那个HelloWorld Handler:
// // ======================================================================== // Copyright (c) 1995-2014 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.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中使用一个或者多个Handlers做所有的请求处理。一些handlers负责选择其它特定的handlers(例如,一个ContextHandlerCollection用上下文路径选择一个ContextHandler);其它一些使用应用逻辑产生一个响应(例如,ServletHandler传递请求到一个应用Servlet),或者做一些和产生响应无关的任务(例如,RequestLogHandler或者StatisticsHandler)。
后面将描述你怎么组合多个handlers。你能在org.eclipse.jetty.server.handler包中看到Jetty中可用的一些handler。
Handler集合和包装器
复杂的请求处理通常涉及多个Handler,你能用多种方式组合它们。Jetty有几个HandlerContainer接口的实现:
1)HandlerCollection
包含其它多个handler的集合,按顺序调用每一个handler。
2)HandlerList
一个handler集合,依次调用每一个handler,直到或者一个异常产生,或者响应被提交,或者request.isHandled()返回true。
3)HandlerWrapper
一个Handler基类,你能以面向方面编程的风格使用链接在一起的Handler。例如,一个标准web应用通过一个context、session、security和servlet handlers的链实现。
4)ContextHandlerCollection
一个特殊的HandlerCollection,使用请求URI(contextPath)的最长前缀选择一个包含的ContextHandler处理这个请求。
限定Handler的作用域
Jetty中的大部分标准Servlet容器都是继承自HandlerWrapper,将Handler链接在一起:ContextHandler到SessionHandler到SecurityHandler到ServletHandler。然而,因为servlet规范的限制,由于连接有时需要内部handlers处理的信息,因此它不能是纯粹的handlers嵌套作为外部handlers。例如,当一个ContextHandler调用一些应用监听器,通知他们一个请求进入了上下文,它必须知道ServletHandler将分发这个请求到哪一个servlet,以至于servletPath方法能够返回正确的值。
HandlerWrapper恰好能满足ScopedHandler抽象类,支持一个作用域的处理链。例如如果一个ServletHandler被嵌套在一个ContextHandler内,方法执行的顺序将是:
Server.handle(...) ContextHandler.doScope(...) ServletHandler.doScope(...) ContextHandler.doHandle(...) ServletHandler.doHandle(...) SomeServlet.service(...)
因此当ContextHandler处理请求时,它在ServletHandler建立的作用域内做这个操作。
资源Handler
下面的FileServer的例子展示你怎么用一个ResourceHandler在当前工作目录下提供静态内容服务:
// // ======================================================================== // Copyright (c) 1995-2014 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.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; /* ------------------------------------------------------------ */ /** Simple Jetty FileServer. * This is a simple example of Jetty configured as a FileServer. */ public class FileServer { public static void main(String[] args) throws Exception { // Create a basic Jetty server object that will listen on port 8080. Note that if you set this to port 0 // then a randomly available port will be assigned that you can either look in the logs for the port, // or programmatically obtain it for use in test cases. Server server = new Server(8080); // Create the ResourceHandler. It is the object that will actually handle the request for a given file. It is // a Jetty Handler object so it is suitable for chaining with other handlers as you will see in other examples. ResourceHandler resource_handler = new ResourceHandler(); // Configure the ResourceHandler. Setting the resource base indicates where the files should be served out of. // In this example it is the current directory but it can be configured to anything that the jvm has access to. resource_handler.setDirectoriesListed(true); resource_handler.setWelcomeFiles(new String[]{ "index.html" }); resource_handler.setResourceBase("."); // Add the ResourceHandler to the server. HandlerList handlers = new HandlerList(); handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() }); server.setHandler(handlers); // Start things up! By using the server.join() the server thread will join with the current thread. // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details. server.start(); server.join(); } }
注意一个HandLIst中添加了ResourceHandler和一个DefaultHandler,以至于DefaultHandler为不匹配静态资源的其它请求产生一个404响应。
嵌入连接器
在前面的例子中,Server实例被传递一个端口号,它的内部会创建一个默认的连接器实例,监听该端口的请求。然而,我们经常希望能够直接为Server实例初始化和配置一个或者多个连接器。
单连接器
下面的例子,OneConnector.java,初始化,配置,然后添加一个HTTP连接器实例到Server:
// // ======================================================================== // Copyright (c) 1995-2014 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.Server; import org.eclipse.jetty.server.ServerConnector; /* ------------------------------------------------------------ */ /** * A Jetty server with one connectors. */ public class OneConnector { public static void main(String[] args) throws Exception { // The Server Server server = new Server(); // HTTP connector ServerConnector http = new ServerConnector(server); http.setHost("localhost"); http.setPort(8080); http.setIdleTimeout(30000); // Set the connector server.addConnector(http); // Set a handler server.setHandler(new HelloHandler()); // Start the server server.start(); server.join(); } }
在这里例子中,连接器处理HTTP协议,这在ServerConnector中是默认的。
多连接器
当配置多个连接器时(例如,HTTP和HTTPS),可以为HTTP共享公共参数的配置。为了做这你需要明确的使用ConnectionFactory实例配置ServerConnector类,并且提供公共HTTP配置。
ManyConnectors的例子,使用2个ServerConnector实例配置了一个Server:http连接器有HTTPConnectionFactory实例;https连接器有一个SslConnectionFactory链接到一个HttpConnectionFactory。这些HttpConnectionFactories都基于同样的HttpConfiguration实例配置,然而HTTPS工厂用了一个封装的配置以至于一个SecureRequestCustomizer能被添加。
SPDY连接器
SPDYConnector的例子类似于HTTPS连接器,除了SslConnectionFactory被链接到NPNConnectionFactory,用于协商下一个协议是否被认为是SPDY/2、SPDY/3或者HTTPS。
嵌入Servlets
Servlet是用于提供处理HTTP请求的应用逻辑的标准方法。Servlet类似于Jetty Handler,除了请求对象是不可变的。Servlet在Jetty中被一个ServletHandler处理。它使用标准路径匹配方法来匹配一个Servlet到一个请求;设置请求servletPath和pathInfo;传递请求到Servlet,可能通过Filter产生一个响应。
下面MinimalServlets例子创造一个ServletHandler实例并配置一个HelloServlet:
// // ======================================================================== // Copyright (c) 1995-2014 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 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 { // Create a basic jetty server object that will listen on port 8080. Note that if you set this to port 0 // then a randomly available port will be assigned that you can either look in the logs for the port, // or programmatically obtain it for use in test cases. Server server = new Server(8080); // The ServletHandler is a dead simple way to create a context handler that is backed by an instance of a // Servlet. This handler then needs to be registered with the Server object. ServletHandler handler = new ServletHandler(); server.setHandler(handler); // Passing in the class for the servlet allows jetty to instantite an instance of that servlet and mount it // on a given context path. // !! This is a raw Servlet, not a servlet that has been configured through a web.xml or anything like that !! handler.addServletWithMapping(HelloServlet.class, "/*"); // Start things up! By using the server.join() the server thread will join with the current thread. // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details. 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 SimpleServlet</h1>"); } } }
嵌入上下文
ContextHandler是一个ScopedHandler,仅对那些URI前缀匹配配置的上下文路径的请求作出响应。匹配上下文路径的请求有他们的路径方法相应地被更新,上下文作用域是可用的,包括:
1)一个Classloader,当请求处理在作用域内时作为线程上下文classloader被设置;
2)一组属性,通过ServletContext API是可用的;
3)一组初始化参数,通过ServletContext API是可用的;
4)基础资源,用于静态资源请求;
5)一组虚拟主机名。
下面的OneContext例子展示一个上下文怎么被建立:
// // ======================================================================== // Copyright (c) 1995-2014 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.Server; import org.eclipse.jetty.server.handler.ContextHandler; public class OneContext { public static void main(String[] args) throws Exception { Server server = new Server(8080); ContextHandler context = new ContextHandler(); context.setContextPath("/"); context.setResourceBase("."); context.setClassLoader(Thread.currentThread().getContextClassLoader()); context.setHandler(new HelloHandler()); server.setHandler(context); server.start(); server.join(); } }
当许多上下文存在时,你能使用一个ContextHandlerCollection。下面ManyContexts的例子展示你怎么配置:
// // ======================================================================== // Copyright (c) 1995-2014 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.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(); } }
嵌入ServletContexts
一个ServletContextHandler专门用于支持标准sessions和Servlets。看下面OneServletContext的例子:
// // ======================================================================== // Copyright (c) 1995-2014 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.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; public class OneServletContext { public static void main(String[] args) throws Exception { Server server = new Server(8080); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); server.setHandler(context); context.addServlet(org.eclipse.jetty.servlet.DefaultServlet.class,"/"); context.addServlet(new ServletHolder(new DumpServlet()),"/dump/*"); server.start(); server.join(); } }
嵌入Web应用
一个WebAppContext是一个ServletContextHandler的扩展,使用标准布局和web.xml配置servlets、filters和其它特性。下面的OneWebApp的例子配置Jetty test webapp。web应用能用容器提供的资源,在这个例子中LoginService被需要和配置:
// // ======================================================================== // Copyright (c) 1995-2014 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.lang.management.ManagementFactory; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.webapp.WebAppContext; public class OneWebApp { public static void main(String[] args) throws Exception { // Create a basic jetty server object that will listen on port 8080. Note that if you set this to port 0 then // a randomly available port will be assigned that you can either look in the logs for the port, // or programmatically obtain it for use in test cases. Server server = new Server(8080); // Setup JMX MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer()); server.addBean(mbContainer); // The WebAppContext is the entity that controls the environment in which a web application lives and // breathes. In this example the context path is being set to "/" so it is suitable for serving root context // requests and then we see it setting the location of the war. A whole host of other configurations are // available, ranging from configuring to support annotation scanning in the webapp (through // PlusConfiguration) to choosing where the webapp will unpack itself. WebAppContext webapp = new WebAppContext(); webapp.setContextPath("/"); webapp.setWar("../../jetty-distribution/target/distribution/demo-base/webapps/test.war"); // A WebAppContext is a ContextHandler as well so it needs to be set to the server so it is aware of where to // send the appropriate requests. server.setHandler(webapp); // Configure a LoginService // Since this example is for our test webapp, we need to setup a LoginService so this shows how to create a // very simple hashmap based one. The name of the LoginService needs to correspond to what is configured in // the webapp's web.xml and since it has a lifecycle of its own we register it as a bean with the Jetty // server object so it can be started and stopped according to the lifecycle of the server itself. HashLoginService loginService = new HashLoginService(); loginService.setName("Test Realm"); loginService.setConfig("src/test/resources/realm.properties"); server.addBean(loginService); // Start things up! By using the server.join() the server thread will join with the current thread. // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details. server.start(); server.join(); } }
使用Jetty XML
通常配置一个Jetty server实例的方法是通过jetty.xml和相关的配置文件。然而Jetty XML配置格式仅仅是你在代码中能做的的简单呈现;在代码中实现jetty.xml配置做的事情是非常简单的。下面LikeJettyXml例子将在代码中呈现下面配置文件包含的行为:
1)jetty.xml
2)jetty-jmx.xml
3)jetty-http.xml
4)jetty-https.xml
5)jetty-deploy.xml
6)jetty-stats.xml
7)jetty-requestlog.xml
8)jetty-lowresources.xml
9)test-realm.xml
// // ======================================================================== // Copyright (c) 1995-2014 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.lang.management.ManagementFactory; import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.deploy.PropertiesConfigurationManager; import org.eclipse.jetty.deploy.providers.WebAppProvider; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.security.HashLoginService; 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 org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; public class LikeJettyXml { public static void main(String[] args) throws Exception { String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution"); String jetty_base = System.getProperty("jetty.home","../../jetty-distribution/target/distribution/demo-base"); 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 + "/etc/keystore"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); sslContextFactory.setTrustStorePath(jetty_home + "/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,"http/1.1"), new HttpConnectionFactory(https_config)); sslConnector.setPort(8443); server.addConnector(sslConnector); // === jetty-deploy.xml === DeploymentManager deployer = new DeploymentManager(); deployer.setContexts(contexts); deployer.setContextAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*/servlet-api-[^/]*\\.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); // === jetty-stats.xml === StatisticsHandler stats = new StatisticsHandler(); stats.setHandler(server.getHandler()); server.setHandler(stats); // === 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.setRefreshInterval(0); server.addBean(login); // Start the server server.start(); server.join(); } }
嵌入的例子
简单的文件服务器
这个例子展示怎么在Jetty中创建一个简单的文件服务器。
// // ======================================================================== // Copyright (c) 1995-2014 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.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; /* ------------------------------------------------------------ */ /** Simple Jetty FileServer. * This is a simple example of Jetty configured as a FileServer. */ public class FileServer { public static void main(String[] args) throws Exception { // Create a basic Jetty server object that will listen on port 8080. Note that if you set this to port 0 // then a randomly available port will be assigned that you can either look in the logs for the port, // or programmatically obtain it for use in test cases. Server server = new Server(8080); // Create the ResourceHandler. It is the object that will actually handle the request for a given file. It is // a Jetty Handler object so it is suitable for chaining with other handlers as you will see in other examples. ResourceHandler resource_handler = new ResourceHandler(); // Configure the ResourceHandler. Setting the resource base indicates where the files should be served out of. // In this example it is the current directory but it can be configured to anything that the jvm has access to. resource_handler.setDirectoriesListed(true); resource_handler.setWelcomeFiles(new String[]{ "index.html" }); resource_handler.setResourceBase("."); // Add the ResourceHandler to the server. HandlerList handlers = new HandlerList(); handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() }); server.setHandler(handlers); // Start things up! By using the server.join() the server thread will join with the current thread. // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details. server.start(); server.join(); } }
在你的项目中使用这个例子,你需要配置Maven坐标:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>${project.version}</version> </dependency>
分离文件服务器
这个例子在上一个的基础上展示怎么串联多个ResourceHandlers在一起,让你能够在一个路径下提供多个文件夹下的资源,并且展示你怎么能链接这些和ContextHandlers在一起。
// // ======================================================================== // Copyright (c) 1995-2014 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.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.resource.Resource; /* ------------------------------------------------------------ */ /** * A {@link ContextHandlerCollection} handler may be used to direct a request to * a specific Context. The URI path prefix and optional virtual host is used to * select the context. * */ public class SplitFileServer { public static void main(String[] args) throws Exception { // Create the Server object and a corresponding ServerConnector and then set the port for the connector. In // this example the server will listen on port 8090. If you set this to port 0 then when the server has been // started you can called connector.getLocalPort() to programmatically get the port the server started on. Server server = new Server(); ServerConnector connector = new ServerConnector(server); connector.setPort(8090); server.setConnectors(new Connector[] { connector }); // Create a Context Handler and ResourceHandler. The ContextHandler is getting set to "/" path but this could // be anything you like for builing out your url. Note how we are setting the ResourceBase using our jetty // maven testing utilities to get the proper resource directory, you needn't use these, // you simply need to supply the paths you are looking to serve content from. ContextHandler context0 = new ContextHandler(); context0.setContextPath("/"); ResourceHandler rh0 = new ResourceHandler(); rh0.setBaseResource( Resource.newResource(MavenTestingUtils.getTestResourceDir("dir0"))); context0.setHandler(rh0); // Rinse and repeat the previous item, only specifying a different resource base. ContextHandler context1 = new ContextHandler(); context1.setContextPath("/"); ResourceHandler rh1 = new ResourceHandler(); rh1.setBaseResource( Resource.newResource(MavenTestingUtils.getTestResourceDir("dir1"))); context1.setHandler(rh1); // Create a ContextHandlerCollection and set the context handlers to it. This will let jetty process urls // against the declared contexts in order to match up content. ContextHandlerCollection contexts = new ContextHandlerCollection(); contexts.setHandlers(new Handler[] { context0, context1 }); server.setHandler(contexts); // Start things up! By using the server.join() the server thread will join with the current thread. // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details. server.start(); System.err.println(server.dump()); server.join(); } }
为了在你的项目中使用这个例子,你需要配置Maven坐标:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.eclipse.jetty.toolchain</groupId> <artifactId>jetty-test-helper</artifactId> <version>2.2</version> </dependency>
多连接器
这个例子展示怎么配置Jetty使用多个连接器,以至于它能同时处理http和https请求。
// // ======================================================================== // Copyright (c) 1995-2014 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.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; /* ------------------------------------------------------------ */ /** * A Jetty server with multiple connectors. */ public class ManyConnectors { public static void main(String[] args) throws Exception { // Since this example shows off SSL configuration, we need a keystore with the appropriate key. These two // lines are purely a hack to get access to a keystore that we use in many unit tests and should probably be // a direct path to your own keystore (used on line 29). String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution"); System.setProperty("jetty.home", jetty_home); // Create a basic jetty server object without declaring the port. Since we are configuring connectors // directly we'll be setting ports on those connectors. Server server = new Server(); // HTTP Configuration // HttpConfiguration is a collection of configuration information appropriate for http and https. The default // scheme for http is <code>http</code> of course, as the default for secured http is <code>https</code> but // we show setting the scheme to show it can be done. The port for secured communication is also set here. HttpConfiguration http_config = new HttpConfiguration(); http_config.setSecureScheme("https"); http_config.setSecurePort(8443); http_config.setOutputBufferSize(32768); // HTTP connector // The first server connector we create is the one for http, passing in the http configuration we configured // above so it can get things like the output buffer size, etc. We also set the port (8080) and configure an // idle timeout. ServerConnector http = new ServerConnector(server,new HttpConnectionFactory(http_config)); http.setPort(8080); http.setIdleTimeout(30000); // SSL Context Factory for HTTPS and SPDY // SSL requires a certificate so we configure a factory for ssl contents with information pointing to what // keystore the ssl connection needs to know about. Much more configuration is available the ssl context, // including things like choosing the particular certificate out of a keystore to be used. SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(jetty_home + "/etc/keystore"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); // HTTPS Configuration // A new HttpConfiguration object is needed for the next connector and you can pass the old one as an // argument to effectively clone the contents. On this HttpConfiguration object we add a // SecureRequestCustomizer which is how a new connector is able to resolve the https connection before // handing control over to the Jetty Server. HttpConfiguration https_config = new HttpConfiguration(http_config); https_config.addCustomizer(new SecureRequestCustomizer()); // HTTPS connector // We create a second ServerConnector, passing in the http configuration we just made along with the // previously created ssl context factory. Next we set the port and a longer idle timeout. ServerConnector https = new ServerConnector(server, new SslConnectionFactory(sslContextFactory,"http/1.1"), new HttpConnectionFactory(https_config)); https.setPort(8443); https.setIdleTimeout(500000); // Here you see the server having multiple connectors registered with it, now requests can flow into the server // from both http and https urls to their respective ports and be processed accordingly by jetty. A simple // handler is also registered with the server so the example has something to pass requests off to. // Set the connectors server.setConnectors(new Connector[] { http, https }); // Set a handler server.setHandler(new HelloHandler()); // Start the server server.start(); server.join(); } }
为了使用这个例子,你需要配置Maven坐标:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-security</artifactId> <version>${project.version}</version> </dependency>
嵌入SPDY Server
这个例子展示怎么在Jetty中创建一个带SPDY连接器的Server。带有SPDY客户端实现的客户端(大部分浏览器)将使用SPDY协议连接,其它的将自动退回使用HTTP,其对应用是透明的。
// // ======================================================================== // Copyright (c) 1995-2014 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.lang.management.ManagementFactory; import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.deploy.providers.WebAppProvider; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.server.AsyncNCSARequestLog; import org.eclipse.jetty.server.ForwardedRequestCustomizer; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; 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.spdy.server.NPNServerConnectionFactory; import org.eclipse.jetty.spdy.server.SPDYServerConnectionFactory; import org.eclipse.jetty.spdy.server.http.HTTPSPDYServerConnectionFactory; import org.eclipse.jetty.spdy.server.http.PushStrategy; import org.eclipse.jetty.spdy.server.http.ReferrerPushStrategy; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; public class SpdyServer { public static void main(String[] args) throws Exception { String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution"); System.setProperty("jetty.home",jetty_home); // Setup Threadpool QueuedThreadPool threadPool = new QueuedThreadPool(512); // Setup Jetty Server instance Server server = new Server(threadPool); server.manage(threadPool); server.setDumpAfterStart(false); server.setDumpBeforeStop(false); // Setup JMX MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer()); server.addBean(mbContainer); // Common HTTP configuration HttpConfiguration config = new HttpConfiguration(); config.setSecurePort(8443); config.addCustomizer(new ForwardedRequestCustomizer()); config.addCustomizer(new SecureRequestCustomizer()); config.setSendServerVersion(true); // Http Connector Setup // A plain HTTP connector listening on port 8080. Note that it's also possible to have port 8080 configured as // a non SSL SPDY connector. But the specification and most browsers do not allow to use SPDY without SSL // encryption. However some browsers allow it to be configured. HttpConnectionFactory http = new HttpConnectionFactory(config); ServerConnector httpConnector = new ServerConnector(server,http); httpConnector.setPort(8080); httpConnector.setIdleTimeout(10000); server.addConnector(httpConnector); // SSL configurations // We need a SSLContextFactory for the SSL encryption. That SSLContextFactory will be used by the SPDY // connector. SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(jetty_home + "/etc/keystore"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); sslContextFactory.setTrustStorePath(jetty_home + "/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"); // Spdy Connector // Make sure that the required NPN implementations are available. SPDYServerConnectionFactory.checkProtocolNegotiationAvailable(); // A ReferrerPushStrategy is being initialized. // See: http://www.eclipse.org/jetty/documentation/current/spdy-configuring-push.html for more details. PushStrategy push = new ReferrerPushStrategy(); HTTPSPDYServerConnectionFactory spdy2 = new HTTPSPDYServerConnectionFactory(2,config,push); spdy2.setInputBufferSize(8192); spdy2.setInitialWindowSize(32768); // We need a connection factory per protocol that our server is supposed to support on the NPN port. We then // create a ServerConnector and pass in the supported factories. NPN will then be used to negotiate the // protocol with the client. HTTPSPDYServerConnectionFactory spdy3 = new HTTPSPDYServerConnectionFactory(3,config,push); spdy2.setInputBufferSize(8192); NPNServerConnectionFactory npn = new NPNServerConnectionFactory(spdy3.getProtocol(),spdy2.getProtocol(),http.getProtocol()); npn.setDefaultProtocol(http.getProtocol()); npn.setInputBufferSize(1024); SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory,npn.getProtocol()); // Setup the npn connector on port 8443 ServerConnector spdyConnector = new ServerConnector(server,ssl,npn,spdy3,spdy2,http); spdyConnector.setPort(8443); server.addConnector(spdyConnector); // The following section adds some handlers, deployers and webapp providers. // See: http://www.eclipse.org/jetty/documentation/current/advanced-embedding.html for details. // Setup handlers HandlerCollection handlers = new HandlerCollection(); ContextHandlerCollection contexts = new ContextHandlerCollection(); RequestLogHandler requestLogHandler = new RequestLogHandler(); handlers.setHandlers(new Handler[] { contexts, new DefaultHandler(), requestLogHandler }); StatisticsHandler stats = new StatisticsHandler(); stats.setHandler(handlers); server.setHandler(stats); // Setup deployers DeploymentManager deployer = new DeploymentManager(); deployer.setContexts(contexts); server.addBean(deployer); WebAppProvider webapp_provider = new WebAppProvider(); webapp_provider.setMonitoredDirName(jetty_home + "/webapps"); webapp_provider.setParentLoaderPriority(false); webapp_provider.setExtractWars(true); webapp_provider.setScanInterval(2); webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml"); deployer.addAppProvider(webapp_provider); HashLoginService login = new HashLoginService(); login.setName("Test Realm"); login.setConfig(jetty_home + "/etc/realm.properties"); server.addBean(login); NCSARequestLog requestLog = new AsyncNCSARequestLog(); requestLog.setFilename(jetty_home + "/logs/jetty-yyyy_mm_dd.log"); requestLog.setExtended(false); requestLogHandler.setRequestLog(requestLog); server.setStopAtShutdown(true); server.start(); server.dumpStdErr(); server.join(); } }
为了使用这个例子,你需要配置Maven坐标:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-spdy</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-deploy</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util</artifactId> <version>${project.version}</version> </dependency>
安全Hello Handler
这个例子展示怎么包装一个handler到另一个处理安全的handler。
// // ======================================================================== // Copyright (c) 1995-2014 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.util.Collections; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.security.Constraint; public class SecuredHelloHandler { public static void main(String[] args) throws Exception { // Create a basic jetty server object that will listen on port 8080. Note that if you set this to port 0 // then a randomly available port will be assigned that you can either look in the logs for the port, // or programmatically obtain it for use in test cases. Server server = new Server(8080); // Since this example is for our test webapp, we need to setup a LoginService so this shows how to create a // very simple hashmap based one. The name of the LoginService needs to correspond to what is configured a // webapp's web.xml and since it has a lifecycle of its own we register it as a bean with the Jetty server // object so it can be started and stopped according to the lifecycle of the server itself. In this example // the name can be whatever you like since we are not dealing with webapp realms. LoginService loginService = new HashLoginService("MyRealm","src/test/resources/realm.properties"); server.addBean(loginService); // A security handler is a jetty handler that secures content behind a particular portion of a url space. The // ConstraintSecurityHandler is a more specialized handler that allows matching of urls to different // constraints. The server sets this as the first handler in the chain, // effectively applying these constraints to all subsequent handlers in the chain. ConstraintSecurityHandler security = new ConstraintSecurityHandler(); server.setHandler(security); // This constraint requires authentication and in addition that an authenticated user be a member of a given // set of roles for authorization purposes. Constraint constraint = new Constraint(); constraint.setName("auth"); constraint.setAuthenticate( true ); constraint.setRoles(new String[]{"user", "admin"}); // Binds a url pattern with the previously created constraint. The roles for this constraing mapping are // mined from the Constraint itself although methods exist to declare and bind roles separately as well. ConstraintMapping mapping = new ConstraintMapping(); mapping.setPathSpec( "/*" ); mapping.setConstraint( constraint ); // First you see the constraint mapping being applied to the handler as a singleton list, // however you can passing in as many security constraint mappings as you like so long as they follow the // mapping requirements of the servlet api. Next we set a BasicAuthenticator instance which is the object // that actually checks the credentials followed by the LoginService which is the store of known users, etc. security.setConstraintMappings(Collections.singletonList(mapping)); security.setAuthenticator(new BasicAuthenticator()); security.setLoginService(loginService); // The Hello Handler is the handler we are securing so we create one, and then set it as the handler on the // security handler to complain the simple handler chain. HelloHandler hh = new HelloHandler(); // chain the hello handler into the security handler security.setHandler(hh); // Start things up! By using the server.join() the server thread will join with the current thread. // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details. server.start(); server.join(); } }
域属性文件(realm.properties)
# # This file defines users passwords and roles for a HashUserRealm # # The format is # <username>: <password>[,<rolename> ...] # # Passwords may be clear text, obfuscated or checksummed. The class # org.eclipse.util.Password should be used to generate obfuscated # passwords or password checksums # # If DIGEST Authentication is used, the password must be in a recoverable # format, either plain text or OBF:. # jetty: MD5:164c88b302622e17050af52c89945d44,user admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin,user other: OBF:1xmk1w261u9r1w1c1xmq,user plain: plain,user user: password,user # This entry is for digest auth. The credential is a MD5 hash of username:realmname:password digest: MD5:6e120743ad67abfbc385bc2bb754e297,user
为了使用这个例子,你需要添加Maven坐标:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>${project.version}</version> </dependency>
最简单Servlet
这个例子展示怎么在Jetty中部署一个最简单的servlet。
// // ======================================================================== // Copyright (c) 1995-2014 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 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 { // Create a basic jetty server object that will listen on port 8080. Note that if you set this to port 0 // then a randomly available port will be assigned that you can either look in the logs for the port, // or programmatically obtain it for use in test cases. Server server = new Server(8080); // The ServletHandler is a dead simple way to create a context handler that is backed by an instance of a // Servlet. This handler then needs to be registered with the Server object. ServletHandler handler = new ServletHandler(); server.setHandler(handler); // Passing in the class for the servlet allows jetty to instantite an instance of that servlet and mount it // on a given context path. // !! This is a raw Servlet, not a servlet that has been configured through a web.xml or anything like that !! handler.addServletWithMapping(HelloServlet.class, "/*"); // Start things up! By using the server.join() the server thread will join with the current thread. // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details. 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 SimpleServlet</h1>"); } } }
为了在你的项目中使用这个例子,你需要配置Maven坐标:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>${project.version}</version> </dependency>
Web应用
这个例子展示怎么使用一个嵌入的Jetty实例部署一个简单的webapp。
// // ======================================================================== // Copyright (c) 1995-2014 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.lang.management.ManagementFactory; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.webapp.WebAppContext; public class OneWebApp { public static void main(String[] args) throws Exception { // Create a basic jetty server object that will listen on port 8080. Note that if you set this to port 0 then // a randomly available port will be assigned that you can either look in the logs for the port, // or programmatically obtain it for use in test cases. Server server = new Server(8080); // Setup JMX MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer()); server.addBean(mbContainer); // The WebAppContext is the entity that controls the environment in which a web application lives and // breathes. In this example the context path is being set to "/" so it is suitable for serving root context // requests and then we see it setting the location of the war. A whole host of other configurations are // available, ranging from configuring to support annotation scanning in the webapp (through // PlusConfiguration) to choosing where the webapp will unpack itself. WebAppContext webapp = new WebAppContext(); webapp.setContextPath("/"); webapp.setWar("../../jetty-distribution/target/distribution/demo-base/webapps/test.war"); // A WebAppContext is a ContextHandler as well so it needs to be set to the server so it is aware of where to // send the appropriate requests. server.setHandler(webapp); // Configure a LoginService // Since this example is for our test webapp, we need to setup a LoginService so this shows how to create a // very simple hashmap based one. The name of the LoginService needs to correspond to what is configured in // the webapp's web.xml and since it has a lifecycle of its own we register it as a bean with the Jetty // server object so it can be started and stopped according to the lifecycle of the server itself. HashLoginService loginService = new HashLoginService(); loginService.setName("Test Realm"); loginService.setConfig("src/test/resources/realm.properties"); server.addBean(loginService); // Start things up! By using the server.join() the server thread will join with the current thread. // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details. server.start(); server.join(); } }
为了在你的项目中使用这个例子,你需要配置Maven坐标:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>${project.version}</version> </dependency>
Jetty开发指导:嵌入