struts2+spring+jap整合案例

来源:互联网 发布:淘宝网老爹商城 编辑:程序博客网 时间:2024/05/29 10:00

这几天刚去新公司上班,要熟悉下公司的开发平台和框架,框架是基于struts2+spring+jap的,前端还有easyui,这些我都不是很熟悉,最恶心的是maven。尽管如此,我还是得在这个周六日把他们过一遍熟悉一下,现在我把总结到的知识点和如何搭建一个struts2,spring,jap的案例写出来。


首先导入jar包,我是直接从网上找的现成的jar包:



编写beans.xml或者applicationContext.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:util="http://www.springframework.org/schema/util"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-2.0.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"></beans>

下面 我们会在这个文件中依次加入如下内容:


1、spring的组件扫描机制
<!-- 有了<context:component-scan>,另一个<context:annotation-config/>标签可以移除掉 --><context:component-scan base-package="cn.lvpeng"></context:component-scan>

2、jpa的相关配置

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"><property name="persistenceUnitName" value="lvpeng"/><!--      指定persistence.xml的配置 默认是在classpath下<property name="persistenceXmlLocation" value="classpath:/META-INF/persistence.xml" />  指定数据源 也可以在persistence.xml中配置<property name="dataSource" ref="dataSource" />选配属性        <property name="jpaVendorAdapter">              <bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter">                  <property name="showSql" value="false"/>                  <property name="generateDdl" value="false"/>                  <property name="databasePlatform" value="org.apache.openjpa.jdbc.sql.MySQLDictionary"/>              </bean>          </property>  --></bean>

3、事务处理器配置

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"><property name="entityManagerFactory" ref="entityManagerFactory"/></bean>

4、使用基于注解的方式管理事务

<!-- 对@Transactional这个注解进行的驱动,这是基于注解的方式使用事务配置声明,这样在具体应用中可以指定对哪些方法使用事务。 --><tx:annotation-driven transaction-manager="transactionManager"/>

5、相关bean配置
<bean id="userAction" class="cn.lvpeng.web.action.UserAction" scope="prototype">



其中第二点,对jpa的配置中,我们需要针对entityManagerFactory,他的实现是class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"该实现默认会去寻找classpath:/META-INF/路径下的persistence.xml,读取相关配置,其中会根据<property name="persistenceUnitName" value="lvpeng"/>的配置读取persistenceUnitName为lvpeng的配置内容,该文件的位置在:


内容如下:

<?xml version="1.0" encoding="UTF-8"?><persistence version="2.0" 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_2_0.xsd">     <!-- name属性用于定义持久化单元的名字 (name必选,空值也合法);      <property name="persistenceUnitName" value="itcast"/>     transaction-type 指定事务类型(可选) -->  <persistence-unit name="lvpeng" transaction-type="RESOURCE_LOCAL">   <!-- 描述信息(可选)   <description></description>  -->      <!-- javax.persistence.PersistenceProvider接口的一个实现类(可选)      <provider>org.hibernate.ejb.HibernatePersistence</provider>    -->           <!-- Jta-data-source和 non-jta-data-source用于分别指定持久化提供商使用的JTA和/或non-JTA数据源的全局JNDI名称(可选)     <jta-data-source>java:/MySqlDS</jta-data-source>      <non-jta-data-source></non-jta-data-source>    -->        <!-- 声明orm.xml所在位置.(可选)     <mapping-file>product.xml</mapping-file>    -->       <!-- 以包含persistence.xml的jar文件为基准的相对路径,添加额外的jar文件.(可选)     <jar-file>../lib/model.jar</jar-file>    -->       <!-- 显式列出实体类,在Java SE 环境中应该显式列出.(可选)    <class>com.domain.User</class>   <class>com.domain.Product</class>    -->       <!-- 声明是否扫描jar文件中标注了@Enity类加入到上下文.若不扫描,则如下:(可选)     <exclude-unlisted-classes>false</exclude-unlisted-classes>    -->       <!-- 厂商专有属性(可选) -->    <properties>          <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver" />          <property name="hibernate.connection.username" value="damaib2b" />          <property name="hibernate.connection.password" value="damaib2b" />          <property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:ORCL" />          <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" />          <property name="hibernate.show_sql" value="true" />          <property name="hibernate.hbm2ddl.auto" value="update"/>         </properties>            </persistence-unit>        </persistence>  

