Jetty 開發指南:Jetty 內嵌開發


Jetty的口號是“不要在Jetty中部署你的應用程序,在你的應用程序中部署Jetty!” 這意味着,作為將應用程序捆綁為要部署在Jetty中的標准WAR的替代方案,Jetty旨在成為一個軟件組件,可以像任何POJO一樣在Java程序中實例化和使用。 換句話說,在嵌入模式下運行Jetty意味着將HTTP模塊放入應用程序,而不是將應用程序放入HTTP服務器。

本教程將逐步介紹從最簡單的Jetty服務器實例化到使用基於標准的部署描述符運行多個Web應用程序。 大多數這些示例的來源是標准Jetty項目的一部分。

1. 概述

要嵌入Jetty服務器,以下典型的步驟,本教程中的示例說明了這些步驟:

  1. 創建一個Server實例。
  2. 添加/配置連接器(Connectors)。
  3. 添加/配置處理器(Handlers)、上下文(Contexts)、Servlets。
  4. 啟動服務器。
  5. 等待連接或用線程做其他事情。

2. 創建Server

SimplestServer.java中的以下代碼為實例化並運行最簡單的Jetty服務器:

package org.eclipse.jetty.embedded;

import org.eclipse.jetty.server.Server;

/**
 * 最簡單的 Jetty 服務器
 */
public class SimplestServer
{
    public static void main( String[] args ) throws Exception
    {
        Server server = new Server(8080);
        server.start();
        server.dumpStdErr();
        server.join();
    }
}

上面程序運行一個http server在8090端口。但是這個server沒有任何用處,因為它沒有任何handler,因此不管任何的請求都會返回404.

3. 使用 Handlers

要生成對請求的響應,Jetty要求您在服務器上設置Handler。 處理程序可以:

  1. 檢查/修改HTTP請求。
  2. 生成完整的HTTP響應。
  3. 調用另一個Handler(參見HandlerWrapper)。
  4. 選擇一個或多個要調用的處理程序(請參閱HandlerCollection)。

3.1 HelloWorld Handler

以下HelloHandler.java的代碼顯示了一個簡單的hello world處理程序:

package org.eclipse.jetty.embedded;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;

public class HelloHandler extends AbstractHandler
{
    final String greeting;
    final String body;

    public HelloHandler()
    {
        this("Hello World");
    }

    public HelloHandler( String greeting )
    {
        this(greeting, null);
    }

    public HelloHandler( String greeting, String body )
    {
        this.greeting = greeting;
        this.body = body;
    }

    @Override
    public void handle( String target,
                        Request baseRequest,
                        HttpServletRequest request,
                        HttpServletResponse response ) throws IOException,
                                                      ServletException
    {
        response.setContentType("text/html; charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);

        PrintWriter out = response.getWriter();

        out.println("<h1>" + greeting + "</h1>");
        if (body != null)
        {
            out.println(body);
        }

        baseRequest.setHandled(true);
    }
}

 

傳遞給handle方法的參數是:

  • target - 請求的目標,它是URI或命名調度程序的名稱。
  • baseRequest - Jetty可變請求對象,沒有被包裝的request對象。
  • request - 不可變請求對象,可能已被filter或servlet包裝。
  • response- 響應,可能已被過濾器或servlet包裝。

handler設置響應狀態,內容類型,並在使用writer生成響應主體之前將請求標記為已處理。

3.2 運行 HelloWorldHandler

package org.eclipse.jetty.embedded;

import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;

public class OneHandler
{
    public static void main( String[] args ) throws Exception
    {
        Server server = new Server(8080);
        server.setHandler(new HelloHandler());

        server.start();
        server.join();
    }
}

在Jetty中一般有一個或者多個handler來處理所有的請求。有些handler會選擇其他指定的handler去做處理(例如ContextHandlerCollection會通過context path來選擇ContextHandler); 還有一些handler通過應用程序邏輯生成響應(例如,ServletHandler將請求傳遞給應用Servlet),其他的handler則執行與生成響應無關的任務(例如,RequestLogHandler或StatisticsHandler)。

后面的章節描述了你可以像切面一樣組合多個handler。 您可以在org.eclipse.jetty.server.handler包中看到Jetty中的一些可用的Handlers。

4. Handler Collections and Wrappers

復雜請求處理通常由多個Handler構建,您可以通過各種方式進行組合。 Jetty有幾個HandlerContainer接口的實現:

