第
6
章
Spring
与
Web
在
Web
项目中使用
Spring
框架,首先要解决在
web
层(这里指
Servlet
)中获取到
Spring
容器的问题。只要在
web
层获取到了
Spring
容器,便可从容器中获取到
Service
对象。
6.1Web
项目使用
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
容器就又不唯一了。
6.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_ATTRIBUTE
。所以,可
以直接通过
ServletContext
的
getAttribute()
方法,按照指定的
key
将容器对象获取到。
(
2
) 通过
WebApplicationContextUtils
获取
工具类
WebApplicationContextUtils
有一个方法专门用于从
ServletContext
中获取
Spring
容器对象:
getRequiredWebApplicationContext(ServletContext sc)
调用
Spring
提供的方法获取容器对象:
查其源码,看其调用关系,就可看到其是从
ServletContext
中读取的属性值,即
Spring
容器。
以上两种方式,无论使用哪种获取容器对象,刷新
success
页面后,可看到代码中使用
的
Spring
容器均为同一个对象。
spring完结。