注释写的都已经很清楚了,仔细看看就可以了。下面的properties是数据源的相关信息,该信息也可以配置在beans.xml中。这个随意。使用的数据库相关驱动要加入到classpath下。


另外注意hibernate.hbm2ddl.auto的设置有如下几个value:

create:
    每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop:
    每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
update:
    最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
validate:
    每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。


这里我们使用的是update,会自动创建表。


通过上述的配置,我们基本上把spring和jpa配置完毕了。现在我们再来配置struts.xml文件:

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"    "http://struts.apache.org/dtds/struts-2.0.dtd"><struts>    <!-- 将struts2委托Spring管理 -->    <constant name="struts.objectFactory" value="spring" />    <constant name="struts.devMode" value="true" />        <package name="user" extends="struts-default">    <action name="user_*" class="userAction" method="{1}">    <result name="add">/WEB-INF/page/user/register.jsp</result>        <result name="success">/WEB-INF/page/user/regSuccess.jsp</result>    <result name="fail">/WEB-INF/page/user/regFail.jsp</result>    </action>    </package></struts>

最后修改web.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">    <welcome-file-list>        <welcome-file>index.html</welcome-file>        <welcome-file>index.jsp</welcome-file>    </welcome-file-list><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>    <!-- 配置Spring监听器  默认从根目录开始寻找配置文件,我们可以通过spring提供的classpath:前缀指定从类路径下寻找 -->    <listener>        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>    </listener>    <!-- 配置Spring应用上下文文件的位置 -->    <context-param>        <param-name>contextConfigLocation</param-name>        <param-value>classpath:beans.xml</param-value>    </context-param>    <!-- 配置Struts2 -->    <filter>        <filter-name>struts2</filter-name>        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>    </filter>    <filter-mapping>        <filter-name>struts2</filter-name>        <url-pattern>*.action</url-pattern>    </filter-mapping>   </web-app>

这样我们的配置就OK了,下面我们来写几个类,分别是dao层,service层,action层的测试类,需要注意的是,我们会使用注解来完全相关的编写,首先看我们的实体类User:

package cn.lvpeng.bean;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Table;@Entity //使用此批注将普通的旧式 Java 对象 (POJO) 类指定为实体,以便可以将它用于 JPA 服务@Table(name="d_user") //默认情况下,JPA 持续性提供程序假设实体名称对应于同名的数据库表,且实体的数据成员名称对应于同名的数据库列。public class User {@Id@Column(length=20,nullable=false)private String username;@Column(length=20,nullable=false)private String password;public User(String username,String password){this.username = username;this.password = password;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}

再来看一下我们的service层代码:

package cn.lvpeng.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import cn.lvpeng.base.BaseDao;import cn.lvpeng.bean.User;@Service@Transactionalpublic class UserServiceImpl<T extends User> implements IUserService<T> {@Autowiredpublic BaseDao<User> baseDao;public void saveUser(T entity){this.baseDao.save(entity);if(entity.getUsername().equals("name5")){this.baseDao.delete(entity);}}}

这里我们使用了多处注解 @service不用说,@Transaction是管理事务的注解 而@Autowired是自动装配。在这里我们可以延伸下@Transaction注解的其他属性:

@Transactional     
propagation: 指定事务定义中使用的传播
isolation: 指定事务的隔离级别
timeout: 超时时间
readonly : 如果为true, 事务标致为只读
noRollbackFor: 目标方法可抛出的异常所构成的数组,但通知仍会提交事务
rollbackFor: 异常所构成的数组,如果目标方法抛出了这些异常,通知就会回滚

service中调用了dao层的对象,dao层代码如下:

