Top

JAVA SSH DAY01

  1. 使用Spring整合Hibernate
  2. 使用Spring整合Struts2
  3. SSH整合

1 使用Spring整合Hibernate

1.1 问题

使用Spring整合Hibernate,并实现资费表的增、删、改、查。

1.2 方案

Spring整合Hibernate的步骤:

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:导包

创建WEB项目SpringHibernate,并导入数据库驱动包、Hibernate开发包以及Spring开发包,完成后项目中包结构如下图

图-1

步骤二:配置applicationContext.xml

引入Spring配置文件applicationContext.xml,放在src根路径下。在该文件中配置数据源、SessionFactory、开启组件扫描、声明式事务,代码如下

<?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:tx="http://www.springframework.org/schema/tx" 
		xmlns:aop="http://www.springframework.org/schema/aop"
		xmlns:context="http://www.springframework.org/schema/context" 
		xmlns:jee="http://www.springframework.org/schema/jee"
		xsi:schemaLocation="
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/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/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

	<!-- 配置数据源 -->
	<bean id="ds" 
		class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<!-- 配置连接参数 -->
		<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe"/>
		<property name="driverClass" value="oracle.jdbc.OracleDriver"/>
		<property name="user" value="lhh"/>
		<property name="password" value="123456"/>
		<!-- 配置连接池 -->
		<property name="initialPoolSize" value="3"/>
		<property name="maxPoolSize" value="10"/>
		<property name="minPoolSize" value="1"/>
		<property name="acquireIncrement" value="3"/>
		<property name="maxIdleTime" value="60"/>
	</bean>
	
	<!-- 配置SessionFactory -->
	<bean id="sessionFactory" 
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!-- 依赖数据源 -->
		<property name="dataSource" ref="ds"/>
		<!-- Hibernate框架相关配置 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.OracleDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.formate_sql">true</prop>
			</props>
		</property>
	</bean>
	
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>

	<!-- 声明式事务管理,采用AOP形式切入 -->
	<bean id="txManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="load*" read-only="true" />
			<tx:method name="execute" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>
	<aop:config proxy-target-class="true">
		<aop:advisor advice-ref="txAdvice" 
			pointcut="within(com.tarena.action.*)" />
	</aop:config>

</beans>

步骤三:创建实体类和映射关系文件

创建com.tarena.entity包,并在包下创建资费实体类和映射关系文件,这两个文件可以从NETCTOSS项目中复制过来。其中实体类Cost代码如下

package com.tarena.entity;

import java.sql.Date;

/**
 * 资费实体类
 */
public class Cost {

	private Integer id;// 主键
	private String name;// 资费名称
	private Integer baseDuration;// 在线时长
	private Double baseCost;// 基本费用
	private Double unitCost;// 单位费用
	private String status;// 状态
	private String descr;// 资费说明
	private Date createTime;// 创建日期
	private Date startTime;// 启用日期
	private String costType;// 资费类型

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getBaseDuration() {
		return baseDuration;
	}

	public void setBaseDuration(Integer baseDuration) {
		this.baseDuration = baseDuration;
	}

	public Double getBaseCost() {
		return baseCost;
	}

	public void setBaseCost(Double baseCost) {
		this.baseCost = baseCost;
	}

	public Double getUnitCost() {
		return unitCost;
	}

