嵌入式jetty

12年前

本文主要讲述如何使用嵌入式jetty,创建http/https服务器.

一.   相关jar包

Jetty-server
Jetty-servlet

二.创建方式

2.1)最简单的

Server server = new Server(8080);  server.start();  server.join();


创建一个jetty server,并启动,这样我们就创建了一个最简单的http服务器,检查8080端口为监听状态, 但是很明显,该服务器不会对客户端请求有任何响应.

2.2)HANDLER

1)实现

从实现上来看, jetty server本身就是一个HandlerWrapper, 可以通过为server设置handler,处理客户端的请求.

Server server = new Server(8080);  server.setHandler(new HelloHandler());  server.start();  server.join();

通过扩展AbstractHandler类, 实现handle方法, 定义用户自己的handler, 例如:

public class HelloHandler 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("</pre><h1>Hello World</h1><pre>");      }  }

2)测试

浏览器上输入:

http://localhost:8080

输出:

<h1>Hello World</h1>

2.3) SERVLET

直接为Server设置Handler,我们无法针对不同的URL Path,完成不同的处理逻辑, 例如,
当浏览器输入如下URL时,服务器区别处理:

http://localhost:8080/*    http://localhost:8080/TYPE1/*    http://localhost:8080/TYPE2/*

1)实现

Server添加ServletContextHandler,然后,针对不同的path, 设置对应的Servlet来处理.

Server server = new Server(8080);  ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);  context.setContextPath("/");  server.setHandler(context);  context.addServlet(new ServletHolder(new HelloServlet()), "/*");  context.addServlet(new ServletHolder(new HelloServlet("TYPE1 Request")), "/TYPE1/*");  context.addServlet(new ServletHolder(new HelloServlet("TYPE2 Request")), "/TYPE2/*");  server.start();  server.join();


通过扩展HttpServlet,覆盖doPost或者doGet方法,定义用户自己的Servlet,例如:

public class HelloServlet extends HttpServlet {      String greeting = "Hello";      public HelloServlet() {      }         public HelloServlet(String hi) {          greeting = hi;      }         @Override      protected void doGet(HttpServletRequest request,      HttpServletResponse response) throws ServletException, IOException {          response.setContentType("text/html");          response.setStatus(HttpServletResponse.SC_OK);          response.getWriter().println("</pre><h1>” + greeting + "</h1><pre>");      }         @Override      protected void doPost(HttpServletRequest request,      HttpServletResponse response) throws ServletException, IOException {          doGet(request, response);      }  }


2)测试

浏览器上输入:

http://localhost:8080/*    http://localhost:8080/TYPE1/*    http://localhost:8080/TYPE2/*

分别输出:

 <h1>Hello</h1>   <h1>TYPE1 Request</h1>   <h1>TYPE2 Request<h1>

2.3)Connector

http/https服务器也可以同时在多个端口上提供服务, 这就需要引入Connector

1)实现

如下代码就设置了两个Connector, 一个使用8080端口,另一个使用8888端口:

Server server = new Server();  SelectChannelConnector connector0 = new SelectChannelConnector();  connector0.setPort(8080);  connector0.setMaxIdleTime(30000);  connector0.setRequestHeaderSize(8192);     SelectChannelConnector connector1 = new SelectChannelConnector();  connector1.setPort(8888);  connector1.setMaxIdleTime(30000);  connector1.setRequestHeaderSize(8192);     server.setConnectors(new Connector[] { connector0,connector1 });  server.setHandler(new HelloHandler());  server.start();  server.join();

2)测试

浏览器上输入:

 http://localhost:8080/*

或者

 http://localhost:8888/*

三.https服务器

本节着重讲述如何创建https服务器.

3.1)KEYSTORE

使用keytool命令,创建keystore. 例如:

keytool -keystore zenithKS -alias zenith -genkey -keyalg RSA  Enter keystore password:  Re-enter new password:  What is your first and last name?    [Unknown]:  zenith    What is the name of your organizational unit?    [Unknown]:  zenith    What is the name of your organization?    [Unknown]:  zenith    What is the name of your City or Locality?    [Unknown]:  bj    What is the name of your State or Province?    [Unknown]:  bj    What is the two-letter country code for this unit?    [Unknown]:  cn    Is CN=zenith, OU=zenith, O=zenith, L=bj, ST=bj, C=cn correct? (type "yes" or "no")    [no]:  yes    Enter key password for <zenith>:          (RETURN if same as keystore password):

需要用户输入keystore密码以及key密码,最后,会在当前目录下生成一个zenithKS文件,这就是keystore文件

3.2)SSL CONNECTOR

为jetty Server设置ssl Connector,需要指定keystore路径, keystore密码以及key密码.

Server server = new Server();  SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector();  ssl_connector.setPort(8443);  SslContextFactory cf = ssl_connector.getSslContextFactory();  cf.setKeyStore("D:\\keystores\\zenithKS");  cf.setKeyStorePassword("password");  cf.setKeyManagerPassword("password");  server.addConnector(ssl_connector);  server.start();  server.join();

浏览器上输入:

 https://localhost:8443/*

3.3)HTTPS客户端

HttpClient提供了对SSL的支持, 以下通过扩展HttpClient类实现自动接受证书.

因为这种方法自动接收所有证书,因此存在一定的安全问题,所以在使用这种方法前请仔细考虑您的系统的安全需求。具体的步骤如下:

1) 提供一个自定义的socket factory(test.MySecureProtocolSocketFactory)。这个自定义的类必须实现接口

org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory

在实现接口 的类中调用自定义的

X509TrustManager(test.MyX509TrustManager)

这两个类可以在随本文带的附件中得到

2) 创建一个org.apache.commons.httpclient.protocol.Protocol的实例,指定协议名称和默认的端口号

Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory (), 443);

3) 注册刚才创建的https协议对象

Protocol.registerProtocol("https ", myhttps);

4) 然后按照普通编程方式打开https的目标地址

代码下载:

source

具体请参考:

http://www.blogjava.net/happytian/archive/2007/01/18/94553.html

四.参考资料

http://download.eclipse.org/jetty/stable-7/xref/org/eclipse/jetty/embedded/package-summary.html
http://docs.codehaus.org/display/JETTY/How+to+configure+SSL