Java web app 启动过程浅析
As we all know,Java web 应用和普通应用程序不大一样,普通应用程序启动很好理解,main 方法就是程序执行的入口,但是 web 应用是没有main这个入口方法的,web 应用需要在容器(container)中运行。这里的容器是指context 容器。
1、context container
Java web 应用需要在container才能运行,这里使用tomcat进行讲解。
把应用放在baseApp指向的目录下,一个应用对应一个context container,context container 管理servlet ,其实就是servlet container。当我们启动或者停止应用时,会触发ServletContextEvent事件,交由 javax.servlet 中的ServletContextListener 对象处理,事实上它监听的是context的生命周期,也就是整个应用的生命周期,它定义了两个方法:
public void contextInitialized(ServletContextEvent sce);在容器启动时调用,调用完成后,容器继续初始化listener、filter、以及on startup 大于0的servlet。
public void contextDestroyed(ServletContextEvent sce);在容器关闭时调用,调用该方法之前,先销毁servlet、filter、listener,小会完成之后,调用该方法
分别在web容器启动和停止时调用。
在tomcat创建context container的时候,会把servletConfig 加入到servletContext中,servletConfig主要负责web应用配置的解析工作,并把相应的配置放在servletContext中。servletContext为整个web应用提供的一块共享内存,应用内的任何请求都可以访问里面的内容,其实就是ApplicationContext,整个应用内可见,生命周期和应用的生命周期相同。以下是tomcat addWebapp方法的代码:
public Context addWebapp(Host host, String url, String path) {
silence(url);
Context ctx = new StandardContext();
ctx.setPath( url );
ctx.setDocBase(path);
if (defaultRealm == null) {
initSimpleAuth();
}
ctx.setRealm(defaultRealm);
ctx.addLifecycleListener(new DefaultWebXmlListener());
ContextConfig ctxCfg = new ContextConfig();
ctx.addLifecycleListener(ctxCfg);
ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML");
if (host == null) {
getHost().addChild(ctx);
} else {
host.addChild(ctx);
}
return ctx;
}
至于ServletContext定义了servletContext的规范,主要的功能可以通过方法名判断出来,比如
setAttribute,addServlet,addFilter,addListener,getRequestDispatcher,getResource。想要理解web app的流程和功能,首先就是要理解j2ee的各种规范。
2、web.xml
web的初始化工作是由servletConfig负责,主要的始化是对web.xml中的配置进行解析。web.xml可视为整个web应用的入口文件。
web.xml加载的顺序为:context-param -> listener -> filter -> servlet。同类型则按照定义顺序进行加载初始化。对于context param,servletConfig会将配置信息加载到servletContext中。在web应用中,servlet和servletConfig是同一个对象,spring的DispatchServlet是HttpServlet的子类,HttpServlet是GenericServlet的子类。
GenericServlet的定义如下:public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable
从应用启动到处理请求,再到停止应用的整个过程大致的过程是这样的:
启动:
>创建standard container
>设置stand container的基本属性(path,url等)
>将stand container加入到Host中
>创建context config
>omcat conf目录下的web.xml配置
>加载项目WEB-INFO目录下的web.xml
>解析web.xml,将context-param的信息设置到context container中
>创建url和servlet的映射关系表(mapping table)
>注册并初始化listener、filter
>加载on load 值大于0的servlet
>向ServletContextListener发送启动事件(ServletContextEvent)
>....
请求处理:
>过滤器进行请求过滤
>经过监听器和过滤器之后,container根据请求的方法和path信息,在web.xml中找到对应的servlet
>检查servlet是否被加载,如果没有加载,则加载
>加载完成之后,调用servlet 的init()方法进行初始化
>根据请求类型,找对应的do方法(eg:doGet doPost)进行处理
>......
停止:
>container等待正在处理的请求,拒绝新的请求
>container向ServletContextListener发送停止事件(ServletContextEvent)
>container调用destroy方法销毁依次销毁servlet,filter,listener
>将container从Host中移除
>销毁container
总结
想要理解java web app的启动过程,必须先了解java ee的规范,同时,这个也是理解spring mvc的重要前提。
https://www.cnblogs.com/gy19920604/p/5377766.html
https://blog.csdn.net/u014431852/article/details/47042895
https://www.ibm.com/developerworks/cn/java/j-lo-servlet/index.html