  • HandlerCollection

    保存其他 handler 集合並按順序調用每個handler。這對於將統計信息和日志記錄 handler 與生成響應的 handler 相結合非常有用。

  • HandlerList

    一個Handler 集合,它依次調用每個 handler,直到拋出異常,響應被提交或request.isHandled() 返回true。您可以使用它來組合handler有選擇的處理請看清,例如調用多個Context上下文直到與虛擬主機匹配。

  • HandlerWrapper

一個Handler基類,可用於以面向切面編程的方式將處理程序連接在一起。例如,標准Web應用程序由上下文,會話,安全性和servlet處理程序鏈實現。

  • ContextHandlerCollection

  一個專門的HandlerCollection,它使用請求URI的最長前綴(contextPath)來選擇一個包含的ContextHandler來處理請求。

 

5. Scoped Handlers

Jetty中的大部分標准Servlet容器都是使用HandlerWrappers實現的,它們將handler 以鏈式組合在一起:ContextHandler --> SessionHandler --> SecurityHandler --> ServletHandler。 但是,由於servlet規范,這種 handler 鏈不能是純粹的嵌套,因為外部 handler 有時需要內部 handler 的處理信息。 例如,當ContextHandler調用某些應用程序listener以通知它們進入上下文的請求時,它必須已經知道ServletHandler將向哪個servlet分派請求,以便servletPath方法返回正確的值。

HandlerWrapper是ScopedHandler抽象類,它支鏈式鏈scopes。 例如,如果ServletHandler嵌套在ContextHandler中,則方法執行的順序和嵌套是:

Server.handle(...)
  ContextHandler.doScope(...)
    ServletHandler.doScope(...)
      ContextHandler.doHandle(...)
        ServletHandler.doHandle(...)
          SomeServlet.service(...)

6. Resource Handler

