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>