Jetty学习【一】 Jetty的嵌入式使用

来源:互联网 发布:网络交流的特点 编辑:程序博客网 时间:2024/05/17 05:08

文中的例子多参考官网,并且做一定讲解和扩展。

1、使用Handler处理HTTP消息

以下的例子出自官网,作为入门十分合适。
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.ServletException; import java.io.IOException; import org.eclipse.jetty.server.Server;import org.eclipse.jetty.server.Request;import org.eclipse.jetty.server.handler.AbstractHandler; public class HelloWorld extends AbstractHandler{    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();    }}

打开浏览器输入http://localhost:8080/,可以看到如下效果,

熟悉Servlet的人看到这段代码都会觉得很熟悉。因为这里的AbstractHandler和Servlet十分相似,而handle函数其实就相当于Servlet中的doGet和doPost函数,并且都有类型为HttpServletRequest的request和response作为参数。接下来让我们把上面的例子变得复杂一些,前面的例子只使用到了response,这里我们把request也用上。
    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);        String str = request.getParameter("str");        String retStr = "<h1>" + (str == null ? "Hello World" : str) + "</h1>";        response.getWriter().println(retStr);    }

上面代码完成的功能是,如果请求的地址中带有参数str,则返回的网页打印出str对应的值,否则打印Hello World。
handle中的参数target表示,与web根目录相对应的地址。比如输入localhost:8080/abc?str=def,则target对应的值就是/abc,而在页面上会打印出def。
handle中的参数baseRequest,表示未封装的request。其定义如下
public class Request implements HttpServletRequest

2、文件服务器1

所谓文件服务器,也就是可以浏览web应用所在的服务器中指定路径的文件,并且下载。
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;import org.eclipse.jetty.server.nio.SelectChannelConnector;public class FileServer{    public static void main(String[] args) throws Exception    {        Server server = new Server();        SelectChannelConnector connector = new SelectChannelConnector();        connector.setPort(8080);        server.addConnector(connector);         ResourceHandler resource_handler = new ResourceHandler();        resource_handler.setDirectoriesListed(true);        resource_handler.setWelcomeFiles(new String[]{ "index.html" });         resource_handler.setResourceBase("F:\\源码学习");         HandlerList handlers = new HandlerList();        handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });        server.setHandler(handlers);         server.start();        server.join();    }}

运行上面的程序,可以看到如下效果

