内置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>");
    }
}
posted @ 2017-04-20 20:02  dongdone  阅读(2464)  评论(0编辑  收藏  举报