 FileServer示例顯示如何使用ResourceHandler從當前工作目錄提供靜態內容:

package org.eclipse.jetty.embedded;

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;

/**
 * 簡單的 Jetty 文件服務器
 * 這是一個Jetty 文件服務器配置的簡單示例
 */
public class FileServer
{
    public static void main(String[] args) throws Exception
    {
        // 創建一個將在8080端口偵聽的基本的服務器對象,注意,如果將端口設置為0
        // server 將會被分配一個隨機可用的端口,你可以在日志中看到分配的端口,
        // 或者則測試用例中通過編程方式獲取。
        Server server = new Server(8080);

        // 創建 ResourceHandler. 它是實際處理給定文件請求的對象。 
        // 它是一個 Jetty Handler 對象,因此你將在其他示例中看到它能夠和其他 handlers 進行鏈式處理。
        ResourceHandler resource_handler = new ResourceHandler();

        // 配置 ResourceHandler。設置提供文件服務的資源根目錄。
        // 在這個例子中是當前目錄,也可以配置成jvm有權限訪問的任何目錄。
        resource_handler.setDirectoriesListed(true);
        resource_handler.setWelcomeFiles(new String[]{ "index.html" });
        resource_handler.setResourceBase(".");

        // 將 ResourceHandler 添加至 server。
        HandlerList handlers = new HandlerList();
        handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
        server.setHandler(handlers);

        // 啟動服務,通過使用 server.join() server 線程將 join 當前線程
        // 在"http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" 了解更多細節.
        server.start();
        server.join();
    }
}

注意我們使用了ResourceHandler和DefaultHandler,所以DefaultHandler對於沒有匹配的請求會友好的返回404。

7. 內嵌 Connectors

在前面的示例中,Server實例通過構造方法傳遞了一個端口號,它在內部創建一個Connector的默認實例,用於偵聽該端口上的請求。 但是,通常在嵌入Jetty時,需要為Server實例顯式實例化和配置一個或多個連接器。

7.1 單個 Connector

以下OneConnector.java,實例化、配置並向服務器添加單個HTTP connector 實例:

package org.eclipse.jetty.embedded;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;

/**
 * 只有一個 Connector 的 Jetty server
 */
public class OneConnector
{
    public static void main( String[] args ) throws Exception
    {
        // Server
        Server server = new Server();

        // HTTP connector
        ServerConnector http = new ServerConnector(server);
        http.setHost("localhost");
        http.setPort(8080);
        http.setIdleTimeout(30000);

        // 設置 connector
        server.addConnector(http);

        // 設置 handler
        server.setHandler(new HelloHandler());

        // 啟動 Server
        server.start();
        server.join();
    }
}

在這個例子里connector處理http協議,因為這是ServerConnetor默認的配置。

 

7.2 多 Connectors

配置多個連接器(例如,HTTP和HTTPS)時,可能需要共享HTTP的公共參數的配置。 要實現此目的,您需要使用ConnectionFactory實例顯式配置ServerConnector類,並為它們提供常見的HTTP配置。

ManyConnectors示例使用兩個ServerConnector實例配置服務器:http連接器具有HTTPConnectionFactory實例; https連接器有一個鏈接到HttpConnectionFactory的SslConnectionFactory。 兩個HttpConnectionFactory都是基於相同的HttpConfiguration實例配置的,但HTTPS工廠使用包裝配置,以便可以添加SecureRequestCustomizer

 

8. 內嵌 Servlets

Servlet是提供處理HTTP請求的應用程序邏輯的標准方法。 Servlet類似於Jetty Handler,但請求對象不可變,因此無法修改。 Servlet由ServletHandler在Jetty中處理。 它使用標准路徑映射來將Servlet與請求進行匹配; 設置請求servletPath和pathInfo; 將請求傳遞給servlet,可能通過 Filters 生成響應。

MinimalServlets示例創建一個ServletHandler實例並配置一個HelloServlet:

package org.eclipse.jetty.embedded;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;

public class MinimalServlets
{
    public static void main( String[] args ) throws Exception
    {
        Server server = new Server(8080);

        // ServletHandler 是創建 context handler 的簡單方法,
        // 由 Servlet 實力支持。
        // 這個 handler 對象需要被注冊給 Server 對象。
        ServletHandler handler = new ServletHandler();
        server.setHandler(handler);

        // 傳遞的 Servlet 類允許 jetty 實例化並且掛載到給定的上下文路徑上。// 重要:
        // 這是一個原始的 Servlet, 不是一個通過 web.xml 或者 @WebServlet注解或者其他類似方式配置的servlet。
        handler.addServletWithMapping(HelloServlet.class, "/*");

        // 啟動服務
        server.start();

        // 使用 server.join() 加入當前線程//http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join() 查看更多。
        server.join();
    }

    @SuppressWarnings("serial")
    public static class HelloServlet extends HttpServlet
    {
        @Override
        protected void doGet( HttpServletRequest request,
                              HttpServletResponse response ) throws ServletException,
                                                            IOException
        {
            response.setContentType("text/html");
            response.setStatus(HttpServletResponse.SC_OK);
            response.getWriter().println("<h1>Hello from HelloServlet</h1>");
        }
    }
}

9. 內嵌 Contexts

ContextHandler是一個ScopedHandler,它只響應具有與配置的上下文路徑匹配的URI前綴的請求。 與上下文路徑匹配的請求會相應地更新其路徑方法,並且上下文范圍可用,可選擇:

