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>
时间: 2024-07-30 23:50:01

Jetty开发指导:嵌入的相关文章

Jetty开发指导:Maven和Jetty

使用Maven Apache Maven是一种软件项目管理和综合工具.基于项目对象模型(POM)的概念,Maven能从核心信息管理一个项目的构建.报告和文档. 他是用于构建一个web应用项目的理想工具,这些项目能用jetty-maven-plugin轻松的运行web应用,从而节省开发时间.你也能用Maven构建.测试和运行一个嵌入Jetty的项目. 首先我们将看一个很简单嵌入Jetty的HelloWorld Java应用,然后看一个简单的webapp怎么使用jetty-maven-plugin加

Jetty开发指导:调试

如果你有一个web应用部署到Jetty,你能容易地从远程调试它.但首先你必须使用附加的参数启动远程JVM,然后在Eclipse中启动一个远程调试连接.这很容易就能做到. 注意:下面的例子假定你正在部署你的web应用到Jetty发布版本中. 设置Jetty调试端口 假定你将你的webapp部署到Jetty,有两种不同的方式设置调试端口: 通过命令行 在命令行中增加要求的参数如下: $ java -Xdebug -agentlib:jdwp=transport=dt_socket,address=9

Jetty开发指导:框架

Spring设置 你能嵌入Jetty到你的项目中,也能够使用差点儿全部的IoC类型框架,包含Spring.假设全部你想做的是在你的Spring中设置Jetty Server,那么以下的xml片段能够作为一个样例.假设你想使用spring代替jetty-xml也是能够的,但这样将不能利用模块系统的其余部分. Jetty-Spring模块 一个Jetty Spring模块的框架能通过模块机制激活.比如: $ java -jar start.jar --add-to-startd=spring 这(或

Jetty开发指导:Handlers

Rewrite Handler RewriteHandler基于一套规则匹配一个请求,然后根据匹配的规则修改请求.最常见的是重写请求的URI,但是不仅限于此:规则能被配置为重定向响应.设置一个cookie或者响应的响应代码.修改header,等等. 快速开始 标准Jetty发布中包含jetty-rewrite模块JAR,在lib/jetty-rewrite-*.jar,和一个例子配置文件,在etc/jetty-rewrite.xml.为了激活重写模块,用例子配置文件,用如下命令启动Jetty:

Jetty开发指导:WebSocket介绍

WebSocket是一个新的基于HTTP的双向通讯的协议. 它是基于低级别的框架协议.使用UTF-8 TEXT或者BINARY格式传递信息. 在WebSocket中的单个信息能够是不论什么长度(然而底层框架有单帧63bits的限制). 发送的信息数量不受限制. 信息被持续的发送,基础协议不支持交叉的信息. 一个WebSocket连接经历一些主要的状态改变: 1)CONNECTING:HTTP升级到WebSocket正在进行中 2)OPEN:HTTP升级成功,而且socket如今打开并准备读/写

Jetty开发指导:HTTP Client

介绍 Jetty HTTP client模块提供易用的API.工具类和一个高性能.异步的实现来运行HTTP和HTTPS请求. Jetty HTTP client模块要求Java版本号1.7或者更高,Java 1.8的应用能用lambda表达式在一些HTTP client API中. Jetty HTTP client被实现和提供一个异步的API.不会由于I/O时间堵塞,因此使它在线程的利用上更有效率,并不是常适合用于负载測试和并行计算. 然而,有时你全部须要做的是对一个资源运行一个GET请求,H

Jetty开发指导:Jetty Websocket API

Jetty WebSocket API使用 Jetty提供了功能更强的WebSocket API,使用一个公共的核心API供WebSockets的服务端和client使用. 他是一个基于WebSocket消息的事件驱动的API. WebSocket事件 每一个WebSocket都能接收多种事件: On Connect Event 表示WebSocket升级成功,WebSocket如今打开. 你将收到一个org.eclipse.jetty.websocket.api.Session对象,相应这个O

jetty使用教程(嵌入eclipse开发)

在eclipse下面建一个java project 建立目录结构如下: 二级目录: (备注jetty_test是工程的根目录,etc.lib.webRoot为其二级目录) 到jetty的官方网站(http://www.eclipse.org/jetty/)下载jetty的开发包: 我下载的jetty-hightide-8.0.0.v20110901.tar.gz: 把里面的lib目录的jar包和lib/jsp目录下面的jar包导入到工程里面 说明白,其实jetty.xml和webdefault.

Jetty使用教程(四:21-22)—Jetty开发指南

二十一.嵌入式开发 21.1 Jetty嵌入式开发HelloWorld 本章节将提供一些教程,通过Jetty API快速开发嵌入式代码 21.1.1 下载Jetty的jar包 Jetty目前已经把所有功能分解成小的jar包,用户可以根据需要选择合适的jar包,来实现需要的功能.通常建议用户使用maven等管理工具来管理jar包,然而本教程使用一个包含所有功能的合集jar包来演示,用户可以使用curl或者浏览器下载jetty-all.jar包. jetty-all.jar下载地址:http://c