Servlet、ServletConfig、ServletContext、DispatcherServlet、ApplicationContext、WebApplicationContext区别?

Servlet

Servlet: is a class in Java that is used to extend the capabilities of servers hosting applications that can be accessed through the "request-response" programming model. Tomcat is a Web application server and a Servlet container. As a Servlet container, Tomcat is responsible for processing client requests, passing requests to Servlets, and returning Servlet responses to clients. In short, a Servlet is a component that runs on a server that supports the Java language .

ServletContext

ServletContext: This is a concept from the servlet specification. It is a combination of interfaces used by servlets to interact with containers. That is to say, this interface defines a series of methods through which servlets can easily communicate with their own Some interactions with the container, such as getting the version information of the container through getMajorVersion and getMinorVersion, etc. It can also be seen from its definition that there is only one ServletContext in an application (one JVM), in other words, all servlets in the container All share the same ServletContext.

    <!-- 配置应用公共配置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!-- 定义Spring监听器,加载Spring -->
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

The initWebApplicationContext in ContextLoaderListener is to initialize WebApplicationContext, which is actually rootApplicationContext

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    
    
    public ContextLoaderListener() {
    
    
    }

    public ContextLoaderListener(WebApplicationContext context) {
    
    
        super(context);
    }

    public void contextInitialized(ServletContextEvent event) {
    
    
        this.initWebApplicationContext(event.getServletContext());
    }

    public void contextDestroyed(ServletContextEvent event) {
    
    
        this.closeWebApplicationContext(event.getServletContext());
        ContextCleanupListener.cleanupAttributes(event.getServletContext());
    }
}

The initWebApplicationContext method specifically creates the WebApplicationContext container, where ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT".


    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
    
    
        ......
       //主要代码,创建 WebApplicationContext 容器
       this.context = this.createWebApplicationContext(servletContext);
       ......
       // 配置参数并调用初始化方法
       this.configureAndRefreshWebApplicationContext(cwac, servletContext); 
       ......
       // 将 WebApplicationContext 容器作为一个属性放回到 ServletContext 容器中
       servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); 
       .....
   }

ServletConfig

ServletConfig: The difference between it and ServletContext is that ServletConfig is for Servlets, and each Servlet has its unique ServletConfig information, which is not shared with each other.

/**
 * Servlet配置对象: Servlet容器在初始化期间将信息传递给 Servlet
 */
public interface ServletConfig {
    
    
 	/**
     * 返回此 Servlet 实例的名称
     */
    String getServletName();
 	/**
     * 获取 Servlet 上下文对象:ServletContext
     */
    ServletContext getServletContext();
 	/**
     * 根据名称获取参数值
     */
    String getInitParameter(String var1);
 	/**
     * 获取所有的参数名称
     */
    Enumeration<String> getInitParameterNames();
}

DispatcherServlet

DispatcherServlet: It is essentially a special Servlet. Since DispatcherServlet inherits from FrameworkServlet, this method calls the initWebApplicationContext method in initServletBean in FrameworkServlet. Through this method, the rootContext is first obtained and passed to wac, so that WebApplicationContext and rootApplicationContext in DispatcherServlet form a parent-child relationship.

DispatcherServlet class diagram:
Class Diagram

The loading process of web containers such as tomcat is roughly as follows:
Web containers such as tomcat

ApplicationContext

ApplicationContext: This class is the core interface for Spring to implement container functions. It is also the most important interface for Spring to implement IoC functions. As can be seen from its name, it maintains the context information needed during the entire program operation. Pay attention to the application here The program does not have to be a web program, but may also be other types of applications. Multiple applicationContexts are allowed in Spring, and these contexts also form the relationship between parent and child, inheritance and inherited. This is what we usually say, there are two Contexts in Spring, one is the root context, and the other is the It is the meaning of servlet applicationContext. This point will be further elaborated later.

This interface has three commonly used implementation classes:

  1. ClassPathXmlApplicationContext: The configuration file under the class path can be loaded, and the configuration file must be under the class path.
  2. FileSystemXmlApplicationContext: You can load configuration files under any path in the disk, requiring access rights.
  3. AnnotationConfigApplicationContext: Used to read annotations and create containers.

ApplicationContext is defined as follows

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    
    
    String getId();

    String getApplicationName();

    String getDisplayName();

    long getStartupDate();

    ApplicationContext getParent();

    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

