內置jetty


jetty有一個口號,不要把你的應用部署到jetty,而是把jetty部署到你的應用中。這說明使用jetty有兩種選擇,一種選擇是將你的應用部署到jetty容器中,另一種選擇是將jetty嵌入到你的應用層序中,后者意味着將一個http的模塊嵌入到了你的程序中,而不是把你的程序放入一個http的server中。

這個文檔就是幫助你一步一步將jetty嵌入到你的程序中。

1.概述

把jetty嵌入到你的程序中,一般都是下面的步驟:

  1. 創建一個server實例
  2. 增加或者配置connector
  3. 增加或者配置handler、context、servlet
  4. 啟動server
  5. 等待連接

2.創建一個server

下面的代碼創建了一個最簡單的server。

import org.eclipse.jetty.server.Server;

/**
 * Created by zdd on 2017/4/1.
 */
public class SimpleServer {
    public static void main(String[] args) throws Exception{
        Server server = new Server(8090);
        server.start();
        server.dumpStdErr();
        server.join();
    }
}

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

3.使用handler

為了對請求產生一個回應,jetty需要你在server上設置handler。一個handler可以:

  1. 檢查或者修改HTTP請求。
  2. 生成response回應。
  3. 調用另一個handler(查看HandlerWrapper)
  4. 選擇一個或者很多個handlers去調用(查看HandlerCollection)

3.1hello world Handler

下面的代碼展示了一個最簡單的helloworld handler:

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Created by zdd on 2017/4/1.
 */
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:請求的目標
  • baseRequest:沒有被包裝的request對象
  • request:不可變的request對象,可能被filter或者servlet包裝過。
  • response:請求的回應,也可能被filter或者servlet包裝過。

handler會設置response的狀態、response的內容類型、並且標記request被處理了,最后才通過out生成response的內容。

3.2運行helloworld Handler

為了允許handler去處理http請求,你必須把它綁定到server實例上。下面的代碼顯示了jetty server是如何和handler綁定的。

import org.eclipse.jetty.server.Server;

/**
 * Created by zdd on 2017/4/1.
 */
public class SimpleServer {
    public static void main(String[] args) throws Exception{
        Server server = new Server(8090);
        server.setHandler(new HelloHandler());
        server.start();
        server.join();
    }
}

在jetty中,一般總會有一個或者多個handler區處理所有的請求。有些handler會選擇其他指定的handler去做處理,例如(一個ContextHandlerCollection使用context path去選擇ContextHandler);還有一些是使用程序的邏輯去產生response,例如(ServletHandler將請求轉發給Servlet來處理),還有其他的一些是做一些無關的任務來生成response,例如(RequestLogHandler或者StatisticsHandler)。

后面的章節描述了你可以像切面一樣合並多個handler。你可以看到一些有價值的handler在org.eclipse.jetty.server.handler包中。

4.Handler Collections and Wrappers

復雜的請求需要你合並多個handler來處理。jetty提供了幾個HandlerContainer接口的實現:

  • HandlerCollection:擁有一個handler的集合並且調用順序調用每個handler。當你想合並統計和日志的handler這是很有用的。
  • HandlerList:一個handler的集合,會依次調用這個集合里面的handler,直到如果有異常發生、response已經被提交、resquest.isHandled()被調用。你可以使用這個來合並一些handler,例如調用handler來處理直到被匹配到的情況下。
  • HandlerWrapper:你可以使用這個來完成連接handlers類似於面向切面編程的風格。例如,一個標准的web程序被實現成一個context、session、security和servlet的串聯。
  • ContextHandlerClollection:一個特殊的HandlerCollection,使用最長uri匹配原則來選擇handler。

5.Scoped Handlers

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

6.Resource Handler

下面的代碼給你展示了你可以使用ReourceHandler去處理靜態的資源。

public class FileServer {
    public static void main(String[] args) throws Exception{

        // 創建一個最基本的jetty server並且綁定8090端口
        // 如果把端口指定為0,那么程序會自動選擇一個可用的端口
        Server server = new Server(8090);
        ResourceHandler resourceHandler = new ResourceHandler();
        // 設置resourceHandler監聽的目錄
        resourceHandler.setDirectoriesListed(true);
        resourceHandler.setWelcomeFiles(new String[]{"idenx.html"});
        resourceHandler.setResourceBase(".");
        HandlerList handlers = new HandlerList();
        handlers.setHandlers(new Handler[]{resourceHandler, new DefaultHandler()});
        server.setHandler(handlers);
        server.start();
        server.join();
    }
}

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

7.內置connectors

在上面的例子中,server實例都會綁定一個端口並且創建一個默認的connector來監聽這個端口。但是,在內置jetty中,自定義一個或者多個connetor是很常見的。

7.1一個connector

public class OneConnector {
    public static void main(String[] args) throws Exception{
        Server server = new Server();
        ServerConnector http = new ServerConnector(server);
        http.setHost("localhost");
        http.setPort(8090);
        http.setIdleTimeout(30000);
        server.addConnector(http);
        server.setHandler(new HelloHandler());
        server.start();
        server.join();
    }
}

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

7.2多connector

當配置多connector的時候,最好是多個connector享用相同的配置信息。為了實現這個你需要明確的指定serverConnector的配置,使用的是ConnectionFactory這個實例。

8內置servlets

servlet是讓應用程序通過邏來處理請求的標准的方式。servlet和handler很相似。servlet在jetty中是被ServletHandler處理的。它使用標准的路徑映射到一個servlet。

下面的代碼創建了一個ServletHandler並且配置了一個簡單的HelloServlet:

public class MinimalServlets {
    public static void main(String[] args) throws Exception{
        Server server = new Server(8090);
        ServletHandler handler = new ServletHandler();
        server.setHandler(handler);
        // 需要注意的是,這是個原生的servlet,你可以通過web.xml或者@WebServlet來配置
        handler.addServletWithMapping(HelloServlet.class,"/*");
        server.start();
        server.join();
    }
}
class HelloServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.setStatus(HttpServletResponse.SC_OK);
        resp.getWriter().println("<h1>hello from HelloServlet</h1>");
    }
}


免責聲明!

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



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