  •  在請求處理期間為Thread context 設置 Classloader 。
  • 一組可通過ServletContext API獲得的屬性。
  • 一組可通過ServletContext API獲得的init參數。
  • 基本資源,通過ServletContext API用作靜態資源請求的文檔根。
  • 一組虛擬主機名。

以下OneContext示例顯示了正在建立的包裝HelloHandler的上下文:

package org.eclipse.jetty.embedded;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;

public class OneContext
{
    public static void main( String[] args ) throws Exception
    {
        Server server = new Server( 8080 );

        // 增加一個唯一的 handler 給 context "/hello"
        ContextHandler context = new ContextHandler();
        context.setContextPath( "/hello" );
        context.setHandler( new HelloHandler() );

        //http://localhost:8080/hello 訪問服務

        server.setHandler( context );

        // 啟動服務
        server.start();
        server.join();
    }
}

當存在許多上下文時,您可以嵌入ContextHandlerCollection以有效地檢查請求URI,然后為請求選擇匹配的ContextHandler。 ManyContexts示例展示了配置多個Context:

package org.eclipse.jetty.embedded;

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;

public class ManyContexts
{
    public static void main( String[] args ) throws Exception
    {
        Server server = new Server(8080);

        ContextHandler context = new ContextHandler("/");
        context.setContextPath("/");
        context.setHandler(new HelloHandler("Root Hello"));

        ContextHandler contextFR = new ContextHandler("/fr");
        contextFR.setHandler(new HelloHandler("Bonjoir"));

        ContextHandler contextIT = new ContextHandler("/it");
        contextIT.setHandler(new HelloHandler("Bongiorno"));

        ContextHandler contextV = new ContextHandler("/");
        contextV.setVirtualHosts(new String[] { "127.0.0.2" });
        contextV.setHandler(new HelloHandler("Virtual Hello"));

        ContextHandlerCollection contexts = new ContextHandlerCollection();
        contexts.setHandlers(new Handler[] { context, contextFR, contextIT,
                contextV });

        server.setHandler(contexts);

        server.start();
        server.join();
    }
}

10. 內嵌 ServletContexts

ServletContextHandler是ContextHandler的一個專門實例,用來支持標准Session和Servlet。 以下OneServletContext示例將DefaultServlet實例化,為/ tmp /目錄下的靜態資源提供服務,以及一個DumpServlet,用於創建會話並轉儲有關請求的基本詳細信息:

package org.eclipse.jetty.embedded;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;

public class OneServletContext
{
    public static void main( String[] args ) throws Exception
    {
        Server server = new Server(8080);

        ServletContextHandler context = new ServletContextHandler(
                ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        context.setResourceBase(System.getProperty("java.io.tmpdir"));
        server.setHandler(context);

        // 添加 dump servlet
        context.addServlet(DumpServlet.class, "/dump/*");
        // 添加 default servlet
        context.addServlet(DefaultServlet.class, "/");

        server.start();
        server.join();
    }
}

 

11. 內嵌 Applications

WebAppContext是ServletContextHandler的擴展,它使用 standard layout和web.xml從web.xml和/或注釋配置servlet,filter和其他功能。 以下OneWebApp示例配置Jetty測試webapp。 Web應用程序可以使用容器提供的資源,在這種情況下,還需要LoginService並進行配置:

package org.eclipse.jetty.embedded;

import java.io.File;
import java.lang.management.ManagementFactory;

import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker;
import org.eclipse.jetty.webapp.WebAppContext;

public class OneWebApp
{
    public static void main( String[] args ) throws Exception
    {
        Server server = new Server(8080);

        // 配置 JMX
        MBeanContainer mbContainer = new MBeanContainer(
                ManagementFactory.getPlatformMBeanServer());
        server.addBean(mbContainer);

        // WebAppContext 是一個控制 web 應用生存環境的實體,
        // 在這個例子中 context path 設置為 “/”,因此它能夠處理 root 上下文請求,然后我們能看到它設置war包路徑。// 還有許多其他配置, 從支持webapp注解掃描(通過PlusConfiguration)到選擇webapp的解壓位置。
        WebAppContext webapp = new WebAppContext();
        webapp.setContextPath("/");
        File warFile = new File(
                "../../tests/test-jmx/jmx-webapp/target/jmx-webapp");
        webapp.setWar(warFile.getAbsolutePath());

        // WebAppContext 是一個 ContextHandler,因此它需要設置給 server,從而能夠將請求發送到合適的位置sts.
        server.setHandler(webapp);

        // 啟動服務
        server.start();

        server.dumpStdErr();//http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join() 查看更多
        server.join();
    }
}

12. Like Jetty XML

配置Jetty服務器實例的典型方法是通過jetty.xml和相關配置文件。 但是,Jetty XML配置格式只是對代碼中可以執行的操作的簡單呈現; 編寫完全符合jetty.xml配置功能的嵌入式代碼非常簡單。 以下LikeJettyXml示例在代碼中呈現從配置文件中獲取的行為:

package org.eclipse.jetty.embedded;

import java.io.File;
import java.io.FileNotFoundException;
import java.lang.management.ManagementFactory;

import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.deploy.PropertiesConfigurationManager;
import org.eclipse.jetty.deploy.bindings.DebugListenerBinding;
import org.eclipse.jetty.deploy.providers.WebAppProvider;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.rewrite.handler.RewriteHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.DebugListener;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.LowResourceMonitor;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnectionStatistics;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.webapp.Configuration;

/**
 * Starts the Jetty Distribution's demo-base directory using entirely
 * embedded jetty techniques.
 */
public class LikeJettyXml
{
    public static void main( String[] args ) throws Exception
    {
        // Path to as-built jetty-distribution directory
        String jettyHomeBuild = "../../jetty-distribution/target/distribution";

        // Find jetty home and base directories
        String homePath = System.getProperty("jetty.home", jettyHomeBuild);
        File start_jar = new File(homePath,"start.jar");
        if (!start_jar.exists())
        {
            homePath = jettyHomeBuild = "jetty-distribution/target/distribution";
            start_jar = new File(homePath,"start.jar");
            if (!start_jar.exists())
                throw new FileNotFoundException(start_jar.toString());
        }

        File homeDir = new File(homePath);

        String basePath = System.getProperty("jetty.base", homeDir + "/demo-base");
        File baseDir = new File(basePath);
        if(!baseDir.exists())
        {
            throw new FileNotFoundException(baseDir.getAbsolutePath());
        }

        // Configure jetty.home and jetty.base system properties
        String jetty_home = homeDir.getAbsolutePath();
        String jetty_base = baseDir.getAbsolutePath();
        System.setProperty("jetty.home", jetty_home);
        System.setProperty("jetty.base", jetty_base);


        // === jetty.xml ===
        // Setup Threadpool
        QueuedThreadPool threadPool = new QueuedThreadPool();
        threadPool.setMaxThreads(500);

        // Server
        Server server = new Server(threadPool);

        // Scheduler
        server.addBean(new ScheduledExecutorScheduler());

        // HTTP Configuration
        HttpConfiguration http_config = new HttpConfiguration();
        http_config.setSecureScheme("https");
        http_config.setSecurePort(8443);
        http_config.setOutputBufferSize(32768);
        http_config.setRequestHeaderSize(8192);
        http_config.setResponseHeaderSize(8192);
        http_config.setSendServerVersion(true);
        http_config.setSendDateHeader(false);
        // httpConfig.addCustomizer(new ForwardedRequestCustomizer());

        // Handler Structure
        HandlerCollection handlers = new HandlerCollection();
        ContextHandlerCollection contexts = new ContextHandlerCollection();
        handlers.setHandlers(new Handler[] { contexts, new DefaultHandler() });
        server.setHandler(handlers);

        // Extra options
        server.setDumpAfterStart(false);
        server.setDumpBeforeStop(false);
        server.setStopAtShutdown(true);

        // === jetty-jmx.xml ===
        MBeanContainer mbContainer = new MBeanContainer(
                ManagementFactory.getPlatformMBeanServer());
        server.addBean(mbContainer);


        // === jetty-http.xml ===
        ServerConnector http = new ServerConnector(server,
                new HttpConnectionFactory(http_config));
        http.setPort(8080);
        http.setIdleTimeout(30000);
        server.addConnector(http);


        // === jetty-https.xml ===
        // SSL Context Factory
        SslContextFactory sslContextFactory = new SslContextFactory();
        sslContextFactory.setKeyStorePath(jetty_home + "/../../../jetty-server/src/test/config/etc/keystore");
        sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
        sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
        sslContextFactory.setTrustStorePath(jetty_home + "/../../../jetty-server/src/test/config/etc/keystore");
        sslContextFactory.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
        sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA",
                "SSL_DHE_RSA_WITH_DES_CBC_SHA", "SSL_DHE_DSS_WITH_DES_CBC_SHA",
                "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
                "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
                "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
                "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");

