ContextLoaderListener可以不写嘛?

写了那么久的Spring,经常写这样的配置,这就是几行Spring、SpringMvc的基本配置, 但是最近也看到不写最前面的context-param以及listener的,好奇记录下.

<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring.xml</param-value>
</context-param>

<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
	<servlet-name>Springmvc</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>Springmvc</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

 

 

ContextLoaderListener监听器介绍

image

上图是ContextLoaderListener的结构图以及javadoc.    ContextLoaderListener肯定要实现ServletContextListener,这点不用多说,另外继承的类是ContextLoader.

JavaDoc告诉我们很多信息:Bootstrap listener启动类监听器用来启动/停止Spring Web上下文容器,代理给ContextLoader来完成启动启动工作。 listener应当在Log4jConfigListener之后注册。

           Spring3.1支持通过ContextLoaderListener构造器方式注入Web 上下文容器,servlet3.0也支持使用WebApplicationInitializer启动Spring容器来替代web.xml写法。

 

主要关注的是ContextLoaderListener,先主要关注容器启动这块吧!监听器的contextInitialized 方法:调用了ContextLoader的initWebApplicationContext,还是代理给了ContextLoader完成容器启动工作。

代码太占篇幅了,记录下加载过程即可:

   step1.检查ServletContext上下文是否有WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE这个属性,没有是正常的,有的话就说明Spring根容器重复定义了!

   step2. 尝试读取context-param中为contextClass的值作为根容器的class属性,如果没有指定context-param属性,就以ContextLoader类所在同一路径下的ContextLoader.properties文件中的 org.springframework.web.context.WebApplicationContext 作为key取出value , 默认为 org.springframework.web.context.support.XmlWebApplicationContext , 以这个作为Spring根容器类型,并且实例化XmlWebApplicationContext;

   step3. Spring根容器的ServletContext设置为当前ServletContext,并且读取web.xml中 其contextConfigLocation作为 Spring配置文件位置,最后调用 根容器的refresh 方法完成容器启动!

   step4. 根容器启动完之后,设置到 ServletContext的WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE 属性中 ,并且存到了ContextLoader中,可以通过静态方法ContextLoader.getCurrentWebApplicationContext就能获取到 Spring根容器。

 

 

DispatcherServlet的初始化

初始化的入口位于 org.springframework.web.servlet.HttpServletBean#init :

  SpringMvc容器类型默认为XmlWebApplicationContext,反射实例化该对象,并且通过ServletContext的 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性得到Spring根容器,

作为SpringMVC容器的父容器。  另外,像如下形式的SpringMvc,没有指定spring配置文件的位置,那默认加载的配置文件位置为: /WEB-INF/Springmvc-servlet.xml 

<servlet>
       <servlet-name>Springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>Springmvc</servlet-name>
		<url-pattern>/</url-pattern>
</servlet-mapping>

 

也就是说没有ContextLoaderListener,对于SpringMvc容器的影响就是没了父容器,照样可以使用SpringMVC的特性

 

 

获取Spring根容器以及Web容器的方式

提供五种获取Spring根容器方案、三种获取Spring父容器方案:

@Controller
@RequestMapping("/context")
public class ContextController implements ApplicationContextAware {

    @Autowired
    private ApplicationContext ac;

    @RequestMapping("/demo1")
    @ResponseBody
    public String demo1(HttpServletRequest request){
        System.out.println("Spring根容器方式一:"+request.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE));
        System.out.println("Spring根容器方式二:"+ContextLoader.getCurrentWebApplicationContext());
        System.out.println("Spring根容器方式三:"+ WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext()));
        System.out.println("Spring根容器方式四:"+ WebApplicationContextUtils.getWebApplicationContext(request.getServletContext()));
        System.out.println("Spring根容器方式五:"+ac.getParent());
        System.out.println("SpringMvc容器获取方式一:"+ac);
        System.out.println("SpringMvc容器获取方式二:"+ac2);
                          //SpringMvc容器获取方式三 继承抽象类 WebApplicationObjectSupport,方式二方式三不能同时用
                          //调用getApplicationContext
        return "hello World";
    }

    private ApplicationContext ac2;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ac2=applicationContext;
    }
}

转载于:https://www.cnblogs.com/lvbinbin2yujie/p/10616889.html

在SSM框架(Spring + Spring MVC + MyBatis)集成项目中,通常我们通过配置文件的方式来启动整个应用环境,而是直接依赖于`main()`方法去启动它。但是如果你想基于注解的方式,在传统的XML配置的基础上运行应用程序,并且需要显式地`main()`方法来触发程序执行,你可以考虑以下几种方案: ### 1. 使用Spring Boot 最简单的方法是迁移到Spring Boot。Spring Boot内置了Tomcat等嵌入式的Servlet容器,并简化了很多配置工作。只需要创建一个包含 `@SpringBootApplication` 注解的应用入口类并提供相应的Controller、Service 和 Repository组件即可。 ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 过这仍然有一个`main()`函数用于启动服务端监听请求的服务进程;这是Java Web应用程序的标准实践之一。 ### 2. 配置Web服务器自动加载ApplicationContext 对于传统非Boot模式下的SSM架构来说,则可以依靠Web容器本身的机制来进行上下文初始化操作而无需手动调用`main()`. 这通常是通过在web.xml里面指定ContextLoaderListener完成的: ```xml <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext*.xml</param-value> </context-param> ``` 这里虽然使用的是XML形式描述Bean定义信息,但实际上也可以配合`@Configuration`, `@ComponentScan` 等一系列全量替换原有的繁琐XML设置. 如果你坚持完全用`main()`而且还要保持原生tomcat部署的形式的话,那么你需要保证项目的结构符合标准war包的要求,然后让IDE帮您打包成War交给像Apache Tomcat这样的外部独立servlet引擎管理起来.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值