ClassPathXmlApplicationContext class diagram
ClassPathXmlApplicationContext class diagram

WebApplicationContext

WebApplicationContext 继承 ApplicationContext、BeanFactory
figure 2

The difference between ApplicationContext and WebApplicationContext is shown in the following table:
difference between the two

Source code analysis

    First look at the loading process of the configuration file in ServletContext. This process is completed by the ContextLoaderListener object, so we find the corresponding source code, remove some logs and irrelevant source code as follows:

  • The first step is to determine whether there is a RootApplicationContext, if there is an exception directly thrown to end
  • The second step is to create a Context object, and set this Context as an attribute named ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE in ServletContext. The difference between ApplicationContext and ServletContext has been explained here. It is just an attribute value in ServletContext. There are all the context information of program running. Since this ApplicationContext is the global application context information, it is named 'root application context' in Spring.
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
	if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
	}
	try {
		// Store context in local instance variable, to guarantee that
		// it is available on ServletContext shutdown.
		if (this.context == null) {
			this.context = createWebApplicationContext(servletContext);
		}
		servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
		return this.context;
	}
}

    Then look at the source code of DispatcherServlet. As a servlet, according to the specification, its configuration information should be completed in the Init method, so we can find the source code of this method to know the initialization process of servletConfig and servlet application context:

  1. The first step is to get all configuration parameters from ServletConfig, the constructor of ServletConfigPropertyValues ​​will traverse all initialization parameters of ServletConfig object, and store them in pvs one by one;

  2. The second step is to start the initial Servlet. Since DispatcherServlet is inherited from FrameworkServlet, this method is found in FrameworkServlet. You can see that the initWebApplicationContext method is called in initServletBean. In this method, the rootContext is first obtained, and then the initialization begins The wac object, in the method of creating this wac object, passed in the rootContext as its parent, that is, here, the parent-child relationship between the two is established, and the inheritance relationship we usually say is formed.

@Override
public final void init() throws ServletException {
    
    
	// Set bean properties from init parameters.
	PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
	// Let subclasses do whatever initialization they like.
	initServletBean();
}
//遍历获取servletConfig的所有参数
public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties)
	throws ServletException {
    
    
	while (en.hasMoreElements()) {
    
    
		String property = (String) en.nextElement();
		Object value = config.getInitParameter(property);
		addPropertyValue(new PropertyValue(property, value));
		if (missingProps != null) {
    
    
			missingProps.remove(property);
		}
	}
}
//初始化webApplicationContext
protected final void initServletBean() throws ServletException {
    
    
	try {
    
    
		this.webApplicationContext = initWebApplicationContext();
	}
}
//具体的初始化操作实现
protected WebApplicationContext initWebApplicationContext() {
    
    
	WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
	WebApplicationContext wac = null;
	if (this.webApplicationContext != null) {
    
    
		// A context instance was injected at construction time -> use it
		wac = this.webApplicationContext;
		if (wac instanceof ConfigurableWebApplicationContext) {
    
    
			ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
			if (!cwac.isActive()) {
    
    
				// The context has not yet been refreshed -> provide services such as
				// setting the parent context, setting the application context id, etc
				if (cwac.getParent() == null) {
    
    
					// The context instance was injected without an explicit parent -> set
					// the root application context (if any; may be null) as the parent
					cwac.setParent(rootContext);
				}
				configureAndRefreshWebApplicationContext(cwac);
			}
		}
	}
	if (wac == null) {
    
    
		// No context instance was injected at construction time -> see if one
		// has been registered in the servlet context. If one exists, it is assumed
		// that the parent context (if any) has already been set and that the
		// user has performed any initialization such as setting the context id
		wac = findWebApplicationContext();
	}
	if (wac == null) {
    
    
		// No context instance is defined for this servlet -> create a local one
		//就是在这个方法中,servlet application context与root application context的继承关系正式建立
		wac = createWebApplicationContext(rootContext);
	}
	if (this.publishContext) {
    
    
		// Publish the context as a servlet context attribute.
		String attrName = getServletContextAttributeName();
		getServletContext().setAttribute(attrName, wac);
	}
	return wac;
}
//就是在这个方法中,servlet application context与root application context的继承关系正式建立
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
    
    
	return createWebApplicationContext((ApplicationContext) parent);
}

Guess you like

Origin blog.csdn.net/u011047968/article/details/129168472