        // SSL HTTP Configuration
        HttpConfiguration https_config = new HttpConfiguration(http_config);
        https_config.addCustomizer(new SecureRequestCustomizer());

        // SSL Connector
        ServerConnector sslConnector = new ServerConnector(server,
            new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
            new HttpConnectionFactory(https_config));
        sslConnector.setPort(8443);
        server.addConnector(sslConnector);


        // === jetty-deploy.xml ===
        DeploymentManager deployer = new DeploymentManager();
        DebugListener debug = new DebugListener(System.err,true,true,true);
        server.addBean(debug);
        deployer.addLifeCycleBinding(new DebugListenerBinding(debug));
        deployer.setContexts(contexts);
        deployer.setContextAttribute(
                "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
                ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$");

        WebAppProvider webapp_provider = new WebAppProvider();
        webapp_provider.setMonitoredDirName(jetty_base + "/webapps");
        webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml");
        webapp_provider.setScanInterval(1);
        webapp_provider.setExtractWars(true);
        webapp_provider.setConfigurationManager(new PropertiesConfigurationManager());

        deployer.addAppProvider(webapp_provider);
        server.addBean(deployer);

        // === setup jetty plus ==
        Configuration.ClassList classlist = Configuration.ClassList
                .setServerDefault( server );
        classlist.addAfter(
                "org.eclipse.jetty.webapp.FragmentConfiguration",
                "org.eclipse.jetty.plus.webapp.EnvConfiguration",
                "org.eclipse.jetty.plus.webapp.PlusConfiguration");

        classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
                            "org.eclipse.jetty.annotations.AnnotationConfiguration");

