1、使用Digester解析Web.xml文件
2、把解析出来的<Servlet>节点对象,转成Servlet的包装器StandardWrapper
3、把StandardWrapper添加到父节点StandardContext
4、管道链末尾实例化Servlet对象、并执行init方法和service方法
class org.apache.catalina.startup.ContextConfig{
protected void webConfig() {
// -----------------------------------------
// 1、使用Digester解析Web.xml文件
// -----------------------------------------
WebXml webXml = createWebXml();
// 取得输入流 "d:/a/b/c/tomcat/webapps/dir1/WEB-INF/web.xml"
InputSource contextWebXml = getContextWebXmlSource();
if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) { // 解析文件 ,数据存入webXml
ok = false;
}
// 使用 org.apache.jasper.servlet.JspServlet 包装 <jsp-file>/a/b/c/file.jsp</jsp-file>的文件
convertJsps(webXml);
// context === org.apache.catalina.core.StandardContext
// 把解析处理的内容设置到 context 中 ,如:context.addFilterMap(filterMap);
configureContext(webXml); //!!!!!
}
private void configureContext(WebXml webxml) {
// -----------------------------------------
// 2、把解析出来的<Servlet>节点对象,转成Servlet的包装器StandardWrapper
// -----------------------------------------
// servlet === org.apache.tomcat.util.descriptor.web.ServletDef
for (ServletDef servlet : webxml.getServlets().values()) { // 添加Servlet对象
// org.apache.catalina.core.StandardContext.createWrapper();
// 创建org.apache.catalina.core.StandardWrapper对象
// 给wrapper添加生命周期监听器
// 给wrapper添加容器监听器
Wrapper wrapper = context.createWrapper();
// Description is ignored
// Display name is ignored
// Icons are ignored
// jsp-file gets passed to the JSP Servlet as an init-param
if (servlet.getLoadOnStartup() != null) {
wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
}
if (servlet.getEnabled() != null) {
wrapper.setEnabled(servlet.getEnabled().booleanValue());
}
wrapper.setName(servlet.getServletName()); // servlet的名称
Map<String,String> params = servlet.getParameterMap(); // Servlet的属性
for (Entry<String, String> entry : params.entrySet()) {
wrapper.addInitParameter(entry.getKey(), entry.getValue());
}
wrapper.setRunAs(servlet.getRunAs());
Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs();
for (SecurityRoleRef roleRef : roleRefs) {
wrapper.addSecurityReference(
roleRef.getName(), roleRef.getLink());
}
wrapper.setServletClass(servlet.getServletClass()); // Servlet的类名
//servlet === org.apache.tomcat.util.descriptor.web.ServletDef
// 设置文件上传的配置
// <web-app>
// <servlet>
// <multipart-config>
// <!-- 50MB max -->
// <max-file-size>52428800</max-file-size>
// <max-request-size>52428800</max-request-size>
// <file-size-threshold>0</file-size-threshold>
// </multipart-config>
// </servlet>
// </web-app>
MultipartDef multipartdef = servlet.getMultipartDef();
if (multipartdef != null) {
if (multipartdef.getMaxFileSize() != null &&
multipartdef.getMaxRequestSize()!= null &&
multipartdef.getFileSizeThreshold() != null) {
// 设置文件上传的配置
wrapper.setMultipartConfigElement(new MultipartConfigElement(
multipartdef.getLocation(),
Long.parseLong(multipartdef.getMaxFileSize()),
Long.parseLong(multipartdef.getMaxRequestSize()),
Integer.parseInt(
multipartdef.getFileSizeThreshold())));
} else {
// org.apache.catalina.core.StandardWrapper
wrapper.setMultipartConfigElement(new MultipartConfigElement(
multipartdef.getLocation()));
}
}
if (servlet.getAsyncSupported() != null) {
wrapper.setAsyncSupported(
servlet.getAsyncSupported().booleanValue());
}
wrapper.setOverridable(servlet.isOverridable());
// -----------------------------------------
// 3、把StandardWrapper添加到父节点StandardContext
// -----------------------------------------
// context === org.apache.catalina.core.StandardContext
// wrapper === org.apache.catalina.core.StandardWrapper
context.addChild(wrapper);
}
for (Entry<String, String> entry :
webxml.getServletMappings().entrySet()) { // 添加Servlet映射
context.addServletMapping(entry.getKey(), entry.getValue());
}
}
}
// -----------------------------------------
// 4、管道链末尾实例化Servlet对象、并执行相应方法
// -----------------------------------------
class org.apache.catalina.core.StandardContextValve{
public final void invoke(Request request, Response response)
throws IOException, ServletException {
Wrapper wrapper = request.getWrapper(); // Servlet包装器对象org.apache.catalina.core.StandardWrapper
// 执行Servlet请求 !!!! wrapper === org.apache.catalina.core.StandardWrapper
// org.apache.catalina.core.StandardWrapperValve.invoke(request, response);
wrapper.getPipeline().getFirst().invoke(request, response);
}
}
class org.apache.catalina.core.StandardWrapperValve{
public final void invoke(Request request, Response response)
throws IOException, ServletException {
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
// org.apache.catalina.core.StandardContext
Context context = (Context) wrapper.getParent();
// org.apache.catalina.core.StandardWrapper
//!!!!!!!!!
// !!!!! 加载Servlet类,创建Servlet对象,反射Servlet对象内部的注解,如:@Resource声明的资源,并进行依赖注入到Servlet对象中!!!
// !!!!! 调用Servlet对象的init方法
servlet = wrapper.allocate();
// !!! 创建过滤器链条
// Create the filter chain for this request
ApplicationFilterChain filterChain =
ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
// -----------------------------------------
// 4.3、调用Servlet对象的service方法
// -----------------------------------------
// 执行过滤器链!!!! ,Servlet在过滤器链条的末端,过滤器执行后,就调用servlet.service(....)
// org.apache.catalina.connector.RequestFacade
// org.apache.catalina.connector.ResponseFacade
filterChain.doFilter(request.getRequest(), response.getResponse());
filterChain.release(); // 释放过滤器链资源
wrapper.deallocate(servlet); // 释放Servlet资源
if ((servlet != null) &&
(wrapper.getAvailable() == Long.MAX_VALUE)) { // 释放StandardWrapper对象
wrapper.unload();
}
}
}
class org.apache.catalina.core.StandardWrapper{
protected final StandardWrapperFacade facade = new StandardWrapperFacade(this);
public Servlet allocate() throws ServletException {
// !!!!! 加载Servlet类,创建Servlet对象,反射Servlet对象内部的注解,如:@Resource声明的资源,并进行依赖注入到Servlet对象中!!!
// !!!!! 调用Servlet对象的init方法
instance = loadServlet();
}
public synchronized Servlet loadServlet() throws ServletException {
//!!!实例管理器 org.apache.catalina.core.StandardContext
// instanceManager === org.apache.catalina.core.DefaultInstanceManager
InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager();
// -----------------------------------------
// 4.1、实例化Servlet对象
// -----------------------------------------
// 创建Servlet对象,反射Servlet对象内部的注解,如:@Resource声明的资源,并进行依赖注入到Servlet对象中!!!
// 如:servletClass === org.apache.jasper.servlet.JspServlet
// 如:servletClass === org.apache.catalina.servlets.DefaultServlet
// 如: servletClass === cn.java.note.HelloServlet
// 如:servlet === new org.apache.jasper.servlet.JspServlet()
// 如:servlet === new org.apache.catalina.servlets.DefaultServlet()
// 如: servlet === new cn.java.note.HelloServlet()
servlet = (Servlet) instanceManager.newInstance(servletClass);
// 处理Servlet的安全注解
processServletSecurityAnnotation(servlet.getClass());
// Special handling for ContainerServlet instances
if ((servlet instanceof ContainerServlet) &&
(isContainerProvidedServlet(servletClass) ||
((Context) getParent()).getPrivileged() )) {
((ContainerServlet) servlet).setWrapper(this); // 容器Servlet实例,设置对父节点的依赖
}
// 调用Servlet的初始化方法init
initServlet(servlet);
fireContainerEvent("load", this); // 触发容器事件 ContainerListener
}
private synchronized void initServlet(Servlet servlet)
throws ServletException {
// -----------------------------------------
// 4.2、调用Servlet对象的init方法
// -----------------------------------------
// 如:servlet === new org.apache.jasper.servlet.JspServlet()
// 如:servlet === new org.apache.catalina.servlets.DefaultServlet()
// 如: servlet === new cn.java.note.HelloServlet()
// 调用Servlet的初始化方法init
// facade = new StandardWrapperFacade(this);
servlet.init(facade);
}
@Override
public ServletContext getServletContext() {
if (parent == null)
return (null);
else if (!(parent instanceof Context))
return (null);
else
// parent = org.apache.catalina.core.StandardContext
// return org.apache.catalina.core.StandardContext.getServletContext()
// return org.apache.catalina.core.ApplicationContextFacade
return (((Context) parent).getServletContext()); // !!!
}
}
// StandardWrapper接口屏蔽类StandardWrapperFacade
class org.apache.catalina.core.StandardWrapperFacade implements ServletConfig {
public StandardWrapperFacade(StandardWrapper config) {
super();
this.config = config;
}
@Override
public ServletContext getServletContext() {
if (context == null) {
// config == org.apache.catalina.core.StandardWrapper;
// context == org.apache.catalina.core.StandardWrapper.getServletContext();
// context == org.apache.catalina.core.StandardContext.getServletContext()
// context == org.apache.catalina.core.ApplicationContextFacade
context = config.getServletContext();
if (context instanceof ApplicationContext) {
context = ((ApplicationContext) context).getFacade();
}
}
return (context);
}
@Override
public String getInitParameter(String name) {
return config.getInitParameter(name);
}
@Override
public Enumeration<String> getInitParameterNames() {
return config.getInitParameterNames();
}
}
// 上下文对象StandardContext
class org.apache.catalina.core.StandardContext{
@Override
public ServletContext getServletContext() {
if (context == null) {
context = new ApplicationContext(this);//!!!!
if (altDDName != null)
context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
}
return (context.getFacade());
}
}