	public void setUnitCost(Double unitCost) {
		this.unitCost = unitCost;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getDescr() {
		return descr;
	}

	public void setDescr(String descr) {
		this.descr = descr;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public String getCostType() {
		return costType;
	}

	public void setCostType(String costType) {
		this.costType = costType;
	}

}

映射关系文件Cost.hbm.xml代码如下

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.tarena.entity.Cost" table="cost">
		<id name="id" type="integer" column="id">
			<!-- 用来指明主键的生成方式 -->
			<generator class="sequence">
				<param name="sequence">cost_seq</param>
			</generator>
		</id>
		
		<property name="name" 
			type="string" column="name" />
		<property name="baseDuration" 
			type="integer" column="base_duration" />
		<property name="baseCost" 
			type="double" column="base_cost" />
		<property name="unitCost" 
			type="double" column="unit_cost" />
		<property name="status" 
			type="string" column="status" />
		<property name="descr" 
			type="string" column="descr" />
		<property name="createTime" 
			type="date" column="creatime" />
		<property name="startTime" 
			type="date" column="startime" />
		<property name="costType" 
			type="string" column="cost_type" />
	</class>
</hibernate-mapping>

在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:tx="http://www.springframework.org/schema/tx" 
		xmlns:aop="http://www.springframework.org/schema/aop"
		xmlns:context="http://www.springframework.org/schema/context" 
		xmlns:jee="http://www.springframework.org/schema/jee"
		xsi:schemaLocation="
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/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/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

	<!-- 配置数据源 -->
	<bean id="ds" 
		class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<!-- 配置连接参数 -->
		<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe"/>
		<property name="driverClass" value="oracle.jdbc.OracleDriver"/>
		<property name="user" value="lhh"/>
		<property name="password" value="123456"/>
		<!-- 配置连接池 -->
		<property name="initialPoolSize" value="3"/>
		<property name="maxPoolSize" value="10"/>
		<property name="minPoolSize" value="1"/>
		<property name="acquireIncrement" value="3"/>
		<property name="maxIdleTime" value="60"/>
	</bean>
	
	<!-- 配置SessionFactory -->
	<bean id="sessionFactory" 
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!-- 依赖数据源 -->
		<property name="dataSource" ref="ds"/>
		<!-- Hibernate框架相关配置 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.OracleDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.formate_sql">true</prop>
			</props>
		</property>
#cold_bold		<property name="mappingResources">
#cold_bold			<list>
#cold_bold				<value>com/tarena/entity/Cost.hbm.xml</value>
#cold_bold			</list>
#cold_bold		</property>
	</bean>
	
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>

	<!-- 声明式事务管理,采用AOP形式切入 -->
	<bean id="txManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="load*" read-only="true" />
			<tx:method name="execute" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>
	<aop:config proxy-target-class="true">
		<aop:advisor advice-ref="txAdvice" 
			pointcut="within(com.tarena.action.*)" />
	</aop:config>

</beans>

步骤四:

创建包com.tarena.dao,并在包下创建资费DAO接口,声明增、删、改、查的方法,代码如下

package com.tarena.dao;

import java.util.List;

import com.tarena.entity.Cost;

public interface ICostDao {

	List<Cost> findAll();

	Cost findById(int id);

	void save(Cost cost);

	void update(Cost cost);

	void delete(int id);

}

创建DAO实现类CostDaoImpl,继承于HibernateDaoSupport,实现接口ICostDao。代码如下

package com.tarena.dao;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.tarena.entity.Cost;

@Repository
public class CostDaoImpl 
	extends HibernateDaoSupport implements ICostDao {
	
	@Resource
	public void setSF(SessionFactory sf) {
		super.setSessionFactory(sf);
	}

	@Override
	public List<Cost> findAll() {
		String hql = "from Cost";
		return getHibernateTemplate().find(hql);
	}

	@Override
	public Cost findById(int id) {
		return (Cost) getHibernateTemplate().get(Cost.class, id);
	}

	@Override
	public void save(Cost cost) {
		getHibernateTemplate().save(cost);
	}

	@Override
	public void update(Cost cost) {
		getHibernateTemplate().update(cost);
	}

	@Override
	public void delete(int id) {
		Cost c = new Cost();
		c.setId(id);
		getHibernateTemplate().delete(c);
	}

}

步骤五:测试

在com.tarena.dao包下,创建JUNIT测试类TestDao,分别写出资费的增、删、改

查测试方法,并执行这些方法进行测试。代码如下

package com.tarena.dao;

import java.util.List;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.tarena.entity.Cost;

public class TestDao {
	
	private String conf = "applicationContext.xml";

	@Test
	public void test1() {
		ApplicationContext ctx = 
			new ClassPathXmlApplicationContext(conf);
		ICostDao dao = (ICostDao) ctx.getBean("costDaoImpl");
		List<Cost> list = dao.findAll();
		for(Cost c : list) {
			System.out.println(
				c.getId() + " " + c.getName()
			);
		}
	}
	
	@Test
	public void test2() {
		ApplicationContext ctx = 
			new ClassPathXmlApplicationContext(conf);
		ICostDao dao = (ICostDao) ctx.getBean("costDaoImpl");
		Cost c = dao.findById(1);
		System.out.println(
			c.getId() + " " + c.getName()
		);
	}
	
	@Test
	public void test3() {
		ApplicationContext ctx = 
			new ClassPathXmlApplicationContext(conf);
		ICostDao dao = (ICostDao) ctx.getBean("costDaoImpl");
		Cost c = new Cost();
		c.setName("aaa");
		c.setBaseDuration(20);
		c.setBaseCost(2.0);
		c.setUnitCost(0.2);
		c.setCostType("1");
		c.setStatus("0");
		dao.save(c);
	}
	
	@Test
	public void test4() {
		ApplicationContext ctx = 
			new ClassPathXmlApplicationContext(conf);
		ICostDao dao = (ICostDao) ctx.getBean("costDaoImpl");
		Cost c = dao.findById(351);
		c.setName("bbb");
		dao.update(c);
	}
	
	@Test
	public void test5() {
		ApplicationContext ctx = 
			new ClassPathXmlApplicationContext(conf);
		ICostDao dao = (ICostDao) ctx.getBean("costDaoImpl");
		dao.delete(351);
	}

}

1.4 完整代码

本案例的完整代码如下所示:

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:tx="http://www.springframework.org/schema/tx" 
		xmlns:aop="http://www.springframework.org/schema/aop"
		xmlns:context="http://www.springframework.org/schema/context" 
		xmlns:jee="http://www.springframework.org/schema/jee"
		xsi:schemaLocation="
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/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/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

	<!-- 配置数据源 -->
	<bean id="ds" 
		class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<!-- 配置连接参数 -->
		<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe"/>
		<property name="driverClass" value="oracle.jdbc.OracleDriver"/>
		<property name="user" value="lhh"/>
		<property name="password" value="123456"/>
		<!-- 配置连接池 -->
		<property name="initialPoolSize" value="3"/>
		<property name="maxPoolSize" value="10"/>
		<property name="minPoolSize" value="1"/>
		<property name="acquireIncrement" value="3"/>
		<property name="maxIdleTime" value="60"/>
	</bean>
	
	<!-- 配置SessionFactory -->
	<bean id="sessionFactory" 
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!-- 依赖数据源 -->
		<property name="dataSource" ref="ds"/>
		<!-- Hibernate框架相关配置 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.OracleDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.formate_sql">true</prop>
			</props>
		</property>
		<property name="mappingResources">
			<list>
				<value>com/tarena/entity/Cost.hbm.xml</value>
			</list>
		</property>
	</bean>
	
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>

	<!-- 声明式事务管理,采用AOP形式切入 -->
	<bean id="txManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="load*" read-only="true" />
			<tx:method name="execute" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>
	<aop:config proxy-target-class="true">
		<aop:advisor advice-ref="txAdvice" 
			pointcut="within(com.tarena.action.*)" />
	</aop:config>

</beans>

实体类Cost完整代码如下

package com.tarena.entity;

import java.sql.Date;

/**
 * 资费实体类
 */
public class Cost {

	private Integer id;// 主键
	private String name;// 资费名称
	private Integer baseDuration;// 在线时长
	private Double baseCost;// 基本费用
	private Double unitCost;// 单位费用
	private String status;// 状态
	private String descr;// 资费说明
	private Date createTime;// 创建日期
	private Date startTime;// 启用日期
	private String costType;// 资费类型

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getBaseDuration() {
		return baseDuration;
	}

	public void setBaseDuration(Integer baseDuration) {
		this.baseDuration = baseDuration;
	}

	public Double getBaseCost() {
		return baseCost;
	}

	public void setBaseCost(Double baseCost) {
		this.baseCost = baseCost;
	}

	public Double getUnitCost() {
		return unitCost;
	}

	public void setUnitCost(Double unitCost) {
		this.unitCost = unitCost;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getDescr() {
		return descr;
	}

	public void setDescr(String descr) {
		this.descr = descr;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public String getCostType() {
		return costType;
	}

	public void setCostType(String costType) {
		this.costType = costType;
	}

}

映射关系文件Cost.hbm.xml完整代码如下

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.tarena.entity.Cost" table="cost">
		<id name="id" type="integer" column="id">
			<!-- 用来指明主键的生成方式 -->
			<generator class="sequence">
				<param name="sequence">cost_seq</param>
			</generator>
		</id>
		
		<property name="name" 
			type="string" column="name" />
		<property name="baseDuration" 
			type="integer" column="base_duration" />
		<property name="baseCost" 
			type="double" column="base_cost" />
		<property name="unitCost" 
			type="double" column="unit_cost" />
		<property name="status" 
			type="string" column="status" />
		<property name="descr" 
			type="string" column="descr" />
		<property name="createTime" 
			type="date" column="creatime" />
		<property name="startTime" 
			type="date" column="startime" />
		<property name="costType" 
			type="string" column="cost_type" />
	</class>
</hibernate-mapping>

DAO接口ICostDao完整代码如下

package com.tarena.dao;

import java.util.List;

import com.tarena.entity.Cost;

public interface ICostDao {

	List<Cost> findAll();

	Cost findById(int id);

	void save(Cost cost);

	void update(Cost cost);

	void delete(int id);

}

DAO实现类CostDaoImpl完整代码如下

package com.tarena.dao;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.tarena.entity.Cost;

@Repository
public class CostDaoImpl 
	extends HibernateDaoSupport implements ICostDao {
	
	@Resource
	public void setSF(SessionFactory sf) {
		super.setSessionFactory(sf);
	}

	@Override
	public List<Cost> findAll() {
		String hql = "from Cost";
		return getHibernateTemplate().find(hql);
	}

	@Override
	public Cost findById(int id) {
		return (Cost) getHibernateTemplate().get(Cost.class, id);
	}

	@Override
	public void save(Cost cost) {
		getHibernateTemplate().save(cost);
	}

	@Override
	public void update(Cost cost) {
		getHibernateTemplate().update(cost);
	}

	@Override
	public void delete(int id) {
		Cost c = new Cost();
		c.setId(id);
		getHibernateTemplate().delete(c);
	}

}

测试类TestDao完整代码如下

package com.tarena.dao;

import java.util.List;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.tarena.entity.Cost;

public class TestDao {
	
	private String conf = "applicationContext.xml";

	@Test
	public void test1() {
		ApplicationContext ctx = 
			new ClassPathXmlApplicationContext(conf);
		ICostDao dao = (ICostDao) ctx.getBean("costDaoImpl");
		List<Cost> list = dao.findAll();
		for(Cost c : list) {
			System.out.println(
				c.getId() + " " + c.getName()
			);
		}
	}
	
	@Test
	public void test2() {
		ApplicationContext ctx = 
			new ClassPathXmlApplicationContext(conf);
		ICostDao dao = (ICostDao) ctx.getBean("costDaoImpl");
		Cost c = dao.findById(1);
		System.out.println(
			c.getId() + " " + c.getName()
		);
	}
	
	@Test
	public void test3() {
		ApplicationContext ctx = 
			new ClassPathXmlApplicationContext(conf);
		ICostDao dao = (ICostDao) ctx.getBean("costDaoImpl");
		Cost c = new Cost();
		c.setName("aaa");
		c.setBaseDuration(20);
		c.setBaseCost(2.0);
		c.setUnitCost(0.2);
		c.setCostType("1");
		c.setStatus("0");
		dao.save(c);
	}
	
	@Test
	public void test4() {
		ApplicationContext ctx = 
			new ClassPathXmlApplicationContext(conf);
		ICostDao dao = (ICostDao) ctx.getBean("costDaoImpl");
		Cost c = dao.findById(351);
		c.setName("bbb");
		dao.update(c);
	}
	
	@Test
	public void test5() {
		ApplicationContext ctx = 
			new ClassPathXmlApplicationContext(conf);
		ICostDao dao = (ICostDao) ctx.getBean("costDaoImpl");
		dao.delete(351);
	}

}

2 使用Spring整合Struts2

2.1 问题

使用Spring整合Struts2,并实现Struts2的HelloWorld案例。

2.2 方案

Spring整合Struts2步骤:

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:导包

创建WEB项目SpringStruts2,并导入Struts2开发包、Spring开发包以及Spring整合Struts2开发包,完成后项目中包结构如下图

图-2

步骤二:配置web.xml

在web.xml中配置一个listener,用于tomcat启动时自动加载Spring。再配置出Struts2的前端控制器,代码如下

<?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">
  <display-name></display-name>	
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- 配置listener,在容器启动时自动加载Spring -->
  <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>
  </context-param>
  
  <!-- 配置Struts2前端控制器 -->
  <filter>
  	<filter-name>Struts2</filter-name>
  	<filter-class>
  		org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
  	</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>Struts2</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
</web-app>

步骤三:配置applicationContext.xml

引入Spring配置文件,放在src根路径下,在该文件下开启组件扫描,代码如下

<?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:tx="http://www.springframework.org/schema/tx" 
		xmlns:aop="http://www.springframework.org/schema/aop"
		xmlns:context="http://www.springframework.org/schema/context" 
		xmlns:jee="http://www.springframework.org/schema/jee"
		xsi:schemaLocation="
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/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/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>

</beans>

步骤四:创建并声明DAO

创建包com.tarena.dao,并在包下创建一个类HelloDao,在这个类中写一个say方法,其返回值为字符串,返回一句话即可。另外要使用Spring注解声明这个DAO组件,将其纳入到Spring容器中,代码如下

package com.tarena.dao;

import org.springframework.stereotype.Repository;

@Repository
public class HelloDao {

	public String say() {
		return "Hello, Spring整合Struts2.";
	}

}

步骤五:创建并声明Action

创建包com.tarena.action,并在包下创建HelloAction,在这个Action的业务方法中,调用HelloDao返回一句话并通过输出属性输出给页面。需要使用Spring注解声明这个Action组件,将其纳入到Spring容器中,另外也需要通过注解将DAO注入进来。代码如下

package com.tarena.action;

import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import com.tarena.dao.HelloDao;

@Controller
public class HelloAction {

	@Resource
	private HelloDao dao;

	private String msg;

	public String execute() {
		// 通过dao获取输出消息
		msg = dao.say();
		return "success";
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

}

步骤六:配置Action

在struts.xml中配置Action。由于使用Spring管理Action,在action元素中通过class属性指定Action类型时,需要指定的是组件的ID。代码如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
    "http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>

	<package name="demo" 
		namespace="/demo" extends="struts-default">
		<!-- 
			由于使用Spring来管理Action,因此需要通过Spring
			容器来创建Action,因此class属性指定的是组件的ID。
		 -->
		<action name="hello" class="helloAction">
			<result name="success">
				/hello.jsp
			</result>
		</action>
	</package>
</struts>

步骤七:创建JSP

在WebRoot下创建hello.jsp,并在这个页面上输出HelloAction中的输出属性,代码如下

<%@page pageEncoding="utf-8" isELIgnored="false"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
</head>
<body>

	<h1>
		<s:property value="msg"/>
	</h1>
	
</body>
</html>

步骤八:测试

部署项目并启动tomcat,访问HelloAction,页面输出效果如下图

图-3

2.4 完整代码

本案例的完整代码如下所示:

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">
  <display-name></display-name>	
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- 配置listener,在容器启动时自动加载Spring -->
  <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>
  </context-param>
  
  <!-- 配置Struts2前端控制器 -->
  <filter>
  	<filter-name>Struts2</filter-name>
  	<filter-class>
  		org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
  	</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>Struts2</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
</web-app>

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:tx="http://www.springframework.org/schema/tx" 
		xmlns:aop="http://www.springframework.org/schema/aop"
		xmlns:context="http://www.springframework.org/schema/context" 
		xmlns:jee="http://www.springframework.org/schema/jee"
		xsi:schemaLocation="
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/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/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>

</beans>

HelloDao完整代码如下

package com.tarena.dao;

import org.springframework.stereotype.Repository;

@Repository
public class HelloDao {

	public String say() {
		return "Hello, Spring整合Struts2.";
	}

}

HelloAction完整代码如下

package com.tarena.action;

import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import com.tarena.dao.HelloDao;

@Controller
public class HelloAction {

	@Resource
	private HelloDao dao;

	private String msg;

	public String execute() {
		// 通过dao获取输出消息
		msg = dao.say();
		return "success";
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

}

struts.xml完整代码如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
    "http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>

	<package name="demo" 
		namespace="/demo" extends="struts-default">
		<!-- 
			由于使用Spring来管理Action,因此需要通过Spring
			容器来创建Action,因此class属性指定的是组件的ID。
		 -->
		<action name="hello" class="helloAction">
			<result name="success">
				/hello.jsp
			</result>
		</action>
	</package>
</struts>

hello.jsp完整代码如下

<%@page pageEncoding="utf-8" isELIgnored="false"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
</head>
<body>

	<h1>
		<s:property value="msg"/>
	</h1>
	
</body>
</html>

3 SSH整合

3.1 问题

使用Spring整合Hibernate及Struts2,实现资费查询功能。

3.2 方案

SSH整合步骤

3.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:导包

创建WEB项目NETCTOSS-SSH,并导入数据库驱动包、Struts2开发包、Hibernate开发包以及Spring开发包,完成后项目中包结构如下图

图-4

注意,Hibernate开发包中的freemarker.jar,与Struts2中的包重复,且版本较低,去掉。Spring开发包中的commons-logging.jar,与Hibernate中的包重复,且版本较低,去掉。

步骤二:使用Spring整合Hibernate

在src根路径下引入并配置applicationContext.xml,并在该文件中配置数据源、SessionFactory、开启组件扫描以及声明式事务,代码如下

<?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:tx="http://www.springframework.org/schema/tx" 
		xmlns:aop="http://www.springframework.org/schema/aop"
		xmlns:context="http://www.springframework.org/schema/context" 
		xmlns:jee="http://www.springframework.org/schema/jee"
		xsi:schemaLocation="
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/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/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

	<!-- 配置数据源 -->
	<bean id="ds" 
		class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<!-- 配置连接参数 -->
		<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe"/>
		<property name="driverClass" value="oracle.jdbc.OracleDriver"/>
		<property name="user" value="lhh"/>
		<property name="password" value="123456"/>
		<!-- 配置连接池 -->
		<property name="initialPoolSize" value="3"/>
		<property name="maxPoolSize" value="10"/>
		<property name="minPoolSize" value="1"/>
		<property name="acquireIncrement" value="3"/>
		<property name="maxIdleTime" value="60"/>
	</bean>
	
	<!-- 配置SessionFactory -->
	<bean id="sessionFactory" 
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!-- 依赖数据源 -->
		<property name="dataSource" ref="ds"/>
		<!-- Hibernate框架相关配置 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.OracleDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.formate_sql">true</prop>
			</props>
		</property>
		<property name="mappingResources">
			<list>
				<value>com/tarena/entity/Cost.hbm.xml</value>
			</list>
		</property>
	</bean>
	
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>

	<!-- 声明式事务管理,采用AOP形式切入 -->
	<bean id="txManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="load*" read-only="true" />
			<tx:method name="execute" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>
	<aop:config proxy-target-class="true">
		<aop:advisor advice-ref="txAdvice" 
			pointcut="within(com.tarena.action.*)" />
	</aop:config>

</beans>

在com.tarena.entity包下创建实体类Cost,代码如下

package com.tarena.entity;

import java.sql.Date;

/**
 * 资费实体类
 */
public class Cost {

	private Integer id;// 主键
	private String name;// 资费名称
	private Integer baseDuration;// 在线时长
	private Double baseCost;// 基本费用
	private Double unitCost;// 单位费用
	private String status;// 状态
	private String descr;// 资费说明
	private Date createTime;// 创建日期
	private Date startTime;// 启用日期
	private String costType;// 资费类型

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getBaseDuration() {
		return baseDuration;
	}

	public void setBaseDuration(Integer baseDuration) {
		this.baseDuration = baseDuration;
	}

	public Double getBaseCost() {
		return baseCost;
	}

	public void setBaseCost(Double baseCost) {
		this.baseCost = baseCost;
	}

	public Double getUnitCost() {
		return unitCost;
	}

	public void setUnitCost(Double unitCost) {
		this.unitCost = unitCost;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getDescr() {
		return descr;
	}

	public void setDescr(String descr) {
		this.descr = descr;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public String getCostType() {
		return costType;
	}

	public void setCostType(String costType) {
		this.costType = costType;
	}

}

在com.tarena.entity包下创建映射关系文件Cost.hbm.xml,代码如下

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.tarena.entity.Cost" table="cost">
		<id name="id" type="integer" column="id">
			<!-- 用来指明主键的生成方式 -->
			<generator class="sequence">
				<param name="sequence">cost_seq</param>
			</generator>
		</id>
		
		<property name="name" 
			type="string" column="name" />
		<property name="baseDuration" 
			type="integer" column="base_duration" />
		<property name="baseCost" 
			type="double" column="base_cost" />
		<property name="unitCost" 
			type="double" column="unit_cost" />
		<property name="status" 
			type="string" column="status" />
		<property name="descr" 
			type="string" column="descr" />
		<property name="createTime" 
			type="date" column="creatime" />
		<property name="startTime" 
			type="date" column="startime" />
		<property name="costType" 
			type="string" column="cost_type" />
	</class>
</hibernate-mapping>

在com.tarena.dao包下创建DAO接口ICostDao,并在接口中声明查询全部资费数据的方法,代码如下

package com.tarena.dao;

import java.util.List;

import com.tarena.entity.Cost;

public interface ICostDao {

	List<Cost> findAll();

}

在com.tarena.dao包下创建DAO实现类CostDaoImpl,继承于HibernateDaoSupport,并实现接口ICostDao,代码如下

package com.tarena.dao;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.tarena.entity.Cost;

@Repository
public class CostDaoImpl 
	extends HibernateDaoSupport implements ICostDao {

	@Resource
	public void setSF(SessionFactory sf) {
		super.setSessionFactory(sf);
	}

	@Override
	public List<Cost> findAll() {
		String hql = "from Cost";
		return getHibernateTemplate().find(hql);
	}

}

步骤三:使用Spring整合Struts2

配置web.xml,配置一个listener,使tomcat启动时自动加载Spring。另外再配置Struts2的前端控制器,代码如下

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name></display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- 配置listener,使tomcat启动时自动加载Spring -->
  <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>
  </context-param>
  
  <!-- 配置前端控制器 -->
  <filter>
    <filter-name>Struts2</filter-name>
    <filter-class>
  		org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
  	</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>Struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

在com.tarena.action包下创建Action类FindCostAction,调用DAO实现对资费的查询,代码如下

package com.tarena.action;

import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import com.tarena.dao.ICostDao;
import com.tarena.entity.Cost;

@Controller
@Scope("prototype")
public class FindCostAction {

	@Resource
	private ICostDao costDao;

	private List<Cost> costs;

	public String load() {
		costs = costDao.findAll();
		return "success";
	}

	public List<Cost> getCosts() {
		return costs;
	}

	public void setCosts(List<Cost> costs) {
		this.costs = costs;
	}

}

在src根路径下引入struts.xml并配置Action,代码如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
    "http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
	
	<package name="cost" 
		namespace="/cost" extends="json-default">
		<action name="findCost" 
			class="findCostAction" method="load">
			<result name="success">
				/WEB-INF/cost/find_cost.jsp
			</result>
		</action>
	</package>
</struts>

在WEB-INF/cost下创建页面find_cost.jsp,实现资费数据的显示,代码如下

<%@page pageEncoding="utf-8" isELIgnored="false"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>达内-NetCTOSS</title>
        <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" />
        <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" />
        <script language="javascript" type="text/javascript">
            //排序按钮的点击事件
            function sort(btnObj) {
                if (btnObj.className == "sort_desc")
                    btnObj.className = "sort_asc";
                else
                    btnObj.className = "sort_desc";
            }

            //启用
            function startFee() {
                var r = window.confirm("确定要启用此资费吗?资费启用后将不能修改和删除。");
                document.getElementById("operate_result_info").style.display = "block";
            }
            //删除
            function deleteFee() {
                var r = window.confirm("确定要删除此资费吗?");
                document.getElementById("operate_result_info").style.display = "block";            }
        </script>        
    </head>
    <body>
        <!--Logo区域开始-->
        <div id="header">
            <img src="../images/logo.png" alt="logo" class="left"/>
            <a href="#">[退出]</a>            
        </div>
        <!--Logo区域结束-->
        <!--导航区域开始-->
        <div id="navi">                        
            <ul id="menu">
                <li><a href="../index.html" class="index_off"></a></li>
                <li><a href="../role/role_list.html" class="role_off"></a></li>
                <li><a href="../admin/admin_list.html" class="admin_off"></a></li>
                <li><a href="../fee/fee_list.html" class="fee_on"></a></li>
                <li><a href="../account/account_list.html" class="account_off"></a></li>
                <li><a href="../service/service_list.html" class="service_off"></a></li>
                <li><a href="../bill/bill_list.html" class="bill_off"></a></li>
                <li><a href="../report/report_list.html" class="report_off"></a></li>
                <li><a href="../user/user_info.html" class="information_off"></a></li>
                <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li>
            </ul>            
        </div>
        <!--导航区域结束-->
        <!--主要区域开始-->
        <div id="main">
            <form action="" method="">
                <!--排序-->
                <div class="search_add">
                    <div>
                        <!--<input type="button" value="月租" class="sort_asc" onclick="sort(this);" />-->
                        <input type="button" value="基费" class="sort_asc" onclick="sort(this);" />
                        <input type="button" value="时长" class="sort_asc" onclick="sort(this);" />
                    </div>
                    <input type="button" value="增加" class="btn_add" onclick="location.href='fee_add.html';" />
                </div> 
                <!--启用操作的操作提示-->
                <div id="operate_result_info" class="operate_success">
                    <img src="../images/close.png" onclick="this.parentNode.style.display='none';" />
                    删除成功!
                </div>    
                <!--数据区域:用表格展示数据-->     
                <div id="data">            
                    <table id="datalist">
                        <tr>
                            <th>资费ID</th>
                            <th class="width100">资费名称</th>
                            <th>基本时长</th>
                            <th>基本费用</th>
                            <th>单位费用</th>
                            <th>创建时间</th>
                            <th>开通时间</th>
                            <th class="width50">状态</th>
                            <th class="width200"></th>
                        </tr>       
                        
                        <!-- 使用Struts2标签遍历集合,使用OGNL表达式输出内容。 -->               
                        <s:iterator value="costs">                 
	                        <tr>
	                            <td><s:property value="id"/></td>
	                            <td><a href="fee_detail.html"><s:property value="name"/></a></td>
	                            <td><s:property value="baseDuration"/></td>
	                            <td><s:property value="baseCost"/></td>
	                            <td><s:property value="unitCost"/></td>
	                            <td><s:property value="createTime"/></td>
	                            <td><s:property value="startTime"/></td>
	                            <td>
	                            	<s:if test="status==0">开通</s:if>
	                            	<s:else>暂停</s:else>
	                            </td>
	                            <td>                                
	                                <input type="button" value="启用" class="btn_start" onclick="startFee();" />
	                                <input type="button" value="修改" class="btn_modify" onclick="location.href='fee_modi.html';" />
	                                <input type="button" value="删除" class="btn_delete" onclick="deleteFee();" />
	                            </td>
	                        </tr>
                       </s:iterator>
                       
                    </table>
                    <p>业务说明:<br />
                    1、创建资费时,状态为暂停,记载创建时间;<br />
                    2、暂停状态下,可修改,可删除;<br />
                    3、开通后,记载开通时间,且开通后不能修改、不能再停用、也不能删除;<br />
                    4、业务账号修改资费时,在下月底统一触发,修改其关联的资费ID(此触发动作由程序处理)
                    </p>
                </div>
                <!--分页-->
                <div id="pages">
        	        <a href="#">上一页</a>
                    <a href="#" class="current_page">1</a>
                    <a href="#">2</a>
                    <a href="#">3</a>
                    <a href="#">4</a>
                    <a href="#">5</a>
                    <a href="#">下一页</a>
                </div>
            </form>
        </div>
        <!--主要区域结束-->
        <div id="footer">
            <p>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</p>
            <p>版权所有(C)加拿大达内IT培训集团公司 </p>
        </div>
    </body>
</html>

步骤四:测试

部署项目并启动tomcat,访问资费列表,效果如下图

图-5

3.4 完整代码

本案例的完整代码如下所示:

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:tx="http://www.springframework.org/schema/tx" 
		xmlns:aop="http://www.springframework.org/schema/aop"
		xmlns:context="http://www.springframework.org/schema/context" 
		xmlns:jee="http://www.springframework.org/schema/jee"
		xsi:schemaLocation="
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/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/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

	<!-- 配置数据源 -->
	<bean id="ds" 
		class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<!-- 配置连接参数 -->
		<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe"/>
		<property name="driverClass" value="oracle.jdbc.OracleDriver"/>
		<property name="user" value="lhh"/>
		<property name="password" value="123456"/>
		<!-- 配置连接池 -->
		<property name="initialPoolSize" value="3"/>
		<property name="maxPoolSize" value="10"/>
		<property name="minPoolSize" value="1"/>
		<property name="acquireIncrement" value="3"/>
		<property name="maxIdleTime" value="60"/>
	</bean>
	
	<!-- 配置SessionFactory -->
	<bean id="sessionFactory" 
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!-- 依赖数据源 -->
		<property name="dataSource" ref="ds"/>
		<!-- Hibernate框架相关配置 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.OracleDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.formate_sql">true</prop>
			</props>
		</property>
		<property name="mappingResources">
			<list>
				<value>com/tarena/entity/Cost.hbm.xml</value>
			</list>
		</property>
	</bean>
	
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>

	<!-- 声明式事务管理,采用AOP形式切入 -->
	<bean id="txManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="load*" read-only="true" />
			<tx:method name="execute" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>
	<aop:config proxy-target-class="true">
		<aop:advisor advice-ref="txAdvice" 
			pointcut="within(com.tarena.action.*)" />
	</aop:config>

</beans>

Cost完整代码如下

package com.tarena.entity;

import java.sql.Date;

/**
 * 资费实体类
 */
public class Cost {

	private Integer id;// 主键
	private String name;// 资费名称
	private Integer baseDuration;// 在线时长
	private Double baseCost;// 基本费用
	private Double unitCost;// 单位费用
	private String status;// 状态
	private String descr;// 资费说明
	private Date createTime;// 创建日期
	private Date startTime;// 启用日期
	private String costType;// 资费类型

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getBaseDuration() {
		return baseDuration;
	}

	public void setBaseDuration(Integer baseDuration) {
		this.baseDuration = baseDuration;
	}

	public Double getBaseCost() {
		return baseCost;
	}

	public void setBaseCost(Double baseCost) {
		this.baseCost = baseCost;
	}

	public Double getUnitCost() {
		return unitCost;
	}

	public void setUnitCost(Double unitCost) {
		this.unitCost = unitCost;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getDescr() {
		return descr;
	}

	public void setDescr(String descr) {
		this.descr = descr;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public String getCostType() {
		return costType;
	}

	public void setCostType(String costType) {
		this.costType = costType;
	}

}

Cost.hbm.xml完整代码如下

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.tarena.entity.Cost" table="cost">
		<id name="id" type="integer" column="id">
			<!-- 用来指明主键的生成方式 -->
			<generator class="sequence">
				<param name="sequence">cost_seq</param>
			</generator>
		</id>
		
		<property name="name" 
			type="string" column="name" />
		<property name="baseDuration" 
			type="integer" column="base_duration" />
		<property name="baseCost" 
			type="double" column="base_cost" />
		<property name="unitCost" 
			type="double" column="unit_cost" />
		<property name="status" 
			type="string" column="status" />
		<property name="descr" 
			type="string" column="descr" />
		<property name="createTime" 
			type="date" column="creatime" />
		<property name="startTime" 
			type="date" column="startime" />
		<property name="costType" 
			type="string" column="cost_type" />
	</class>
</hibernate-mapping>

ICostDao完整代码如下

package com.tarena.dao;

import java.util.List;

import com.tarena.entity.Cost;

public interface ICostDao {

	List<Cost> findAll();

}

CostDaoImpl完整代码如下

package com.tarena.dao;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.tarena.entity.Cost;

@Repository
public class CostDaoImpl 
	extends HibernateDaoSupport implements ICostDao {

	@Resource
	public void setSF(SessionFactory sf) {
		super.setSessionFactory(sf);
	}

	@Override
	public List<Cost> findAll() {
		String hql = "from Cost";
		return getHibernateTemplate().find(hql);
	}

}

web.xml完整代码如下

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name></display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- 配置listener,使tomcat启动时自动加载Spring -->
  <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>
  </context-param>
  
  <!-- 配置前端控制器 -->
  <filter>
    <filter-name>Struts2</filter-name>
    <filter-class>
  		org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
  	</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>Struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

FindCostAction完整代码如下

package com.tarena.action;

import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import com.tarena.dao.ICostDao;
import com.tarena.entity.Cost;

@Controller
@Scope("prototype")
public class FindCostAction {

	@Resource
	private ICostDao costDao;

	private List<Cost> costs;

	public String load() {
		costs = costDao.findAll();
		return "success";
	}

	public List<Cost> getCosts() {
		return costs;
	}

	public void setCosts(List<Cost> costs) {
		this.costs = costs;
	}

}

struts.xml完整代码如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
    "http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
	
	<package name="cost" 
		namespace="/cost" extends="json-default">
		<action name="findCost" 
			class="findCostAction" method="load">
			<result name="success">
				/WEB-INF/cost/find_cost.jsp
			</result>
		</action>
	</package>
</struts>

find_cost.jsp完整代码如下

<%@page pageEncoding="utf-8" isELIgnored="false"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>达内-NetCTOSS</title>
        <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" />
        <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" />
        <script language="javascript" type="text/javascript">
            //排序按钮的点击事件
            function sort(btnObj) {
                if (btnObj.className == "sort_desc")
                    btnObj.className = "sort_asc";
                else
                    btnObj.className = "sort_desc";
            }

            //启用
            function startFee() {
                var r = window.confirm("确定要启用此资费吗?资费启用后将不能修改和删除。");
                document.getElementById("operate_result_info").style.display = "block";
            }
            //删除
            function deleteFee() {
                var r = window.confirm("确定要删除此资费吗?");
                document.getElementById("operate_result_info").style.display = "block";            }
        </script>        
    </head>
    <body>
        <!--Logo区域开始-->
        <div id="header">
            <img src="../images/logo.png" alt="logo" class="left"/>
            <a href="#">[退出]</a>            
        </div>
        <!--Logo区域结束-->
        <!--导航区域开始-->
        <div id="navi">                        
            <ul id="menu">
                <li><a href="../index.html" class="index_off"></a></li>
                <li><a href="../role/role_list.html" class="role_off"></a></li>
                <li><a href="../admin/admin_list.html" class="admin_off"></a></li>
                <li><a href="../fee/fee_list.html" class="fee_on"></a></li>
                <li><a href="../account/account_list.html" class="account_off"></a></li>
                <li><a href="../service/service_list.html" class="service_off"></a></li>
                <li><a href="../bill/bill_list.html" class="bill_off"></a></li>
                <li><a href="../report/report_list.html" class="report_off"></a></li>
                <li><a href="../user/user_info.html" class="information_off"></a></li>
                <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li>
            </ul>            
        </div>
        <!--导航区域结束-->
        <!--主要区域开始-->
        <div id="main">
            <form action="" method="">
                <!--排序-->
                <div class="search_add">
                    <div>
                        <!--<input type="button" value="月租" class="sort_asc" onclick="sort(this);" />-->
                        <input type="button" value="基费" class="sort_asc" onclick="sort(this);" />
                        <input type="button" value="时长" class="sort_asc" onclick="sort(this);" />
                    </div>
                    <input type="button" value="增加" class="btn_add" onclick="location.href='fee_add.html';" />
                </div> 
                <!--启用操作的操作提示-->
                <div id="operate_result_info" class="operate_success">
                    <img src="../images/close.png" onclick="this.parentNode.style.display='none';" />
                    删除成功!
                </div>    
                <!--数据区域:用表格展示数据-->     
                <div id="data">            
                    <table id="datalist">
                        <tr>
                            <th>资费ID</th>
                            <th class="width100">资费名称</th>
                            <th>基本时长</th>
                            <th>基本费用</th>
                            <th>单位费用</th>
                            <th>创建时间</th>
                            <th>开通时间</th>
                            <th class="width50">状态</th>
                            <th class="width200"></th>
                        </tr>       
                        
                        <!-- 使用Struts2标签遍历集合,使用OGNL表达式输出内容。 -->               
                        <s:iterator value="costs">                 
	                        <tr>
	                            <td><s:property value="id"/></td>
	                            <td><a href="fee_detail.html"><s:property value="name"/></a></td>
	                            <td><s:property value="baseDuration"/></td>
	                            <td><s:property value="baseCost"/></td>
	                            <td><s:property value="unitCost"/></td>
	                            <td><s:property value="createTime"/></td>
	                            <td><s:property value="startTime"/></td>
	                            <td>
	                            	<s:if test="status==0">开通</s:if>
	                            	<s:else>暂停</s:else>
	                            </td>
	                            <td>                                
	                                <input type="button" value="启用" class="btn_start" onclick="startFee();" />
	                                <input type="button" value="修改" class="btn_modify" onclick="location.href='fee_modi.html';" />
	                                <input type="button" value="删除" class="btn_delete" onclick="deleteFee();" />
	                            </td>
	                        </tr>
                       </s:iterator>
                       
                    </table>
                    <p>业务说明:<br />
                    1、创建资费时,状态为暂停,记载创建时间;<br />
                    2、暂停状态下,可修改,可删除;<br />
                    3、开通后,记载开通时间,且开通后不能修改、不能再停用、也不能删除;<br />
                    4、业务账号修改资费时,在下月底统一触发,修改其关联的资费ID(此触发动作由程序处理)
                    </p>
                </div>
                <!--分页-->
                <div id="pages">
        	        <a href="#">上一页</a>
                    <a href="#" class="current_page">1</a>
                    <a href="#">2</a>
                    <a href="#">3</a>
                    <a href="#">4</a>
                    <a href="#">5</a>
                    <a href="#">下一页</a>
                </div>
            </form>
        </div>
        <!--主要区域结束-->
        <div id="footer">
            <p>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</p>
            <p>版权所有(C)加拿大达内IT培训集团公司 </p>
        </div>
    </body>
</html>