        // === jetty-stats.xml ===
        StatisticsHandler stats = new StatisticsHandler();
        stats.setHandler(server.getHandler());
        server.setHandler(stats);
        ServerConnectionStatistics.addToAllConnectors(server);

        // === Rewrite Handler
        RewriteHandler rewrite = new RewriteHandler();
        rewrite.setHandler(server.getHandler());
        server.setHandler(rewrite);

        // === jetty-requestlog.xml ===
        NCSARequestLog requestLog = new NCSARequestLog();
        requestLog.setFilename(jetty_home + "/logs/yyyy_mm_dd.request.log");
        requestLog.setFilenameDateFormat("yyyy_MM_dd");
        requestLog.setRetainDays(90);
        requestLog.setAppend(true);
        requestLog.setExtended(true);
        requestLog.setLogCookies(false);
        requestLog.setLogTimeZone("GMT");
        RequestLogHandler requestLogHandler = new RequestLogHandler();
        requestLogHandler.setRequestLog(requestLog);
        handlers.addHandler(requestLogHandler);


        // === jetty-lowresources.xml ===
        LowResourceMonitor lowResourcesMonitor=new LowResourceMonitor(server);
        lowResourcesMonitor.setPeriod(1000);
        lowResourcesMonitor.setLowResourcesIdleTimeout(200);
        lowResourcesMonitor.setMonitorThreads(true);
        lowResourcesMonitor.setMaxConnections(0);
        lowResourcesMonitor.setMaxMemory(0);
        lowResourcesMonitor.setMaxLowResourcesTime(5000);
        server.addBean(lowResourcesMonitor);


        // === test-realm.xml ===
        HashLoginService login = new HashLoginService();
        login.setName("Test Realm");
        login.setConfig(jetty_base + "/etc/realm.properties");
        login.setHotReload(false);
        server.addBean(login);

        // Start the server
        server.start();
        server.join();
    }
}

 

上一節:Jetty 開發指南:(1) 嵌入式開發之HelloWorld

下一節:

參考資料:http://www.eclipse.org/jetty/documentation/9.4.x/embedding-jetty.html

 

PlusConfiguration


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM