其实不管是tomcat还是jetty,他们在启动的时候要做的事情都差不太多。。。无非就是下面的内容:
(1)创建用于连接的connector,创建线程池,
(2)扫描当前的web程序的部署目录,为他们创建上下文环境,并对他们进行path的路由设置
(3)初始化创建的web程序上下文,这里就包括创建servlet啥的。,初始化linstener啥的。并做好自己的path路由
(4)启动connector,开始监听,整个server开始运行。。。。
好了,接下来来分析一下jetty的启动过程吧,其实启动的过程也要分为好几种的,这里就拿最常用的来说吧,也就是在jetty服务器下同时部署多个webapp,因而jetty需要分别为这些webApp创建他们的context。。
来看启动的代码吧:
- Server server = new Server();
- ContextHandlerCollection contexts = new ContextHandlerCollection();
- server.setHandler(contexts);
-
- SocketConnector connector = new SocketConnector();
- String address = args[0];
- int colon = address.lastIndexOf(':');
-
- if (colon<0) {
- connector.setPort(Integer.parseInt(address));
- } else {
- connector.setHost(address.substring(0,colon));
- connector.setPort(Integer.parseInt(address.substring(colon+1)));
- }
- server.setConnectors(new Connector[]{connector});
-
- if (args.length<3) {
- ContextHandler context = new ContextHandler();
- context.setContextPath(URIUtil.SLASH);
- context.setResourceBase(args.length==1?".":args[1]);
- ServletHandler servlet = new ServletHandler();
- servlet.addServletWithMapping("org.mortbay.jetty.servlet.DefaultServlet", URIUtil.SLASH);
- context.setHandler(servlet);
- contexts.addHandler(context);
- } else if ("-webapps".equals(args[1])) {
- WebAppContext.addWebApplications(server, args[2], WebAppContext.WEB_DEFAULTS_XML, true, true);
- } else if ("-webapp".equals(args[1])) {
- WebAppContext webapp = new WebAppContext();
- webapp.setResourceBase(args[2]);
- webapp.setContextPath(URIUtil.SLASH);
- contexts.addHandler(webapp);
-
- }
-
- server.start();
本身看起来还是很简单的吧,首先是创建一个server对象,然后创建ContextHandlerCollection对象,这个我们在以前说过,它将会用于管理所有的WebAppContext,并对http请求进行路由,将他们交给相应的webAppContext来处理。。然后这里创建了connector对象,貌似默认用的还是之前分析过的SocketConnector,也就是bio的connector,其实这里应该不用他才对,因为毕竟还有性能够好的nio实现的SelectChannelConnector。。。。
然后就是设置connector的监听地址,端口一类的信息。。。
对于有多个app的启动,应该是要分析如下的代码:
- WebAppContext.addWebApplications(server, args[2], WebAppContext.WEB_DEFAULTS_XML, true, true);
这里直接调用了一个类方法来进行处理的。。那么我们来看看这个方法是怎么搞的吧:
-
-
- public static void addWebApplications(Server server,
- String webapps,
- String defaults,
- boolean extract,
- boolean java2CompliantClassLoader)
- throws IOException
- {
- addWebApplications(server, webapps, defaults, __dftConfigurationClasses, extract, java2CompliantClassLoader);
- }
这里传进来的server对象就是前面创建的server对象,webapps是我们用来存放app代码的地方,待会将会扫描这个目录,然后为这些app创建webAppContext,default是默认的jetty服务器的配置文件路径,extract表示是否要解压war包,
好了这里依然是调用了一个类方法来执行的。。接下去看吧:
- public static void addWebApplications(Server server,
- String webapps,
- String defaults,
- String[] configurations,
- boolean extract,
- boolean java2CompliantClassLoader)
- throws IOException {
-
-
- HandlerCollection contexts = (HandlerCollection)server.getChildHandlerByClass(ContextHandlerCollection.class);
- if (contexts==null) {
- contexts = (HandlerCollection)server.getChildHandlerByClass(HandlerCollection.class);
- }
-
- addWebApplications(contexts,webapps,defaults,configurations,extract,java2CompliantClassLoader);
- }
这个好像比较囧,。其实主要是后去了ConextHandlerCollection对象,然后再进行下一步的动作。。好吧。
- public static void addWebApplications(HandlerContainer contexts,
- String webapps,
- String defaults,
- String[] configurations,
- boolean extract,
- boolean java2CompliantClassLoader)
- throws IOException
- {
- Log.warn("Deprecated configuration used for "+webapps);
- WebAppDeployer deployer = new WebAppDeployer();
- deployer.setContexts(contexts);
- deployer.setWebAppDir(webapps);
-
-
-
-
-
-
-
- deployer.setConfigurationClasses(configurations);
- deployer.setExtract(extract);
- deployer.setParentLoaderPriority(java2CompliantClassLoader);
- try
- {
- deployer.start();
- }
- catch(IOException e)
- {
- throw e;
- }
- catch(Exception e)
- {
- throw new RuntimeException(e);
- }
- }
这段代码就稍微有一些干货了。。这里可以看到,创建了一个WebAppDeployer对象,这个我们可以将其理解为一个工具类,那些app的部署的事情就交给它去做了。。。
为其设置了ContextHandlerCollection,然后设置了当前app所在的根目录,并且这只了app启动时候用到的配置类型。。。。然后再执行它的start方法。。。
好了,接下来的事情就是扫描app的目录,然后为他们创建WebAppContext,并对他们进行初始化的一些工作了。。。这里就先停住吧。。。毕竟这个是app的创建和启动,而不是server的启动。。
那么回归到最开始的代码来看看server的start过程吧:
- protected void doStart() throws Exception
- {
- Log.info("jetty-"+_version);
- HttpGenerator.setServerVersion(_version);
- MultiException mex=new MultiException();
-
-
- for (int i=0;_realms !=null && i<_realms.length; i++) {
- if (_realms[i] instanceof LifeCycle) {
- ((LifeCycle)_realms[i]).start();
- }
- }
-
- Iterator itor = _dependentLifeCycles.iterator();
- while (itor.hasNext()) {
- try{
- ((LifeCycle)itor.next()).start();
- }
- catch (Throwable e) {mex.add(e);}
- }
-
-
- if (_threadPool==null) {
- QueuedThreadPool tp=new QueuedThreadPool();
- setThreadPool(tp);
- }
-
-
- if (_sessionIdManager!=null) {
- _sessionIdManager.start();
- }
-
- try {
-
- if (_threadPool instanceof LifeCycle)
- ((LifeCycle)_threadPool).start();
- }
- catch(Throwable e) { mex.add(e);}
-
- try {
- super.doStart();
- }
- catch(Throwable e)
- {
- Log.warn("Error starting handlers",e);
- }
-
- if (_connectors!=null) {
- for (int i=0;i<_connectors.length;i++) {
- try{_connectors[i].start();}
- catch(Throwable e){
- mex.add(e);
- }
- }
- }
- mex.ifExceptionThrow();
- }
这里部分虽然看起来代码还挺多的。。不过最主要的就是要干如下的三件事情。。
(1)创建线程池,并且启动
(2)启动内部的handler,其实也就是启动那个contextHandlerCollection,这个handler的启动将会设置WebAppContext的路由设置,以及对WebAppContext的启动。。进而使一些contextListener的启动,servlet的初始化一系列的事情。。
(3)启动connector,它已启动,那么就代表整个server已经开始正常的运行了。。。
另外我们再来看看server对象的一个重要方法吧:
-
-
-
-
-
-
- public void handle(HttpConnection connection) throws IOException, ServletException
- {
- String target=connection.getRequest().getPathInfo();
- if (Log.isDebugEnabled()) {
- Log.debug("REQUEST "+target+" on "+connection);
- handle(target, connection.getRequest(), connection.getResponse(), Handler.REQUEST);
- Log.debug("RESPONSE "+target+" "+connection.getResponse().getStatus());
- } else {
-
-
- handle(target, connection.getRequest(), connection.getResponse(), Handler.REQUEST);
- }
- }
从上面的注释就可以知道,每一个httpConnection当收到了http请求之后都会调用server的这个方法来处理。。而其实这个方法最终又是交给内部的ContextHandlerCollection来处理这个请求。。。
接下来再由ContextHandlerCollection将这个请求路由给对应的WebAppContext,然后再由其路有个内部的servlet来处理。。。
那么到这里为止真个jetty的server的创建和启动就差不多了。。。还是蛮简单的。。。。