共计 3496 个字符,预计需要花费 9 分钟才能阅读完成。
第 5 章 Spring 与 Web
官网下载地址
http://www.bjpowernode.com/
视频观看地址
https://www.bilibili.com/vide…
在 Web 我的项目中应用 Spring 框架,首先要解决在 web 层(这里指 Servlet)中获取到 Spring 容器的问题。只有在 web 层获取到了 Spring 容 器,便可从容器中获取到 Service 对象。
5.1 Web 我的项目应用 Spring 的问题 (理解)
举例:springWeb 我的项目(在 spring-mybatis 根底上批改)
Step1:新建一个 Maven Project
类型 maven-archetype-webapp
Step2: 复制代码,配置文件,jar
将 spring-mybatis 我的项目中以下内容复制到以后我的项目中:
(1)Service 层、Dao 层全副代码
(2)配置文件 applicationContext.xml 及 jdbc.properties,mybatis.xml
(3)pom.xml
(4)退出 servlet ,jsp 依赖
在之前原有的 pom.xml 文件中再退出以下的内容:
<!-- servlet 依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- jsp 依赖 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
<scope>provided</scope>
</dependency>
Step3:定义 index 页面
Step4:定义 RegisterServlet(重点代码)
Step5:定义 success 页面
Step6:web.xml 注册 Servlet
Step7:运行后果剖析
当表单提交,跳转到 success.jsp 后,多刷新几次页面,查看后盾输入,发现每刷新一次页面,就 new 出一个新的 Spring 容器。即,每提交一次申请,就会创立一个新的 Spring 容器。对于一个利用来说,只须要一个 Spring 容器 即可。所以,将 Spring 容器的创立语句放在 Servlet 的 doGet() 或 doPost() 办法中是有问题的。
此时,能够思考,将 Spring 容器的创立放在 Servlet 进行初始化时进行,即执行 init() 办法时执行。并且,Servlet 还是单例多线程的,即一个业务只有 一个 Servlet 实例,所有执行该业务的用户执行的都是这一个 Servlet 实例。这 样,Spring 容器就具备了唯一性了。
然而,Servlet 是一个业务一个 Servlet 实例,即 LoginServlet 只有一个,但还会有 StudentServlet、TeacherServlet 等。每个业务都会有一个 Servlet,都会执行本人的 init() 办法,也就都会创立一个 Spring 容器了。这样一来,Spring 容器就又不惟一了。
5.2 应用 Spring 的监听器 ContextLoaderListener(把握)
举例:springweb-2 我的项目(在 spring-web 我的项目根底上批改)
对于 Web 利用来说,ServletContext 对象是惟一的,一个 Web 利用,只有一个 ServletContext 对象,该对象是在 Web 利用装载时初始化的。若将 Spring 容器的创立机会,放在 ServletContext 初始化时,就能够保障 Spring 容器的创立只会执行一次,也就保障了 Spring 容器在整个利用中的唯一性。
当 Spring 容器创立好后,在整个利用的生命周期过程中,Spring 容器应该是随时能够被拜访的。即,Spring 容器应具备全局性。而放入 ServletContext 对象的属性,就具备利用的全局性。所以,将创立好的 Spring 容器,以属性的模式放入到 ServletContext 的空间中,就保障了 Spring 容器的全局性。
上述的这些工作,曾经被封装在了如下的 Spring 的 Jar 包的相干 API 中:spring-web 5.2.5.RELEASE
Step1:maven 依赖 pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
Step2:注册监听器 ContextLoaderListener
若要在 ServletContext 初始化时创立 Spring 容器,就须要应用监听器接 口 ServletContextListener 对 ServletContext 进行监听。在 web.xml 中注册该监听器。
Spring 为该监听器接口定义了一个实现类 ContextLoaderListener,实现 了两个很重要的工作:创立容器对象,并将容器对象放入到了 ServletContext 的空间中。
关上 ContextLoaderListener 的源码。看到一共四个办法,两个是构造方法,一个初始化办法,一个销毁办法。
所以,在这四个办法中较重要的办法应该就是 contextInitialized(),context 初始化办法。
跟踪 initWebApplicationContext() 办法,能够看到,在其中创立了容器对象。
并且,将创立好的容器对象放入到了 ServletContext 的空间中,key 为一个常量:
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。
Step3:指定 Spring 配置文件的地位 <context-param>
ContextLoaderListener 在对 Spring 容器进行创立时,须要加载 Spring 配置文件。其默认的 Spring 配置文件地位与名称为:WEB-INF/applicationContext.xml。但,个别会将该配置文件搁置于我的项目的 classpath 下,即 src 下,所以须要在 web.xml 中对 Spring 配置文件的地位及名称进行指定。
从监听器 ContextLoaderListener 的父类 ContextLoader 的源码中能够看到其要读取的配置文件地位参数名称 contextConfigLocation。
Step4:获取 Spring 容器对象
在 Servlet 中获取容器对象的罕用形式有两种:
(1)间接从 ServletContext 中获取
从对监听器 ContextLoaderListener 的源码剖析可知,容器对象在 ServletContext 的中寄存的 key 为 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUT E。所以,能够间接通过 ServletContext 的 getAttribute() 办法,依照指定的 key 将容器对象获取到。
(2)通过 WebApplicationContextUtils 获取
工具类 WebApplicationContextUtils 有一个办法专门用于从 ServletContext 中获取 Spring 容器对象:getRequiredWebApplicationContext(ServletContext sc)
调用 Spring 提供的办法获取容器对象:
查其源码,看其调用关系,就可看到其是从 ServletContext 中读取的属性值,即 Spring 容器。
以上两种形式,无论应用哪种获取容器对象,刷新 success 页面后,可看到代码中应用的 Spring 容器均为同一个对象。