package cn.lvpeng.base;import java.util.LinkedHashMap;import java.util.List;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;import javax.persistence.Query;import org.springframework.stereotype.Component;import cn.lvpeng.service.QueryResult;@Componentpublic class BaseDaoImpl<T> implements BaseDao<T> {//@Resource可以理解为资源->数据源->也就是数据连接,基本上就是告诉程序数据库在哪里//@PersistenceContext  注入的是实体管理器,执行持久化操作的,需要配置文件persistence.xml。@PersistenceContext protected EntityManager em;@Overridepublic void delete(T entity) {em.remove(em.merge(entity));}@Overridepublic void save(T entity) {em.persist(entity);}@Overridepublic void update(T entity) {em.merge(entity);}@Overridepublic T find(Class<T> clazz, Integer id) {return em.find(clazz, id);}/** *  * 总记录 *  * */@Overridepublic QueryResult<T> getScrollData(Class<T> clazz){return getScrollData(clazz,-1,-1,null,null,null);}/** *  * 记录分页 *  * */@Overridepublic QueryResult<T> getScrollData(Class<T> clazz,int startIndex,int maxSize){return getScrollData(clazz,startIndex,maxSize,null,null,null);}/** *  * 记录分页,排序 *  * */@Overridepublic QueryResult<T> getScrollData(Class<T> clazz,int startIndex,int maxSize,LinkedHashMap<String,String> orderby){return getScrollData(clazz,startIndex,maxSize,null,null,orderby);}/** *  * 记录分页,条件查询,排序 *  * */@SuppressWarnings("unchecked")@Overridepublic QueryResult<T> getScrollData(Class<T> clazz, int startIndex,int maxSize,String whereJPQL,Object[] params,LinkedHashMap<String, String> orderby) {String orderbyString=getOrderby(orderby);//设置排序方式String where=(whereJPQL!=null&&!"".equals(whereJPQL.trim()))?"where "+whereJPQL:"";String JPQL="from "+clazz.getName()+" o "+where+orderbyString;List<T> list=null;Query query1=em.createQuery(JPQL);setParams(query1,params);//设置参数if(startIndex!=-1&&maxSize!=-1){query1.setFirstResult(startIndex);query1.setMaxResults(maxSize);}list=query1.getResultList();Query query2=em.createQuery("select count(*) from "+clazz.getName()+" o "+where);setParams(query2, params);long totalRecord=(Long)query2.getSingleResult();QueryResult<T> result=new QueryResult<T>();result.setResult(list);result.setTotalRecord(totalRecord);return result;}/* *  * 设置排序条件 *  * */private String getOrderby(LinkedHashMap<String, String> orderby) {StringBuilder str=new StringBuilder();String orderbyString="";if(orderby!=null&&orderby.size()>0){str.append(" order by o.");for(String key:orderby.keySet()){str.append(key).append(" ").append(orderby.get(key)).append(",o.");}orderbyString=str.substring(0, str.length()-3);}return orderbyString;}/* *  * 设置查询条件参数。 *  * */private void setParams(Query query, Object[] params) {if(params!=null&¶ms.length!=0){for(int i=0;i<params.length;i++){query.setParameter(i+1, params[i]);}}}}

这里面,我们要区分开两个注解他们使用的场景不同:

@Resource可以理解为资源->数据源->也就是数据连接,基本上就是告诉程序数据库在哪里

@PersistenceContext  注入的是实体管理器,执行持久化操作的,需要配置文件persistence.xml。



这样我们的代码和配置基本完成了,现在我们使用单元测试,看一下能否跑通代码:

package test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.lvpeng.bean.User;import cn.lvpeng.service.IUserService;public class Test {public static void main(String[] args) {ApplicationContext act =new ClassPathXmlApplicationContext("beans.xml");IUserService<User> buyerService = (IUserService<User>)act.getBean("userServiceImpl");for(int i=0;i<20;i++){//Buyer b = new Buyer();//b.setUsername("gege"+i);buyerService.saveUser(new User("name"+i,"7387121"));}}}

我们往数据库中插入20条数据,为了测试其事务管理是否正确,我们在service层的addUser方法中加入以下判断:

public void saveUser(T entity){this.baseDao.save(entity);if(entity.getUsername().equals("name5")){this.baseDao.delete(entity);}}

如果执行成功,在数据库中不会找到name5的行记录,执行完毕,查看结果:



执行成功。struts环境配置也成功(测试略)



下载地址:http://download.csdn.net/detail/qq522935502/6494525