Jetty 是一个轻量级的、开源的servlet容器,可以非常容易的嵌入到应用程序当中作为嵌入式服务器使用,下面我们从代码层面来看看它是如何启动的
Jetty的启动从Server类的start()方法开始的,Server类继承了AbstractLifeCycle类,会首先执行AbstractLifeCycle的start()方法.方法如下:
public final void start() throws Exception { synchronized (_lock) { try { if (_state == STARTED || _state == STARTING) return; setStarting();//启动之前调用监听器 doStart();//启动jetty Log.debug("started {}",this); setStarted();//启动之后调用监听器 } catch (Exception e) { setFailed(e); throw e; } catch (Error e) { setFailed(e); throw e; } } }
doStart()方法在Server类中.如下:
/* ------------------------------------------------------------ */ 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(); }
这里面启动了处理请求的线程和Session管理器,还有连接器,super.doStart()调用了HandlerWrapper类的doStart()方法,如下:
protected void doStart() throws Exception { if (_handler!=null) _handler.start(); super.doStart(); }
_handler.start()调用了AbstractLifeCycle的start()方法,同上面,AbstractLifeCycle里面的start()方法会调用
WebAppContext的doStart()方法,如下:
protected void doStart() throws Exception { try { // 初始化四个类WebInfConfiguration,WebXmlConfiguration, JettyWebXmlConfiguration,TagLibConfiguration
loadConfigurations(); for (int i=0;i<_configurations.length;i++) _configurations[i].setWebAppContext(this); // Configure classloader _ownClassLoader=false; if (getClassLoader()==null) { WebAppClassLoader classLoader = new WebAppClassLoader(this); setClassLoader(classLoader);//生成classloader加载应用的war _ownClassLoader=true; } if (Log.isDebugEnabled())//打印日志 { ClassLoader loader = getClassLoader(); Log.debug("Thread Context class loader is: " + loader); loader=loader.getParent(); while(loader!=null) { Log.debug("Parent class loader is: " + loader); loader=loader.getParent(); } } for (int i=0;i<_configurations.length;i++) _configurations[i].configureClassLoader();//WebInfConfiguration类加载war包的lib,classes目录
getTempDirectory(); if (_tmpDir!=null && !_isExistingTmpDir && !isTempWorkDirectory()) { File sentinel = new File(_tmpDir, ".active"); if(!sentinel.exists()) sentinel.mkdir(); } super.doStart(); if (isLogUrlOnStart()) dumpUrl(); } catch (Exception e) { //start up of the webapp context failed, make sure it is not started Log.warn("Failed startup of context "+this, e); _unavailableException=e; _unavailable = true; } }
WebInfConfiguration类的configureClassLoader()方法如下:
public void configureClassLoader() throws Exception { //cannot configure if the context is already started if (_context.isStarted()) { if (Log.isDebugEnabled()){Log.debug("Cannot configure webapp after it is started");} return; } Resource web_inf=_context.getWebInf();//生成临时目录将war拷过来 // Add WEB-INF classes and lib classpaths if (web_inf != null && web_inf.isDirectory() && _context.getClassLoader() instanceof WebAppClassLoader) { // Look for classes directory Resource classes= web_inf.addPath("classes/"); if (classes.exists()) ((WebAppClassLoader)_context.getClassLoader()).addClassPath(classes.toString()); // Look for jars Resource lib= web_inf.addPath("lib/"); if (lib.exists() || lib.isDirectory()) ((WebAppClassLoader)_context.getClassLoader()).addJars(lib); } }
WebAppContext的start()方法里的 super.doStart()会调用ContextHandler的doStart()方法,方法如下:
protected void doStart() throws Exception { if (_contextPath==null) throw new IllegalStateException("Null contextPath"); _logger=Log.getLogger(getDisplayName()==null?getContextPath():getDisplayName()); ClassLoader old_classloader=null; Thread current_thread=null; SContext old_context=null; _contextAttributes=new AttributesMap(); try { // Set the classloader if (_classLoader!=null) { current_thread=Thread.currentThread(); old_classloader=current_thread.getContextClassLoader(); current_thread.setContextClassLoader(_classLoader); } if (_mimeTypes==null) _mimeTypes=new MimeTypes(); old_context=(SContext)__context.get(); __context.set(_scontext); if (_errorHandler==null) setErrorHandler(new ErrorHandler()); startContext(); } finally { __context.set(old_context); // reset the classloader if (_classLoader!=null) { current_thread.setContextClassLoader(old_classloader); } } }
startContext()方法会调用WebAppContext类的startContext()方法,如下:
protected void startContext() throws Exception { // Configure defaults for (int i=0;i<_configurations.length;i++) _configurations[i].configureDefaults();//调用WebXmlConfiguration类解析xml文件
// Is there a WEB-INF work directory Resource web_inf=getWebInf(); if (web_inf!=null) { Resource work= web_inf.addPath("work"); if (work.exists() && work.isDirectory() && work.getFile() != null && work.getFile().canWrite() && getAttribute(ServletHandler.__J_S_CONTEXT_TEMPDIR) == null) setAttribute(ServletHandler.__J_S_CONTEXT_TEMPDIR, work.getFile()); } // Configure webapp for (int i=0;i<_configurations.length;i++) _configurations[i].configureWebApp(); super.startContext(); }
super.startContext()调用父类Context的startContext()方法,如下:
protected void startContext() throws Exception { super.startContext();//初始化xml里配置的listener // OK to Initialize servlet handler now if (_servletHandler != null && _servletHandler.isStarted()) _servletHandler.initialize();//初始化xml里面配置的servlet }