ssh(Struts+spring+Hibernate)三大框架配合使用来开发项目,是目前javaee最流行的开发方式,必须掌握;
注意:
为了稳健起见,每加入一个框架,我们就需要测试一下,必须通过才行;
框架整合的具体步骤:
创建web项目
1. 先搞定spring
2. 引入Spring开发包
3. 编写applicationContext文件(也可以是其他名字),暂时先放src目录下
4. 测试一下spring是否ok--->工作正常
5. 加入hibernate开发包
6. 因为我们是ssh,所以我们hibernate的核心,就被spring接管了,hibernate.cfg.xml文件,对象映射文件,SessionFactory在spring的配置文件中配置即可。
7. 配置数据源
<!-- 配置数据源对象 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<property name="driverClassName"value="oracle.jdbc.driver.OracleDriver"/>
<property name="url"value="jdbc:oracle:thin:@127.0.0.1:1521:orahsp8"/>
<property name="username"value="scott"/>
<property name="password"value="tiger"/>
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="3"/>
<!-- 连接池的最大值 -->
<property name="maxActive"value="500"/>
<!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
<property name="maxIdle" value="2"/>
<!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
<property name="minIdle" value="1"/>
</bean>
8. 配置SessionFactory
<!-- 配置会话工厂对象 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>cn/xxx/bean/Person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.OracleDialect
hibernate.hbm2ddl.auto=update
hibernate.show_sql=false
</value>
</property>
</bean>
9. 编写domain对象和映射文件,Employee.hbm.xml--->测试spring和hibernate能不能结合使用
10. 考虑分层
11. 使用事务管理器来统一管理事务.
注意如果使用事务管理器来统一管理事务时,则不要配置
hibernate.current_session_context_class=thread这一属性
不然会报:createQuery is not valid without activetransaction 错误!
<!-- 使用事务管理器来统一管理事务. -->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"ref="sessionFactory"/>
</bean>
<!-- 启用事务注解 @Transactional -->
<tx:annotation-driven transaction-manager="txManager"/>
详情可查看文档[中间层数据访问->声明事务管理->使用@Transactional]
12. 配置我们的hibernate二级缓存 [ehcache / oscache ]并引入二级缓存开发包和对应的配置文件;
在sessionFactory中配置hibernateProperties属性如下:
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.OracleDialect
hibernate.hbm2ddl.auto=update
hibernate.show_sql=false
hibernate.cache.use_second_level_cache=true
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
hibernate.generate_statistics=true <!—缓存统计策略-->
</value>
</property>
12.0 在需要使用二级缓存的对象domain对象配置文件*.hbm.xml中配置二级缓存策略:
<class ………..>
<!-- 使用二级缓存策略 -->
<cache usage="read-write"/>
... ..</class>
12.1 添加二级缓存开发包。
12.2 将我们的ehcache的配置文件放到 src目录
12.3 证明二级缓存生效
13. 整合struts
13.1 引入struts开发包
13.2 创建struts-config.xml 方法 /WEB-INF 目录下
配置如下:
14. 在web.xml中配置struts
<?xml version="1.0"encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
15. 在web.xml文件中初始化我们的Spring容器
<!-- 指定spring的配置文件,默认从web根目录寻找配置文件,
我们可以通过spring提供的classpath:前缀指定从类路径下寻找 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- 对Spring容器进行实例化 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
16. 让Spring接管我们struts(action控件)
当把action交给了spring管理后,其实可以以注解的方式自动注入action,如果全部
以注解的方式注入就要求action、service全部都配置注解,还需要启用“组件扫描配置“
也就是说如果需要的话,我们完全可以使用基于注解注入的方式来完成注入;
步骤:(1)启用注解
<!-- 启用注解 -->
<context:annotation-config/>
(2)到需要注入的源码初步进行元注解标记注入
如 下图:
(甚至可以做到action、service都无需配置到容器中,而是采用注解的方式完成)
详情用法可查看spring文档》》
16.1在struts-config.xml中配置 (代理请求处理)把实例化action组件转交给spring
<!-- 配置代理请求处理DelegatingRequestProcessor ,它的用处是
当ActionServlet中心控制器查找对应的action时,它如果发现struts-config.xml中有
如下配置,则不会在本配置中查找,而是到spring 的applicationContext中去找,并实例化
-->
<controller>
<set-property property="processorClass"
value="org.springframework.web.struts.DelegatingRequestProcessor"/>
</controller>
<action path="/login" name="empForm"attribute="empForm" input="/login.jsp" parameter="flag" "><!—这里要注意的是type则无需再配置了因为交由spring管理-->
<forward name="ok"path="/WEB-INF/mainframe.jsp"></forward>
<forward name="err"path="/login.jsp"></forward>
</action>
16.2在spring配置容器中applicationContext.xml中作如下配置:
例子:当浏览器请求为:http://……../login.do;
那么对于在spring则应如下配置,其他action同理;
<!-- 配置action对象,这里把 scope='prototype'可以有效地解决了action的单例问题,达到非单例的效果 -->
<bean name="/login" class="com.sx.web.actions.LoginAction"></bean>
16.3 这我们就可以通过spring容器来获取action,和配置action的一些属性
16.4 通过使用sping来接管我们的action,还有一个好处,可以解决action 是单例的问题.通过在applicationContext.xml文件中配置属性
<bean scope=”singlton/prototype/request/sesssion/global session”/>
- 解决中文乱码的问题
思路1:
① :可以使用以前的办法,如使用过滤器;
② :重写ActionServlet,重写它的protected void process(HttpServletRequest request, HttpServletResponse response)方法重新设置编码
思路2:
使用spring框架提供的处理中文乱码的过滤器,直接配置到web.xml中即可(其实跟前面的过滤器实现是一样的原理,只是封装了一把)
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
18. 对ssh整合的特别说明:
18.1. spring可以启用注解的方式来配置属性.
重新这样配置bean
<bean id="employeeService"class="com.hsp.service.imp.EmployeeService"/>
在EmployeeService的属性sessionFactory中添加一个注解 @Resource
在applicationContext.xml中启用注解
<context:annotation-config/>
此时还必须启用注解扫描如使用了@service、Controler...等
<context:component-scanbase-package="com.shop"/>
详情可见,spring查询文档的: 核心技术—> IoC(控制反转)容器 --->对受管组件的Classpath扫描
测试->ok
18.2. ssh整合的时候,如何解决懒加载问题
问题? 如果我们的雇员都属于一个部门
Class Department{
privateInteger id;
private String name;
}
目前我们把测试数据作出了.
具体问题?如果我们在 mainFrame.jsp中要求显示该雇员所在部门的时候
${loginuser.department.name} 时候,懒加载问题出现:
解决思路:
1. 明确初始化
在session还没有关闭时,访问一次xxx.getXxx(),强制访问数据库。或者 Hibernate.initialize(xxx)
2 在对象映射文件中 取消懒加载 <lazy=”false”/>
上面方法问题是: 不管你在jsp中使不使用 部门的名称,它都有向数据库发出select 请求.
3. spring专门提供了opensessioninview的方法来解决懒加载.
需要在web.xml文件中添加如下配置:
这是针对Hibernate的
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这是针对JPA的
<!-- 懒加载 -->
<filter>
<filter-name>Spring?OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Spring?OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
该方法可以有效的减少对数据库的查询,缺点是和数据保持的session,时间延长了.
18.3. 如果想获取到Spring管理的session时,我们可以使用回调函数完成;(好处是,session无需我们去管理,而是由Spring包办了)
18.4 Hibernate与Spring整合后可以使用处理事务的方法有:
(1) 继承Spring给hibernate所提供的dao类 extends HibernateDaoSupport 然后使用其提供给我们的HibernateTemplate对象即可对数据库进行一系列的操作,而无须关系事务的事情,如果想得到spring管理的下的session则要使用回调函数:上面1点所述;详情可查看spring查询文档;
(2) 可以使用配置的方式管理事务:
方法①:
首先在容器中启用事务管理器
<!-- 启用注解 -->
<context:annotation-config/>
<!-- 配置统一管理事务-->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory">
</property>
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
这时候则在对应需要事务处理的类文件中做如下注解(@Transactional):
这样spring则会自动帮我们管理事务,而无需我们自己去管理;
方法②:
①事物管理器
②advice通知(这里可以指定把事物应用到那个方法,使用哪种级别传播方式)
③aop切面
<!-- 事务配置方法② -->
<!-- 事务管理器 -->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 配置通知 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="update*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置切面 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(*com.s2sha.web.biz.impls.*.*(..))" id="usrBizOperaction"/>
<!-- 织入通知 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="usrBizOperaction"/>
</aop:config>