前排提示博文较长,了解ssh工程的搭建只需要这一篇就够了!
1.SSH框架结构
- action,biz,dao之间的依赖关系由spring维护,动态注入
- sping以AOP(面向切面的方式)实现了事务管理器。
- spring整合Hibernate时,spring替代实现HibernateSessionFacctory和dao
- spring整合struts时,代替实现Action
- 开发过程中的所有对象由spring控制管理
2. 项目流程
2.1框架导入推荐顺序
Spring–>struts–>hibernate
hibernate框架搭建的两种方式主要基于是否使用spring框架
Hibernate导入的两种方式:
- 保留Hibernate自己的配置文件
- Hibernate的配置信息写入Spring的配置文件(推荐)
2.2 基于MyEclipse的框架搭建步骤
导入Spring框架
导入struts2框架
- 导入hibernate框架(需要小心)
2.3 配置文件介绍
(以不保留hibernate配置文件为例)
- spring配置文件(applicationContext.xml)
1.添加命名空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
2.配置hibernate中数据源对象
<!--数据源,驱动这里没指定,在下面的sessionFactory中指定方言会自动加载驱动-->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="url"
value="jdbc:oracle:thin:@localhost:1521:orcl">
</property>
<property name="username" value="jack"></property>
<property name="password" value="admin"></property>
</bean>
3.spring提供并维护sessionFactory对象
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</prop>
</props>
</property>
</bean>
4.事务管理器及事务注解,后期只需在使用事务的方法上使用注解即可维护事务
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
5.为后期需要spring动态注入的对象所在包进行扫描
<!-- 注册注解的后台处理类 -->
<context:annotation-config/>
<!-- 指明使用注解的类的位置 -->
<context:component-scan base-package="com.studySystem.biz"/>
<context:component-scan base-package="com.studySystem.action"/>
2.4 生成实体类和dao
- Hibernate reverse engineering反向工程生成
- spring配置文件变化
生成bean标签,提供session工厂
<bean id="UstbstudentsDAO"
class="com.zhangrui.dao.UstbstudentsDAO">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
dao中的sesionFactory由spring动态注入,获得session进行数据库操作
public class UstbstudentsDAO {
private static final Logger log = LoggerFactory
.getLogger(UstbstudentsDAO.class);
// property constants
public static final String STUNAME = "stuname";
public static final String STUPASSWORD = "stupassword";
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
2.5 编写BIZ
使用注解的方式维护对象@Component("ustbstudentsBIZ") //告诉spring这个对象需要被维护
public class UstbstudentsBIZ {
//使用动态注入的方式维护dao对象,可以在属性或者set方法上添加此注解
@Autowired
@Qualifier("UstbstudentsDAO")
private UstbstudentsDAO ustbstudentsDAO;
public UstbstudentsBIZ() {
}
public UstbstudentsBIZ(UstbstudentsDAO ustbstudentsDAO) {
super();
this.ustbstudentsDAO = ustbstudentsDAO;
}
public UstbstudentsDAO getUstbstudentsDAO() {
return ustbstudentsDAO;
}
public void setUstbstudentsDAO(UstbstudentsDAO ustbstudentsDAO) {
this.ustbstudentsDAO = ustbstudentsDAO;
}
- BIZ的事务通过在需要处理事务的方法之上添加注解的方式进行事务管理
spring以AOP的方式实现了事务的管理
@Transactional(propagation = Propagation.REQUIRED, readOnly = true) //设置只读
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })//异常回滚
2.6 Spring整合struts2的Action
Action是在用户发送请求时创建的,Spring框架要在Action被struts2创建之前加载,通过Spring提供的一个监听器类(ContextLoaderListener),在WEB工程启动时加载Spring框架。使用方式:
打开web.xml,配置
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> <!-- 还可以使用绝对路径 <param-value>/WEB-INF/applicationContext.xml</param-value> --> </context-param>
param-name只可以有一个,多个xml以逗号隔开
- 创建Action(使用注解的方式)
这里的action使用的是模型驱动,需要重写一个getModel()方法
使用时jsp的name要与类属性的set方法名一致
@ParentPackage("struts-default")
@Namespace("/users")
@Component("UstbStudentsAction")
@Scope("prototype") //设置为多例,Action是有状态的
public class UstbStudentsAction extends ActionSupport implements ModelDriven<Ustbstudents> {
@Autowired
@Qualifier("ustbstudentsBIZ")
private UstbstudentsBIZ ustbstudentsBIZ;
private Ustbstudents student = new Ustbstudents();
@Override
public Ustbstudents getModel() {
return student;
}
@Action(value = "users_isRegister", results = {
@Result(name = SUCCESS, type = "redirectAction", params = {"namespace", "/buildings", "actionName", "showAllBuilding" }),
@Result(name = "isexist", location = "/regist.jsp"), })
public String isRegister() {
boolean result = ustbstudentsBIZ.isExistStudent(student.getStuid());
if (result) {
this.setError("学号已存在!");
return "isexist";
} else {
ustbstudentsBIZ.save(student);
student = ustbstudentsBIZ.findByStuID(student.getStuid());
ActionContext.getContext().getSession().put("student", student); // 保存当前用户到会话
return SUCCESS;
}
}
}
3 异常信息处理
配置文件
保留Hibernate配置文件的情况下会出现
canot unwrap to requested type [javax.sql.DataSource]
问题描述:Spring创建sessionFactory时需要DataSource
原因分析:版本3以前可以这么用,版本4之后不行
解决方案:删除hibetnate中关于数据库连接的四个参数项
加入到spring中,创建datasource,将datasource对象注入sessionFactoryJar包问题
hibernate和spring存在jar冲突,进部署工程目录删去冲突jar包
- 延迟加载问题
在查询级联对象时,会报错:
could not initialize proxy - no session
解决方案:加一个filter
sprin中提供了OpensessionInviewFilter(注意版本可能不同)
在web.xml中配置(配置在struts2过滤器之前)
<filter> <filter-name>OpenSessionInViewFilter</filter-name> <filter-class> org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>singleSession</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>OpenSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>ASYNC</dispatcher> <dispatcher>ERROR</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>REQUEST</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping>