Spring 容器與 Servlet互動
1 Servlet容器如何啟動spring容器的?
在serlet容器中的 web.xml中配置’ Spring 容器的相關配置:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-config.xml</param-value>
</context-param>
//1 方法一
<listener>
<listener-class>org.springframework.context.ContextLoaderListener</listener-class>
</listener>
//2 方法二 3.0也已經發布宣告說,已經移除了
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
1.1 Listener方式
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
實現了ServletContextListener,是serlet容器的規範,容器會回撥入contextInitialized方法。
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
org.springframework.web.context.ContextLoader#initWebApplicationContext
try {
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdown.
// 1 建立webapplication
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
}
//2 重新整理容器
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
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 ->
// determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
//3 在serlet容器中,儲存ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE與webapplication容器建值對
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
//4 設定類載入器與容器引用的關係。
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
}
else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}
if (logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("Root WebApplicationContext initialized in " + elapsedTime + " ms");
}
return this.context;
}
contextConfigLocation 引數配置檔案的路徑,CONFIG_LOCATION_PARAM是在configureAndRefreshWebApplicationContext方法中傳入的。
1.2 Servlet方式
已廢棄
2 SpringMVC 容器的載入
<!--載入springMVC-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springcfg/springMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
DispatcherServlet繼承了httpservlet
@Override
protected final void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");
if (logger.isInfoEnabled()) {
logger.info("Initializing Servlet '" + getServletName() + "'");
}
long startTime = System.currentTimeMillis();
try {
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
catch (ServletException | RuntimeException ex) {
logger.error("Context initialization failed", ex);
throw ex;
}
if (logger.isDebugEnabled()) {
String value = this.enableLoggingRequestDetails ?
"shown which may lead to unsafe logging of potentially sensitive data" :
"masked to prevent unsafe logging of potentially sensitive data";
logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails +
"': request parameters and headers will be " + value);
}
if (logger.isInfoEnabled()) {
logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
}
}
DispatcherServlet 的父類,該方法是載入 SpringMVC 容器,org.springframework.web.servlet.FrameworkServlet#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
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
// Either the context is not a ConfigurableApplicationContext with refresh
// support or the context injected at construction time had already been
// refreshed -> trigger initial onRefresh manually here.
synchronized (this.onRefreshMonitor) {
onRefresh(wac);
}
}
if (this.publishContext) {
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
}
return wac;
}
DispatcherServlet 此時作為一個 Bean,實現了 ApplicationContextAware 介面,會自動將上下文環境儲存到 webApplicationContext 欄位中;
rootContext 和 webApplicationContext 區別?
rootContext是當前servlet容器中的spring 中的webApplicationcontext。是springMVC的父容器的Context。
webApplicationContext載入DispatcherServlet spring容器的webApplicationcontext。
3 springBoot
1、在 Springboot 應用程式啟動時,在 SpringBootServletInitializer#onStartup 方法中,會建立一個 rootAppContext 容器,如下:
同時將上文所說的 ContextLoaderListener 監聽器新增到 Servlet 容器中,同樣達到了 xml 配置的效果,而調createRootApplicationContext 方法建立 rootAppContext 容器時,會將 contextClass 設定為 AnnotationConfigServletWebServerApplicationContext.class。
相關文章
- 十二、Spring Boot 嵌入式 Servlet 容器啟動原理Spring BootServlet
- Servlet實現、與html的簡單互動ServletHTML
- 從servlet容器到Spring mvc 5.1.1.RELEASE IoC 啟動原始碼分析ServletSpringMVC原始碼
- Servlet 規範和 Servlet 容器Servlet
- JAVA網路程式設計基本功之Servlet與Servlet容器Java程式設計Servlet
- 互動式 .Net 容器版
- 為什麼要有 Servlet ,什麼是 Servlet 容器,什麼是 Web 容器?ServletWeb
- Spring 容器自動注入.Spring
- SpringBoot 中的 Servlet Web 容器Spring BootServletWeb
- Spring容器系列-啟動原理Spring
- 簡述Spring容器與SpringMVC的容器的聯絡與區別SpringMVC
- 淺嘗Spring註解開發_Servlet3.0與SpringMVCServletSpringMVC
- Spring WebFlux效能真的超過Spring Servlet ? - GavinSpringWebUXServlet
- js 與WKWebView 互動JSWebView
- spring容器Spring
- 【Docker】Docker基礎-埠對映與容器互聯Docker
- 作為servlet容器的hi-nginx-javaServletNginxJava
- SpringBoot2.0之Servlet容器變成UndertowSpring BootServlet
- Spring IOC容器的設計與實現Spring
- Java與Excel的互動!-JavaExcel
- ReactNative與iOS的互動ReactiOS
- Flutter 與Native原生互動Flutter
- Flutter 與 Android 的互動FlutterAndroid
- flash如何與js互動?JS
- 【Spring】普通單例 Bean 的建立與三級快取之間的互動Spring單例Bean快取
- SpringBoot2.4.0中嵌入式servlet容器的自動配置以及啟動原理(自我理解)Spring BootServlet
- 容器間互聯(1)
- Spring Bean容器SpringBean
- spring原始碼閱讀--容器啟動過程Spring原始碼
- 淺析Spring Framework框架容器啟動過程SpringFramework框架
- Spring IOC 容器預啟動流程原始碼探析Spring原始碼
- 如何向Spring IOC 容器 動態註冊beanSpringBean
- Reactive Spring實戰 -- 響應式MySql互動ReactSpringMySql
- Reactive Spring實戰 -- 響應式Kafka互動ReactSpringKafka
- Reactive Spring實戰 -- 響應式Redis互動ReactSpringRedis
- Servlet 到 Spring MVC 的簡化之路ServletSpringMVC
- C++ vector容器的swap方法(容器互換)C++
- ajax與XML檔案互動XML