这一篇说的是纯手动的整合,目前主流的应该是采用 Maven 或者 Gradle 进行整合,这个以后再说吧…
关于集成顺序,不是固定的,但是一般是先添加 Spring 支持,再添加 Hibernate 支持,这样 hibernate.cfg.xml 就被集成到 applicationContext.xml(beans.xml) 中,就不用手动配置了。至于 Struts 在他们俩前后都可以了….
每添加一个框架建议做一次测试,以保证引入是没有问题的,用简单的单元测试就行
环境搭建
先用最基本的手动搭建大法,现在使用构建工具来搭建也很普遍了,也更方便一些,后面看看再说吧,这里采用的是:Struts2-2.3 + Spring4.3 + Hibernate5.2
手动导入的时候还要注意一个问题,那就是 jar 包的冲突问题
1.引入Spring&XML知识补充
作为第一个引入的来说,应该是最简单的,没什么可说的和平常加入 Spring 是一样的,导入相应的 jar 包,设置好相应的配置文件就行了
配置文件的名字和位置其实是随意的,前面都说过,通过用 applicationContext 或者 beans 还有种是 spring-config,一般放在 src 目录下
配置方面可以加入 aop 和事务的约束,对于 spring 来说 xsd 文件可以不写版本号,会使用自带的最新的版本,内部做了本地的映射,jar 包中就有 xsd 文件,避免离线不能用的情况
1 | <beans xmlns="http://www.springframework.org/schema/beans" |
这里就顺便补充下关于 xml 的一些知识吧,原来大多使用的是 dtd 约束文件,但是因为其的局限性已经逐步被 XML Schema 取代,对于 Spring ,为了避免冲突,有几种不同的命名空间,相当于 java 中的包了
需要那个加那个就可以了
- xmlns=
声明 xml 文件默认的命名空间,表示未使用其他命名空间的所有标签的默认命名空间。
如果没有提供 schemaLocation,那么 Spring 的 XML 解析器会从 namespace 的 URI 里加载 XSD 文件 - xmlns:xsi=
声明 XML Schema 实例,声明后就可以使用 schemaLocation 属性了
说明当前的 xml 是 schema 一个实例文档 - xmlns:aop=
声明前缀为 aop 的命名空间,后面的 URL 用于标示命名空间的地址,不会被解析器用于查找信息。
其惟一的作用是赋予命名空间一个惟一的名称。当命名空间被定义在元素的开始标签中时,所有带有相同前缀的子元素都会与同一个命名空间相关联。 - xsi:schemaLocation=
这个从命名可以看出个大概,指定 Schema 的位置这个属性必须结合命名空间使用。
这个属性有两个值,第一个值表示需要使用的命名空间。第二个值表示供命名空间使用的 XML schema 的位置
schemaLocation 提供了一个 xml namespace 到对应的 XSD 文件的一个映射,所以我们可以看到,在 xsi:schemaLocation 后面配置的字符串都是成对的,前面的是 namespace 的 URI,后面是 xsd 文件的 URI
为了防止离线获取不到的问题,Spring 很贴心的将这些文件打包到 jar 文件里了,并且进行了映射,所以说:不要在 Spring 的配置里,配置上 XSD 的版本号,因为如果没有配置版本号,取的就是当前 jar 里的 XSD 文件,减少了各种风险。而且这样约定大于配置的方式很优雅。
如果感觉下载 XSD 文件非常慢,导致IDE的卡顿,可以事先下载好然后本地引用,详细配置可以参考:
http://blog.csdn.net/jackphang/article/details/17021241
2.引入Hibernate
和一般的引入也是差不多的,倒不如说更简单了,因为 cfg 文件不需要单独配置了(映射的 hbm 文件也可以用 JPA 来代替了),直接在 Spring 的配置文件里用就行了
导入相关的 jar 包不要忘了数据库驱动的包和连接池相关的包(spring 也自带一些)
首先要配置数据源,这里使用的 C3P0:
1 | <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> |
至于为什么要配置数据源,现在基本都是用线程池的吧,要不然效率也太低了并且官方也推荐这样配置,关于连接池的好处前面其实已经说过了
然后就是 Hibernate 最重要的对象 sessionFactory 了(单例),并且我们知道它是需要一个数据源的,我们配置的 cfg 配置文件其实就是为了生成它:
1 | <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> |
至于里面的配置是什么意思,我想都看出来了,这也更说明了 Spring 其实就是个快速生成对象(bean)的框架(从这里来看)
其他的,可以配置下事务等配置,使用事务管理器最大的好处就是能少些代码,由它来管理 sessionFactory 的事务,其实是使用的类似 AOP 技术的(织入)通知实现的,这样在 Service 层的类中写的 CRUD 方法的时候就不需要写事务相关的代码了(记得在类上加注解)
1 | <!-- 配置事务管理器 --> |
然后可以创建个实体 bean,编写好对应的映射文件,在上面的配置中写好 hbm 的文件路径(如果用注解就是类名了),然后就可以进行测试了,不出意外的话 hibernate 就集成完毕了
3.引入Struts
Struts 作为 web 层的框架引入也是很简单的,首先当然还是要导入相关的 jar ,还是要注意 jar 包的重复,以及因为要和 spring 整合,不要忘了导入 struts2-spring-plugin 包和 spring-web-x.x.x.RELEASE.jar 包
然后顺便配置下相关的配置文件,有 struts 的 Struts.xml :
1 | <!-- 指定Action对象由谁创建 --> |
注意:Action 的管理托管给 Spring 后,在 action 标签配置的 class 就是 spring 配置文件中 bean 的 id
在 web.xml 中配置 struts:
1 | <filter> |
最后还是要在 Web.xml 中配置实例化 Spring 容器,避免每一次请求就初始化一次,浪费资源;实际上就是把 spring 容器存到 ServletContext 中去了:
1 | <!-- 指定spring的配置文件,默认从web根目录寻找配置文件,我们可以通过spring提供的classpath:前缀指定从类路径下寻找 --> |
到这里基本就整合完了,下面要做的就是测试一下然后进行开发了,测试也非常的简单
4.测试
创建个 Action 访问下测试就可以了,比如可以这样写一个测试类
1 |
|
OK,到这里基本就真的完成了,如果不出问题的话。。。。
所谓整合
我们所说的整合一般就是:
Spring 整合 Hibernate :由 IOC
容器(Spring 框架的核心)管理 Hibernagte 的 SessionFactory
;以及让 Hibernate 使用上 Spring 的声明式事务
Spring 整合 Struts :让 spring 来接管 Struts 的 Action
在服务器启动的时候自动创建相应的 Action,如果想要解决高并发问题可以利用 spring 的 scope 属性(scope="prototype"
),让其每一个请求产生独立的 Action,避免数据的混乱,当然它的生命周期是很短的
补充
来说一下为什么要在 web.xml 中配置实例化 Spring,如果不实例化那么在 Action 被访问的时候是必须要实例化的(因为 Action 要用啊),如果有很多人访问就会多次执行生成 ApplicationContext 的代码,这个是非常耗费资源的
所以不如索性在服务器启动的时候就把 ApplicationContext 给实例化了,存到 ServletContext 中,需要的时候可以使用下面的代码获取:
1 | ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext()); |
更好的,可以通过继承 ApplicationContextAware 来构造一个 spring 的工具类,别忘了让 spring 把这个工具类顺便给实例化了,这样直接调用就可以了
或者可以直接使用 spring 提供的:WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
进而使用 wac 来获取 bean
WebApplicationContext:
其实这个接口不过是 applicationContext 接口的一个子接口罢了,只不过说它的应用形式是 web 罢了. 它在ApplicationContext 的基础上,添加了对 ServletContext 的引用(后面还加入了很多其他作用域的引用),即 getServletContext 方法.
可以说:它是一个是支持 web 特性的 BeanFactory。
相关源码:
1 | public interface WebApplicationContext extends ApplicationContext { |
在配置 Hibernate 数据库信息的时候,就是 datasource 的时候,可以从 prop 文件中装载的,需要配一个:<context:property-placeholder location="classpath:db.properties"/>
属性而已
这样可以在 datasource 中使用:value="${user}"
进行引用;
同理,配置 SessionFactory 的时候也可以引用外部文件:
1 | <property name="configLocations" value="classpath:hinernate.cfg.xml" /> |
这样 cfg 文件中就没必要写数据库连接的相关东西了,因为会注入一个连接池,只需要写 hibernate 特有的一些配置就 OK 了
至于是使用外部文件好还是直接写在一起好,我也不造….
再补充 classpath 是指 WEB-INF 文件夹下的 classes 目录;
classpath 和 classpath*
区别:
- classpath:只会到你的 class 路径中查找找文件;
- classpath*:不仅包含 class 路径,还包括 jar 文件中( class 路径)进行查找.
也就是说前者只会从第一个 classpath 中加载,而后者会从所有的 classpath 中加载,用 classpath*
需要遍历所有的 classpath,所以加载速度是很慢的,因此,在规划的时候,应该尽可能规划好资源文件所在的路径,尽量避免使用 classpath*
;
另外,"**/"
表示的是任意目录;**/applicationContext-*.xml"
表示任意目录下的以 “applicationContext-“ 开头的 XML 文件。
千万注意 jar 包的重复和未部署 jar 包的巨坑,详细的解决笔记在我的 Github
参考&拓展
http://www.cnblogs.com/doit8791/p/5757798.html
http://blog.csdn.net/hzy38324/article/details/44139609
spring获取bean的几种方式
https://essviv.github.io/2016/07/02/spring/spring-differerce-between-application-context-and-servlet-context/
http://www.cnblogs.com/panxuejun/p/5898540.html
评论框加载失败,无法访问 Disqus
你可能需要魔法上网~~