十七 Spring2.5+JPA+Struts1.3整合开发 第一步 加入spring的jar包 Spring安装包下的 dist\spring.jar dist\modules\spring-webmvc-struts.jar lib\jakarta-commons\commons-logging.jar、commons-dbcp.jar、commons-pool.jar lib\aspectj\aspectjweaver.jar、aspectjrt.jar lib\cglib\cglib-nodep-2.1_3.jar lib\j2ee\common-annotations.jar lib\log4j\log4j-1.2.15.jar 加入jpa的hibernate的实现包 这里JPA的实现采用hibernate,需要使用到下面的jar文件 Hiberante核心包(8个文件) hibernate-distribution-3.3.1.GA --------------------------------------------- hibernate3.jar lib\bytecode\cglib\hibernate-cglib-repack-2.1_3.jar lib\required\*.jar Hiberante注解包(3个文件):hibernate-annotations-3.4.0.GA ------------------------------------------------------------------------------------ hibernate-annotations.jar lib\ejb3-persistence.jar、hibernate-commons-annotations.jar Hibernate针对JPA的实现包(3个文件):hibernate-entitymanager-3.4.0.GA ------------------------------------------------------------------------------------------------------ hibernate-entitymanager.jar lib\test\log4j.jar、slf4j-log4j12.jar 第二步 加入spring的配置文件 beans.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- 启动注解依赖注入 --> <context:annotation-config/> <!-- 作用:跟hibernate的sessionFactory的作用是一样的,是一个连接工厂的对象,使用的是spring的jap的连接工厂 --> <!-- persistenceUnitName 持久化单元名称 这个是要在src的META-INF配置 --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <property name="persistenceUnitName" value="itcast"/> </bean> <!-- 配置jpa的事务管理容器 --> <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!-- 开启注解方式启动事务管理 --> <tx:annotation-driven transaction-manager="txManager"/> </beans> 第三步:在src的META-INF配置 META-INF目录下放置persistence.xml <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <!--persistence-unit 这里就是持久化单元的配置 单元的名称是 itcast --> <persistence-unit name="itcast" transaction-type="RESOURCE_LOCAL"> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> <property name="hibernate.connection.driver_class" value="org.gjt.mm.mysql.Driver"/> <property name="hibernate.connection.username" value="root"/> <property name="hibernate.connection.password" value="root"/> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/itcast?useUnicode=true&characterEncoding=UTF-8"/> <property name="hibernate.max_fetch_depth" value="3"/> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence> 第四步 建立实体bean package cn.itcast.bean; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; /** * 利用注解 表明当前的Person是一个实体bean * @author Administrator * */ @Entity public class Person implements Serializable { private Integer id; private String name; public Person(){} public Person(String name){ this.name=name; } /** * Id 实体标识 * GeneratedValue 指定主键生成策略 * @return */ @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } /** * Column 指定获取name的映射的列名 并指定列值长度 并指定其列值是否允许为空 * @return */ @Column(length=10,nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } } 第五步 建立服务bean PersonServiceBean package cn.itcast.service.impl; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import cn.itcast.bean.Person; import cn.itcast.service.PersonService; /** * @Transactional 这个注解用来为这个服务开启事务 * @author Administrator * */ @Transactional public class PersonServiceBean implements PersonService { /** * @PersistenceContext 用来注入EntityManager对象 * 原理:要这个注入 到这个service spring会从spring的配置文件中的entityManagerFactory * 得到EntityManager对象 */ @PersistenceContext EntityManager em; public void save(Person person){ em.persist(person); } public void update(Person person){ em.merge(person); } public void delete(Integer id){ em.remove(em.getReference(Person.class, id)); } /** * 指定当前的方法不需要开启事务 并且设定为只读 */ @Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true) public Person getPerson(Integer personid){ return em.find(Person.class, personid); } @Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true) @SuppressWarnings("unchecked") public List<Person> getPersons(){ //这里的查询语句的from 后 必须是实体类名 return em.createQuery("select o from Person o").getResultList(); } } 第六步 建立相应的接口 package cn.itcast.service; import java.util.List; import cn.itcast.bean.Person; public interface PersonService { public void save(Person person); public void update(Person person); public void delete(Integer id); public Person getPerson(Integer personid); @SuppressWarnings("unchecked") public List<Person> getPersons(); } 做测试类 package junit.test; import static org.junit.Assert.*; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.itcast.bean.Person; import cn.itcast.service.PersonService; public class PersonServiceBeanTest { private static PersonService personservice; @BeforeClass public static void setUpBeforeClass() throws Exception { try { AbstractApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); personservice=(PersonService)context.getBean("personService"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Test public void testSave() { personservice.save(new Person("小叶")); } @Test public void testUpdate() { fail("Not yet implemented"); } @Test public void testDelete() { fail("Not yet implemented"); } @Test public void testGetPerson() { fail("Not yet implemented"); } @Test public void testGetPersons() { fail("Not yet implemented"); } } 到这里spring+jpa的集成方式就已经完成了 现在我们来集成struts 第七步:集成struts 加入struts的jar包到lib目录下 除struts中的antlr-2.7.2.jar这个包不能加入外 因为这个包在spring中已经加入了 为避免冲突,不需要加入进来 第八步 添加spring到web容器中,让web容器去实例化这个spring 同时指定实例化的spring添加到action范围中,以后我们的web应用就可以去得到spring容器 <!-- 指定spring的配置文件,默认从web根目录寻找配置文件,我们可以通过spring提供的classpath:前缀指定从类路径下寻找 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:beans.xml</param-value> </context-param> <!-- 对Spring容器进行实例化 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> 在web容器中配置struts, <servlet> <servlet-name>struts</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> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>struts</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> 在struts配置文件中添加进spring的请求控制器,该请法语控制器会先根据action的path属性值到spring容器中寻找跟该属性值同名的bean。如果寻找到即使用该bean处理用户请求 <controller> <set-property property="processorClass" value="org.springframework.web.struts.DelegatingRequestProcessor"/> </controller> 第九步 现在我们来做一个action 测试一下 package cn.itcast.action; import javax.annotation.Resource; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import cn.itcast.service.PersonService; public class PersonAction extends Action { @Resource PersonService personService; @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { request.setAttribute("persons", personService.getPersons()); return mapping.findForward("list"); } } 并把这个action中交给spring管理 同时也配置到struts-config.xml <bean name="/person/list" class="cn.itcast.action.PersonAction"/> 现在把这个配置到struts-config.xml <action-mappings> <action path="/person/list" validate="false"> <forward name="list" path="/WEB-INF/page/personlist.jsp"></forward> </action> </action-mappings> 在浏览器中输入 http://localhost:8808/SSJ/person/list.do 现在我们来利用web页面 插入数据会有乱码问题 解决方法 配置spring的过滤器,解决乱码 <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> 好了 jpa是用EntityManager类进行数据的操作的,如果这个EntityManager对象关闭 会出现延迟加载例外 怎么解决呢? 使用spring解决JPA因EntityManager关闭导致的延迟加载例外问题。 <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> 怎么解决struts1的单例模式 因为struts1是线程不安全的,所以要解决这个问题 当struts1的action交给spring管理后,就可以解决这个问题 只需要在spring 管理的action配置中指定其请求范围即可 <bean name="/person/pmessage" class="cn.itcast.action.PersonMessageAction" scope="prototype"></bean> 这个scope指定的范围:request prototype session singleton 四种模式 现在到这里Spring2.5+JPA+Struts1.3整合就已经全部完成了 现在我们来看其配置文件 web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:beans.xml</param-value> </context-param> <!-- 对Spring容器进行实例化 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 从web页面中插入到数据库中会有乱码的出现 所以利用 spring提供的过滤器 可以解决乱码问题--> <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> <!-- jpa是用EntityManager进行数据操作的,如果这个对象关闭,将会出现延迟加载例外 解决方法 --> <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> <!-- 把struts添加到web容器中 --> <servlet> <servlet-name>struts</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> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>struts</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> jpa的配置文件 persistence.xml <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <!--persistence-unit 这里就是持久化单元的配置 单元的名称是 itcast --> <persistence-unit name="itcast" transaction-type="RESOURCE_LOCAL"> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> <property name="hibernate.connection.driver_class" value="org.gjt.mm.mysql.Driver"/> <property name="hibernate.connection.username" value="root"/> <property name="hibernate.connection.password" value="root"/> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8"/> <property name="hibernate.max_fetch_depth" value="3"/> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence> spring的配置文件 beans.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- 启动注解依赖注入 --> <context:annotation-config/> <!-- 作用:跟hibernate的sessionFactory的作用是一样的,是一个连接工厂的对象,使用的是spring的jap的连接工厂 --> <!-- persistenceUnitName 持久化单元名称 这个是要在src的META-INF配置 --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <property name="persistenceUnitName" value="itcast"/> </bean> <!-- 配置jpa的事务管理容器 --> <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!-- 开启注解方式启动事务管理 --> <tx:annotation-driven transaction-manager="txManager"/> <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"/> <bean name="/person/list" class="cn.itcast.action.PersonAction"/> <bean name="/person/pmessage" class="cn.itcast.action.PersonMessageAction" scope="prototype"></bean> </beans> struts1的配置文件 <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"> <struts-config> <form-beans> <form-bean name="PersonForm" type="cn.itcast.formbean.PersonForm"/> </form-beans> <global-forwards> <forward name="message" path="/WEB-INF/page/message.jsp"></forward> </global-forwards> <action-mappings> <action path="/person/list" validate="false"> <forward name="list" path="/WEB-INF/page/personlist.jsp"></forward> </action> <action path="/person/pmessage" validate="false" parameter="method" scope="request" name="PersonForm"></action> </action-mappings> <!-- 在struts配置文件中添加进spring的请求控制器,该请法语控制器会先根据action的path--> <!-- 属性值到spring容器中寻找跟该属性值同名的bean。如果寻找到即使用该bean处理用户请求 --> <controller> <set-property property="processorClass" value="org.springframework.web.struts.DelegatingRequestProcessor"/> </controller> </struts-config> end 完毕!