|
Jetty不只是个性能优秀的web服务器,还能作为插件供我们开发使用,下面就简单接触一下,我下载的jetty版本是8.1.8版本。最新版9.0.0的api相比8.1.8有不小改动,出于了解学习的目的就随便找个来用。
“从一万里高空看Jetty”就是下面这个架构
Connector
|
|
Server — — ThreadPool
|
|
Handler
Connector负责前端请求的接受,handler负责后台处理,同时维持一个threadpool线程池供服务器调用。
Connector分下面几种
1,SelectChannelConnector
使用高效的NIO模型以及非阻塞线程模型接收request。
当使用coninuations时,线程不会阻塞等待,当一个filter或者servlet在continuation调用getEvent时,会抛出
一个运行时异常,Jetty捕获这个异常但并不响应给客户端,而是释放线程然后将continuation放回时间片队列。当continuation超时或者
有事件发生时,Jetty申请一个线程去继续处理改请求。
2,SocketConnector
传统的阻塞IO以及线程模型,为每个连接开启一个线程去处理,当环境不支持NIO时使用这个
3,SslSelectChannelConnector(支持ssl协议的NIO模型)
4,SslSocketConnector(支持ssl协议的阻塞IO模型)
5,Ajp13SocketConnector(支持AJP13协议,官方wiki上建议使用普通的HTTP connector)
Handler是Jetty的一个组件用来处理接收到的请求,核心api就是handle方法
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
target——请求的目标,一般是URI(某些场景下为资源名称或者资源URI)
baseRequest——原始的请求对象
request——request或者它的一个包装
response——response或者它的一个包装
只要实现这个方法,就可以处理请求,或者将请求传递给别的handler(or servlet),或者包装改请求,所以有三类handlers
1,Coordinating Handlers : HandlerCollection , ContextHandlerCollection
将请求路由到别的handlers。
2,Filtering Handlers : HandlerWrapper , ContextHandler , SessionHandler
包装补充请求并传递给别的handlers
如:
try
{
base_request.setSession(a_session);
next_handler.handle(target,request,response,dispatch);
}
finally
{
base_request.setSession(old_session);
}
3,Generating Handlers : ResourceHandler , ServletHandler
产生content内容
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("<h1>Hello OneHandler</h1>");
//如果不想请求再被别的handler处理,则处理方式如下
base_request.setHandled(true);
handler的调用方法:顺序调用,嵌套调用
顺序调用(各个Handlers的行为不受调用顺序和下一个调用的影响,独立处理request产生response)
Caller --> Handler 1
Caller --> Handler 2
Caller --> User Code
Caller --> Handler 3
嵌套调用(更加常用)
Caller --> Handler 1
Handler 1 --> Handler 2
Handler 2 --> User Code
关于Jetty的架构更多参考 : http://wiki.eclipse.org/Jetty/Reference/Jetty_Architecture
下面写一个简单的程序测试,集成Jetty的步骤如下:
1,Create the server
2,Add/Configure Connectors(线程池的线程数目不可太小,不然会启动失败)
3,Add/Configure Handlers
4,Add/Configure Servlets/Webapps to Handlers
5,Start the server
6,Wait(join the server to prevent main exiting)
package test;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.server.handler.*;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
public class PJetty 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 {
//Set connectors
SelectChannelConnector connector1 = new SelectChannelConnector();
connector1.setPort(1987);
connector1.setThreadPool(new QueuedThreadPool(20));
//request per second : 4207.30 [#/sec] (mean)
SocketConnector connector2 = new SocketConnector();
connector2.setPort(1988);
connector2.setName("jetty");
//request per second : 4166.46 [#/sec] (mean)
Server server = new Server();
server.setConnectors(new Connector[]{connector1,connector2});
//server.setHandler(new PJetty());
//Set handlers
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{new PJetty(), new DefaultHandler()});
server.setHandler(handlers);
server.start();
server.join();
}
}
编译运行方法如下:
root # export CLASSPATH=$CLASSPATH:/pwd/to/jetty/lib/
root # javac -classpath .:* test/PJetty.java
root # java -cp .:* test/PJetty
2012-12-18 14:09:51.789:INFO:oejs.Server:jetty-8.1.8.v20121106
2012-12-18 14:09:51.865:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:1987
2012-12-18 14:09:51.866:INFO:oejs.AbstractConnector:Started SocketConnector@0.0.0.0:1988 |
|
|