在官网的例子中,resource_handler.setResourceBase("."),表示设置文件浏览的根目录为当前工程对应的目录。如果观察仔细,可以发现第一个例子中,只设置了一个Handler,而这个例子中设置了一个HandlerList。下面来看看官网上是怎么说的。

  • A HandlerCollection holds a collection of other handlers and calls each handler in order. This is useful for combining statistics and logging handlers with the handler that generates the response.(HandlerCollection拥有多个Handler,并且依次调用这些Handler。这样的好处是,可以把统计Handler,日志Handler和产生响应的Handler联合起来使用
  • A HandlerList is a Handler Collection that calls each handler in turn until either an exception is thrown, the response is committed or the request.isHandled() returns true. It can be used to combine handlers that conditionally handle a request.(HandlerList是一个Handler集合,它依次r执行各个Handler,知道异常抛出或者response被返回或者request.isHanled()返回true。它能使Handler联合起来有条件的处理一个请求。
  • A HandlerWrapper is a handler base class that can be used to daisy chain handlers together in the style of aspect-oriented programming. For example, a standard web application is implemented by a chain of a context, session, security and servlet handlers.(HandlerWrapper是一个完美的将各个Handler串联起来,并且将这些Handler应用在面向切面编程的基础类。例如,一个标准的web应用由一连串的context, session, security和servlet Handler组成
  • ContextHandlerCollection uses the longest prefix of the request URI (the contextPath) to select a specific ContextHandler to handle the request.(根据请求的URI使用最大前缀匹配,选择出一个合适的ContextHandler处理这个请求。


    通过上面的描述可以看出HandleList的工作原理,如果输入的路径是http://localhost:8080/abc,则会调用DefaultHandler进行处理(DefaultHandler返回的页面是404)。

    /* ------------------------------------------------------------ *//** Default Handler. *  * This handle will deal with unhandled requests in the server. * For requests for favicon.ico, the Jetty icon is served.  * For reqests to '/' a 404 with a list of known contexts is served. * For all other requests a normal 404 is served. * TODO Implement OPTIONS and TRACE methods for the server. *  *  * @org.apache.xbean.XBean */public class DefaultHandler extends AbstractHandler

    3、文件服务器2

    除了使用代码生成文件服务器外,还可以通过xml进行配置,读取xml生成文件服务器

    xml的配置如下

    <?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd"> <Configure id="FileServer" class="org.eclipse.jetty.server.Server">     <Call name="addConnector">      <Arg>          <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">            <Set name="port">8080</Set>          </New>      </Arg>    </Call>     <Set name="handler">      <New class="org.eclipse.jetty.server.handler.HandlerList">        <Set name="handlers">  <Array type="org.eclipse.jetty.server.Handler">    <Item>      <New class="org.eclipse.jetty.server.handler.ResourceHandler">        <Set name="directoriesListed">true</Set><Set name="welcomeFiles">  <Array type="String"><Item>index.html</Item></Array></Set>        <Set name="resourceBase">F:\源码学习</Set>      </New>    </Item>    <Item>      <New class="org.eclipse.jetty.server.handler.DefaultHandler">      </New>    </Item>  </Array>        </Set>      </New>    </Set></Configure>

    java代码如下

    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;import org.eclipse.jetty.util.resource.Resource;import org.eclipse.jetty.xml.XmlConfiguration;public class FileServer{    public static void main(String[] args) throws Exception    {        Resource fileserver_xml = Resource.newSystemResource("fileserver.xml");        XmlConfiguration configuration = new XmlConfiguration(fileserver_xml.getInputStream());        Server server = (Server)configuration.configure();        server.start();        server.join();    }}

    得到的效果与例子2中一样。

    4、设置Context处理请求


    所谓通过设置Context获取请求,是指通过ContextHandler来设置可以匹配的web路径,只有当请求的路径和设置的web路径相匹配时才进行处理,否则不进行处理。
    import org.eclipse.jetty.server.Server;import org.eclipse.jetty.server.handler.ContextHandler;public class ContextHolder{    public static void main(String[] args) throws Exception    {        Server server = new Server(8080);         ContextHandler context = new ContextHandler();        context.setContextPath("/hello");        context.setResourceBase(".");        context.setClassLoader(Thread.currentThread().getContextClassLoader());        server.setHandler(context);         context.setHandler(new HelloWorld());         server.start();        server.join();    }}

    只有当浏览器输入http://localhost:8080/hello/,http://localhost:8080/hello/abc,http://localhost:8080/hello/?a=c这种满足/hello的路径时才会进行处理,而输入http://localhost:8080则会出现404页面。

    5、设置ServletContext处理请求

    与Context相类似,ServletContext可以将定义好的Servlet放置到其中,然后根据输入路径的不同,匹配不同的Servlet进行处理。

    import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class HelloServlet extends HttpServlet{    private String greeting="Hello World";    public HelloServlet(){}    public HelloServlet(String greeting)    {        this.greeting=greeting;    }    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException    {        response.setContentType("text/html");        response.setStatus(HttpServletResponse.SC_OK);        response.getWriter().println("<h1>"+greeting+"</h1>");        response.getWriter().println("session=" + request.getSession(true).getId());    }}

    import org.eclipse.jetty.server.Server;import org.eclipse.jetty.servlet.ServletContextHandler;import org.eclipse.jetty.servlet.ServletHolder;public class ServletContextHolder{    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(new ServletHolder(new HelloServlet()),"/*");        HelloServlet servlet1 = new HelloServlet("print hello1");        context.addServlet(new ServletHolder(servlet1),"/hello1/*");        HelloServlet servlet2 = new HelloServlet("print hello2");        context.addServlet(new ServletHolder(servlet2),"/hello2/*");         server.start();        server.join();    }}
    上面的代码中设置了根路径为/,两个子路径为/hello1/*,/hello2/*,满足这两个子路径的请求将分别调用servlet1和servlet2进行处理,否则同意调用默认的new HelloServlet()进行处理。

    ServletHolder用于保存Servlet,

    /* --------------------------------------------------------------------- *//** Servlet Instance and Context Holder. * Holds the name, params and some state of a javax.servlet.Servlet * instance. It implements the ServletConfig interface. * This class will organise the loading of the servlet when needed or * requested. * *  */public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope, Comparable

    6、设置WebAppContext处理请求

    有些情况下,web应用迁移到jetty上,而且web应用已经打好包,如果解压,然后将jetty迁入其中太麻烦。jetty提供了一种机制,直接加载war包。
    import org.eclipse.jetty.server.Server;import org.eclipse.jetty.webapp.WebAppContext;public class WebAppContextHolder{    public static void main(String[] args) throws Exception    {         Server server = new Server(8080);         WebAppContext webapp = new WebAppContext();        webapp.setContextPath("/");        webapp.setWar("C:\\Users\\xxxx\\Desktop\\HelloWorld.war");        server.setHandler(webapp);         server.start();        server.join();    }}

    当然也会存在web应用还在开发中,然后将jetty集成进来的情况,这种情况下web应用还未打包。
    import org.eclipse.jetty.server.Server;import org.eclipse.jetty.webapp.WebAppContext;public class WebAppContextHolder{    public static void main(String[] args) throws Exception    {        Server server = new Server(8080);                WebAppContext context = new WebAppContext();        context.setDescriptor("/WEB-INF/web.xml");        context.setResourceBase("../test-jetty-webapp/src/main/webapp");        context.setContextPath("/");        context.setParentLoaderPriority(true);         server.setHandler(context);         server.start();        server.join();    }}

    这种情况下,只需要指定对应web.xml和对应的应用路径就可以了。

    7、混合使用上面的几种模式

    使用ContextHandlerCollection可以将多中类型的Handler融合在一起(ServletContextHandler, WebAppContextHandler, ContextHandler)。每个不同的Handler对应一个子应用。
    import org.eclipse.jetty.server.Handler;import org.eclipse.jetty.server.Server;import org.eclipse.jetty.server.handler.ContextHandlerCollection;import org.eclipse.jetty.servlet.ServletContextHandler;import org.eclipse.jetty.servlet.ServletHolder;import org.eclipse.jetty.webapp.WebAppContext;public class ManyContextHolder{    public static void main(String[] args) throws Exception    {        Server server = new Server(8080);         ServletContextHandler context0 = new ServletContextHandler(ServletContextHandler.SESSIONS);        context0.setContextPath("/ctx0");        context0.addServlet(new ServletHolder(new HelloServlet()),"/*");        HelloServlet servlet1 = new HelloServlet("print hello1");        context0.addServlet(new ServletHolder(servlet1),"/hello1/*");        HelloServlet servlet2 = new HelloServlet("print hello2");        context0.addServlet(new ServletHolder(servlet2),"/hello2/*");                WebAppContext webapp = new WebAppContext();        webapp.setContextPath("/ctx1");        webapp.setWar("C:\\Users\\xxxx\\Desktop\\HelloWorld.war");         ContextHandlerCollection contexts = new ContextHandlerCollection();        contexts.setHandlers(new Handler[] { context0, webapp });         server.setHandler(contexts);         server.start();        server.join();    }}

    分别定义了两个根路径/ctx0,和/ctx1,分别对应不同的web应用。

  • 0 0
    原创粉丝点击