这几天刚去新公司上班,要熟悉下公司的开发平台和框架,框架是基于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.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://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
@Transactional
public class UserServiceImpl<T extends User> implements IUserService<T> {
@Autowired
public 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;
@Component
public class BaseDaoImpl<T> implements BaseDao<T> {
//@Resource可以理解为资源->数据源->也就是数据连接,基本上就是告诉程序数据库在哪里
//@PersistenceContext 注入的是实体管理器,执行持久化操作的,需要配置文件persistence.xml。
@PersistenceContext
protected EntityManager em;
@Override
public void delete(T entity) {
em.remove(em.merge(entity));
}
@Override
public void save(T entity) {
em.persist(entity);
}
@Override
public void update(T entity) {
em.merge(entity);
}
@Override
public T find(Class<T> clazz, Integer id) {
return em.find(clazz, id);
}
/**
*
* 总记录
*
* */
@Override
public QueryResult<T> getScrollData(Class<T> clazz){
return getScrollData(clazz,-1,-1,null,null,null);
}
/**
*
* 记录分页
*
* */
@Override
public QueryResult<T> getScrollData(Class<T> clazz,int startIndex,int maxSize){
return getScrollData(clazz,startIndex,maxSize,null,null,null);
}
/**
*
* 记录分页,排序
*
* */
@Override
public QueryResult<T> getScrollData(Class<T> clazz,int startIndex,int maxSize,LinkedHashMap<String,String> orderby){
return getScrollData(clazz,startIndex,maxSize,null,null,orderby);
}
/**
*
* 记录分页,条件查询,排序
*
* */
@SuppressWarnings("unchecked")
@Override
public 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