ide使用idea
- 准备工作
- Spring整合Struts2
- Spring整合Hibernate
- 使用SpringAOP事务
- 扩大session范围
- 整合测试
准备工作:
使用idea创建新的项目,选择Spring
选择Web Application 然后再选择Struts2
选择hibernate
都通过Use Library使用自己的jar包
Struts2 需要jar包
包括了和Spring整合的struts2-spring-plugin
Hibernate 需要jar包
Spring 需要jar包
为了省事,导入全部Spring jar包
还需要日志和aop的第三方包
启动项目,还需要导入数据库,junit,jstl的包。
通过File->Project Structure->Modules选择+,添加新的依赖
将数据库
junit
jstl都添加进依赖。
添加Tomcat
启动项目,在游览器中访问idea自动创建的index.jsp。如果访问成功,说明没有问题。如果出现classNotFound异常,可以在项目中的WEB-INF中创建lib文件夹,将之前的所有jar包都放进去。
准备工作完成。
Spring整合Struts2:
准备工作
在整合之前,首先需要配置Struts2的核心过滤器
<filter>
<filter-name>strutsPrepareAndExecuteFilter</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>strutsPrepareAndExecuteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
将idea自己创建的applicationContext删除,在src下新建一个
让项目在开启的时候读取Spring的配置文件,需要配置一个listener
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
还需要指定Spring配置文件的位置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
创建一个Action对象作为等会整合的实验品
public class UserAction extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("hello World");
return SUCCESS;
}
}
打开Spring注解配置Bean,在applicationContext中添加一条配置
<context:component-scan base-package="com"/>
这些都完成后,就可以开始整合
开始整合
1.在struts.xml文件中,将创建Action的工作交给Spring.
添加这一条配置
<constant name="struts.objectFactory" value="spring"/>
2.使用注解配置Action到applicationContext
@Component("userAction")
@Scope("prototype")
public class UserAction extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("hello World");
return SUCCESS;
}
}
这里必须指定scope为prototype,因为默认值是singleton。
3.在struts.xml中配置Action
<action name="userAction" class="userAction" method="execute">
<result name="success">/index.jsp</result>
</action>
这里与以前使用Struts不同的地方在于class的值不再是action的完成类名,而是bean name。
4.测试
在游览器中访问这个action,如果控制台中打印了hello World,并且跳转到index.jsp页面,说明整合成功。
Spring整合Hibernate:
准备工作:
1.将Spring与Junit整合,为接下来对Hibernate的测试做好准备
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test {
@org.junit.Test
public void test1() {
}
}
只需要在测试类前添加两条注解就可以了。
2.使用c3p0连接池提供数据库连接
在配置连接池属性的时候,不通过手动输入,而读取properties文件。想要Spring去读取指定的properties文件,需要在applicationContext中添加配置。这里使用properties文件的位置在src下。
properties文件
jdbc.url=jdbc:mysql:///demo
jdbc.driver=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=root
<context:property-placeholder
location="classpath:db.properties"/>
配置c3p0,通过在value中使用${键名}的方式读取properties中的内容
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
3.创建一个实体类和对应的hbm
打开数据库视图
添加数据库连接,完成对数据库的连接
添加persistence视图
自动根据数据库中的表创建对应实体类和hbm文件
点击ok后创建完毕。
开始整合
1.配置sessionFactory
将之前准备的dataSource和一些Hibernate的设置注入
(这里属性名必须写全,不然会抛出异常)
再将hbm文件的位置注入,Spring会自动读取。
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="mappingDirectoryLocations" value="classpath:com/zlq/domain"/>
</bean>
2.使用HibernateTemplate
想要使用HibernateTemplate需要继承HibernateDaoSupport类,并且需要注入sessionFactory。
<bean name="studentDao" class="com.zlq.dao.StudentDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
@Component("studentDao")
public class StudentDaoImpl extends HibernateDaoSupport implements StudentDao {
@Override
public void saveStudent(Student student) {
getHibernateTemplate().save(student);
}
@Override
public Student getStudentById(int id) {
return getHibernateTemplate().execute(new HibernateCallback<Student>() {
@Override
public Student doInHibernate(Session session) throws HibernateException {
return session.get(Student.class, id);
}
});
}
}
测试
将之前配置的StudentDaoImpl注入进测试类中
@Resource(name = "studentDao")
private StudentDao studentDao;
然后在测试方法中进行查找操作的测试。还有一个保存student的方法一执行就会抛出异常,因为涉及对数据进行修改的操作需要事务的存在。
@org.junit.Test
public void test1() {
System.out.println(studentDao.getStudentById(1));
}
如果控制台成功打印sql,并且打印对象,说明整合成功。
使用SpringAOP事务
不管使用什么方式配置SpringAOP事务,都需要配置一个TransactionManager。在Hibernate中,是HibernateTransactionManager。
<bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
打开注解配置事务
<tx:annotation-driven transaction-manager="transactionManager"/>
事务注解可以添加在方法上,也可以添加在类上。如果添加在类上,就是类中全部的方法生效。
@Component("studentService")
@Transactional(readOnly = true,isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED)
public class StudentServiceImpl implements StudentService {
@Resource(name = "studentDao")
private StudentDao studentDao;
@Override
public Student getStudent(int id) {
Student student = studentDao.getStudentById(id);
if (student == null) {
throw new RuntimeException("学生不存在");
}
return student;
}
@Override
@Transactional(readOnly = false,isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED)
public void saveStudent(Student student) {
studentDao.saveStudent(student);
}
}
再类上注释之后,还可以继续在方法上注释,覆盖掉原来类上注释对这个方法事务操作的设置。
将StudentServiceImpl注入测试类,进行测试。
@Resource(name = "studentService")
private StudentService studentService;
@org.junit.Test
public void test2() {
System.out.println(studentService.getStudent(1));
Student student = new Student();
student.setName("jack");
student.setPassword("jack");
studentService.saveStudent(student);
}
之前因为没有开启事务而无法运行的保存操作现在也可以运行了,如果控制台打印sql和被查询对象,数据库中多了一条数据,那么说明SpringAOP事务配置成功。
扩大session范围
由于Hibernate懒加载机制的存在,查询返回的是一个代理对象,只有真正使用到它的时候才回去查询,而这个时候session可能已经关闭,所以需要扩大session的作用范围。操作很简单,配置一个filter即可。
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
整合测试
如果没有servlet和jsp jar包,可从tomcat目录下的lib中找到,手动导入
在页面上输入id来查询学生,如果学生不存在,显示错误信息。
查询页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>查询</title>
</head>
<body>
<form action="studentAction.action">
输入查询id<input type="text" name="id">
<input type="submit" value="ok">
</form>
<s:property value="exception.message"/>
</body>
</html>
结果页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<% out.print(session.getAttribute("student"));%>
</body>
</html>
action
@Component("studentAction")
public class StudentAction extends ActionSupport {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Resource(name = "studentService")
private StudentService studentService;
@Override
public String execute() throws Exception {
ActionContext actionContext = ActionContext.getContext();
Student student = studentService.getStudent(id);
actionContext.getSession().put("student", student);
return SUCCESS;
}
}
配置action及异常处理
<global-exception-mappings>
<exception-mapping exception="java.lang.RuntimeException" result="error"/>
</global-exception-mappings>
<action name="studentAction" class="studentAction" method="execute">
<result name="success">/success.jsp</result>
<result name="error">/index.jsp</result>
</action>
开启服务器,进行测试!
查询成功!
如果输入id为7(不存在),会返回查询页面,并且打印错误信息