一段时间以来时间很忙,自己的技术blog也被当作了"Silent hill"了,呵呵!今天有点时间还是把刚写的例子贴上blog巴。
废话不多说,为了方便还是直接贴代码了。
实验环境:tomcat 5.1 IDE:Eclilpse 4.1 oracle9i Spring1.2 struts1.1 Hibernate3

一、先来看看几个xml巴:
1.先是 applicationContext.xml,其中定义了dbcp和jndi数据库连接池,两种方式连接数据库!
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<!-- dateSource 普通dbcp连接方式-->
<bean id="dataSourcedbcp" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@localhost:1521:CCTV</value>
</property>
<property name="username">
<value>hib</value>
</property>
<property name="password">
<value>hib</value>
</property>
</bean>
<!-- dateSource 普通jdbc连接方式 end-->

<!-- dateSource 通过jndi获取连接 -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/testds</value>
</property>
</bean>
<!-- dateSource 通过jndi获取连接 end-->

<!-- 配置hibernate3 SessionFactory 此例子采用hibernate3 规范-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource" />
</property>

<!-- hibernate 数据库相对表的映射文件 -->
<property name="mappingResources">
<list>
<value>com/test/common/hibernate/daos/Customer.hbm.xml</value>
<value>com/test/common/hibernate/daos/Account.hbm.xml</value>
</list>
</property>
<!-- hibernate 数据库相对表的映射文件 end-->

<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.show_sql">true</prop><!-- 是否在控制台输出hibernate 处理过的sql语句?true,falses-->
</props>
</property>
</bean>
<!-- 配置hibernate SessionFactory end-->

<!--hibernate 事务的处理 -->

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>

<!--hibernate 事务的处理 end-->
<!-- hibernate 事务AddCustomerDAOProxy的transactionAttributes属性中,
定义事务策略将所有以save、remove开始的方法纳入事务管理范围,
如果这些方法抛出异常,在Spring将当前事务回滚,如果方法正常结束,则提交事务。
-->
<bean id="AddCustomerDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<ref local="customerDAOService" />
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<!-- prop key="get*">PROPAGATION_REQUIRED</prop>
<prop key="set*">PROPAGATION_REQUIRED</prop>
<prop key="modify*">PROPAGATION_REQUIRED,-BoardException</prop>
<prop key="remove*">PROPAGATION_REQUIRED,-BoardException</prop-->

</props>
</property>
</bean>
<bean id="ShowListDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<ref local="showListDAO" />
</property>
<property name="transactionAttributes">
<props>
<!-- prop key="insert*">PROPAGATION_REQUIRED</prop-->
<prop key="get*">PROPAGATION_REQUIRED</prop>
<!-- prop key="set*">PROPAGATION_REQUIRED</prop>
<prop key="modify*">PROPAGATION_REQUIRED,-BoardException</prop>
<prop key="remove*">PROPAGATION_REQUIRED,-BoardException</prop-->
</props>
</property>
</bean>
<!-- 省略了customerDAOService的服务类1-->
<bean id="customerDAOService" class="com.test.common.springwork.service.customerDAOServiceImpl">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
<property name="customerDAO">
<ref local="customerDAO" />
</property>
</bean>
<!-- adduser DAO-->
<bean id="customerDAO" class="com.test.common.hibernate.daos.CustomerDAOImpl">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<bean id="showListDAO" class="com.test.common.hibernate.daos.ShowListDAOImpl">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>

<!-- action forward!!! this name is mapping in struts-config.xml ,use action proxy to do it-->
<bean name="/jsp/addPerson" class="com.test.common.struts.actions.AddPersonAction" singleton="false">
<property name="customerDAOService">
<ref local="AddCustomerDAOProxy" />
</property>
</bean>
<bean name="/jsp/ShowListAction" class="com.test.common.struts.actions.ShowListAction" singleton="false">
<property name="showListDAO">
<ref local="ShowListDAOProxy" />
</property>
</bean>

<!--test tools!-->
<!-- bean id="wordCaseUtil" class="com.test.common.springwork.dao.WordTools">
<property name="UpperAction">
<ref bean="UpperAction" />
</property>
<property name="LowerAction">
<ref bean="LowerAction" />
</property>
</bean-->

<bean id="UpperAction" class="com.test.common.springwork.dao.UpperAction" />
<bean id="LowerAction" class="com.test.common.springwork.dao.LowerAction" />
<!-- test tools! end!-->

</beans>

接着看一下tomcat在server.xml的datasource的配置:
<!-- Tomcat Root Context -->
<Context docBase="E:/workspace/test/WebRoot" path="/test" reloadable="true" debug="0">
<Resource name="jdbc/testds" auth="Container" type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/testds">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>oracle.jdbc.driver.OracleDriver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:oracle:thin:@localhost:1521:wang</value>
</parameter>
<parameter>
<name>username</name>
<value>hib</value>
</parameter>
<parameter>
<name>password</name>
<value>hib</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>20</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>10</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>-1</value>
</parameter>
</ResourceParams>
</Context>
2.再来看看web.xml的配置!
其中启用了Spring的ContextLoaderListener来做监听,而不是配置servlet
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- log4j 的配置文件-->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<!-- spring applicationContext的配置-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>action</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>
<init-param>
<param-name>debug</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<taglib>
<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/page.tld</taglib-uri>
<taglib-location>/WEB-INF/page.tld</taglib-location>
</taglib>

<resource-ref>
<res-ref-name>jdbc/testds</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
</web-app>


3.web层也就是struts的struts-config.xml的配置略有不同,它需要加上插件,在容器启动时自动加载 applicationContext.xml,并且action可以通过spring beans来以来注入,所以要用到:org.springframework.web.struts.DelegatingActionProxy
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans >
<form-bean name="addPersonForm" type="com.test.common.struts.actionforms.AddPersonActionForm" />
</form-beans>
<action-mappings>
<action
name="addPersonForm"
validate="false"
path="/jsp/addPerson"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="showlist" path="/jsp/show.jsp" />
<forward name="msg" path="/msg/msg.jsp"/>
</action>
<action
path="/jsp/ShowListAction"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="showlist" path="/jsp/showlist.jsp" />
<forward name="msg" path="/msg/msg.jsp"/>
</action>
</action-mappings>
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml"/>
</plug-in>
</struts-config>

二、需要配置的两个表的hbm.xml也就是hibernate对表的配置文件,其中TBL_CUSTOMER是主表TBL_ACCOUNT是从表,TBL_ACCOUNT有外键:CUSTOMER_ID,本例子的dao层要做对其二表的及联添加!
1。Customer.hbm.xml
<?xml version="1.0"?>

<!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.test.common.hibernate.daos.Customer"
table="TBL_CUSTOMER"
dynamic-update="false"
dynamic-insert="false">

<id
name="id"
column="CUSTOMER_ID"
type="java.lang.Long"
unsaved-value="-1"
>
<generator class="increment">
</generator>
</id>
<set name ="accounts"
inverse = "true"
cascade="save-update">
<key column ="CUSTOMER_ID"/>
<one-to-many class="com.test.common.hibernate.daos.Account"/>
</set>
<property
name="email"
type="string"
update="false"
insert="true"
column="CUSTOMER_EMAIL"
length="82"
not-null="true"
/>

<property
name="password"
type="string"
update="false"
insert="true"
column="CUSTOMER_PASSWORD"
length="10"
not-null="true"
/>

<property
name="userId"
type="string"
update="false"
insert="true"
column="CUSTOMER_USERID"
length="12"
not-null="true"
unique="true"
/>
<property
name="firstName"
type="string"
update="false"
insert="true"
column="CUSTOMER_FIRSTNAME"
length="25"
not-null="true"
/>
<property
name="lastName"
type="string"
update="false"
insert="true"
column="CUSTOMER_LASTTNAME"
length="25"
not-null="true"
/>

</class>

</hibernate-mapping>

2。Account.hbm.xml
<?xml version="1.0"?>

<!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.test.common.hibernate.daos.Account"
table="TBL_ACCOUNT"
dynamic-update="false"
dynamic-insert="false">

<id
name="id"
column="ACCOUNT_ID"
type="java.lang.Long"
unsaved-value="-1"
>
<generator class="increment">
</generator>
</id>
<many-to-one
name="customer"
column="CUSTOMER_ID"
cascade="save-update"
class="com.test.common.hibernate.daos.Customer"
/>
<property
name="accountName"
type="string"
update="false"
insert="true"
column="ACCOUNT_NAME"
length="50"
not-null="true"
/>

<property
name="type"
type="string"
update="false"
insert="true"
column="ACCOUNT_TYPE"
length="1"
not-null="true"
/>

<property
name="createDate"
type="date"
update="false"
insert="true"
column="CREATE_DATE"
not-null="true"
/>
<property
name="updateDate"
type="date"
update="true"
insert="true"
not-null="true"
column="UPDATE_DATE"
/>
<property
name="balance"
type="double"
update="true"
insert="true"
column="ACCOUNT_BALANCE"
not-null="true"
/>

</class>

</hibernate-mapping>

接下来看一看这两个表的dao层接口及实现接口的类:
(1)、accountDao和accountDaoImpl

/** *//**
* @author wangghost
* @deprecated:account数据操作接口!
*/

public interface AccountDAO ...{
public abstract void addAccount(Account account);
}

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;


/** *//**
* @author wangghost
* @deprecated:实现account接口!
* @see:AccountDAO.java
*/

public class AccountDAOImpl extends HibernateDaoSupport implements AccountDAO...{



public void addAccount(Account account) ...{
getHibernateTemplate().save(account);
}

}

(2)、customerDao和customerDaoImpl

/** *//**
* @author wangghost
* @deprecated:customer数据模型接口!
*/

public interface CustomerDAO ...{
public abstract void addCustomer(Customer customer);
public abstract Customer getCustomerAccountInfo(Customer customer);
public abstract void deleteCustomerInfo(Customer customer);
}
对应application-context.xml中的bean
<bean id="customerDAO" class="com.test.common.hibernate.daos.CustomerDAOImpl">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
import java.util.List;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;



/** *//**
* @author wangghost
* @deprecated:实现customer接口!
* @see:CustomerDAO.java
*/


public class CustomerDAOImpl extends HibernateDaoSupport implements CustomerDAO...{

public void addCustomer(Customer customer) ...{ //hibernate 被spring 封装接口方法getHibernateTemplate()用它来调用hibernate数据库操作
getHibernateTemplate().save(customer);
getHibernateTemplate().flush();
// TODO Auto-generated method stub
}


public Customer getCustomerAccountInfo(Customer customer) ...{//根据userid得出相应持久化对象
Customer cust = null;
List list = getHibernateTemplate().find("from Customer customer " +

"where customer.userId = ?",new Object[]...{
customer.getUserId()});
// List list = getHibernateTemplate().find("from Customer customer " +
// "where customer.userId = "+customer.getUserId(),Hibernate.STRING); //hibernate 2 写法,这里已经不支持了!

if(list.size() > 0)...{
cust = (Customer) list.get(0);
}
return cust;
}


public void deleteCustomerInfo(Customer customer) ...{
// TODO 自动生成方法存根
}

}
三、service层,由于此例子也无非常简单,但为了遵循三个框架的意见还是添加了service层。
1。接口CustomerDAOService与它的接口实现CustomerDAOServiceImpl:

import com.test.common.struts.actionforms.AddPersonActionForm;


/** *//**
* @author wangghost
*
* 更改所生成类型注释的模板为 窗口 > 首选项 > Java > 代码生成 > 代码和注释
*/

public interface CustomerDAOService ...{

public abstract void customerService(AddPersonActionForm person,
String userid, java.sql.Date date);
}

import com.test.common.hibernate.daos.Account;
import com.test.common.hibernate.daos.Customer;
import com.test.common.hibernate.daos.CustomerDAO;
import com.test.common.struts.actionforms.AddPersonActionForm;


/** *//**
* @author wangghost
*
* 更改
* 窗口 > 首选项 > Java > 代码生成 > 代码和注释
*/

public class CustomerDAOServiceImpl implements CustomerDAOService ...{


/** *//**
*
*/

public CustomerDAOServiceImpl() ...{
super();
}
private CustomerDAO customerDAO;


/** *//**
* @return Returns the customerDAO.
*/

public CustomerDAO getCustomerDAO() ...{
return customerDAO;
}


/** *//**
* @param customerDAO
* The customerDAO to set.
*/

public void setCustomerDAO(CustomerDAO customerDAO) ...{
this.customerDAO = customerDAO;
}


/**//*
* @see com.test.common.springwork.service.CustomerDAOService#customerService()
*/

public void customerService(AddPersonActionForm person,String userid,java.sql.Date date) ...{
// let user info into "pojo" customer
Customer customer = new Customer();
customer.setFirstName(person.getFristname().trim());
customer.setLastName(person.getLastname().trim());
customer.setEmail(person.getEmail());
customer.setPassword(person.getPassword().trim());
customer.setUserId(userid);
// customer done!
// account begin!
Account account = new Account();
account.setAccountName(person.getAccountname());
account.setCreateDate(date);
account.setUpdateDate(date);
account.setType(person.getAccounttype());
account.setBalance(Double.valueOf("1.0"));
// account done
account.setCustomer(customer); //建立从表与主表的联系!
customer.getAccounts().add(account); // account与主表建立关系!
customerDAO.addCustomer(customer); // 调用被封装的接口!数据此时将被级联添加的数据库的两个表中!

}

}

四、web层的实现,首先web层有两个action,AddPersonAction添加新用户的action,ShowListAction列表分页的action
1.AddPersonAction
请注意在application-context.xml中的action的配置:
在action中注入了CustomerDAOService也就是业务层。
<bean name="/jsp/addPerson" class="com.test.common.struts.actions.AddPersonAction" singleton="false">
<property name="customerDAOService">
<ref local="AddCustomerDAOProxy" />
</property>
</bean>
import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
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 com.test.common.hibernate.daos.Account;
import com.test.common.hibernate.daos.Customer;
import com.test.common.hibernate.daos.CustomerDAO;

import com.test.common.springwork.service.CustomerDAOService;
import com.test.common.struts.actionforms.AddPersonActionForm;
//import org.springframework.web.context.ContextLoaderListener;

/** *//** 请按以下注释开发!!
* <p>Title: test action </p>
* <p>Description: struts action add person</p>
* <p>Copyright: Copyright (c) 2006</p>
* <p>Company: digitalArchive</p>
* @author wangghost
* @version 1.0
*/


public class AddPersonAction extends Action ...{


/** *//**
* struts Action 与spring已整合! 功能:做到级联添加新客户信息!
*/

public AddPersonAction() ...{
super();
}
private static Logger log = Logger.getLogger(AddPersonAction.class);
private CustomerDAOService customerDAOService;


/** *//**
* @return Returns the customerDAOService.
*/

public CustomerDAOService getCustomerDAOService() ...{
return customerDAOService;
}


/** *//**
* @param customerDAOService The customerDAOService to set.
*/

public void setCustomerDAOService(CustomerDAOService customerDAOService) ...{
this.customerDAOService = customerDAOService;
}

/** *//**
* @return Returns the customerDAO.
*/
public ActionForward execute(ActionMapping mapping, ActionForm actionform,

HttpServletRequest request, HttpServletResponse response) ...{

String encoding = request.getCharacterEncoding();// 或取当前编码格式!
if (encoding != null && encoding.equalsIgnoreCase("utf-8"))// 如果是utf-8格式转成gb2312编码格式
response.setContentType("text/html; charset=gb2312");

if (actionform instanceof AddPersonActionForm) ...{ // actionform装载是否是addpersonactionform
AddPersonActionForm person = (AddPersonActionForm) actionform;
String name = person.getFristname().trim()
+ person.getLastname().trim();// name 注意格式“+”
String password = person.getPassword().trim();
String accountname = person.getAccountname();
String accounttype = person.getAccounttype();
String email = person.getEmail();
String userid = person.getUserid();
java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
HashMap keymap = new HashMap(); // 建立hashmap把表单域中的相应的值压进去!
keymap.put("name", name);
keymap.put("password", password);
keymap.put("accountname", accountname);
keymap.put("accounttype", accounttype);
keymap.put("email", email);

StringBuffer buffer = (StringBuffer) BlankString(keymap);
if (buffer.length() > 0) // 注意格式!

...{ // “{” 请折行显示!
request.setAttribute("msg", buffer.toString()); // 如果有错误将跳转到错误收集页面!
return mapping.findForward("msg");
}
this.customerDAOService.customerService(person,userid,date);
return mapping.findForward("showlist");
}
return null;

}


/** *//**
* 把actionForm中的validate表单的验证放到action中
*
* @param keymap
* @return String[]
*/

private StringBuffer BlankString(HashMap keymap) ...{
StringBuffer str = new StringBuffer();
if( ( keymap.get("name") ).equals("") )

...{
str.append("用户名不能为空! ");
}
if( ( keymap.get("password") ).equals("") )

...{
str.append("密码不能为空! ");
}else

...{
if( !( ( ( ( keymap.get("password") ).toString() ).length() >= 4 )
&& ( ( ( keymap.get("password") ).toString() ).length() <= 10 ) ) )
str.append("密码必须在4---10之间! ");
}
if( ( keymap.get("accountname") ).equals("") )

...{
str.append("账户名不能为空 ");
}
if( ( keymap.get("accounttype") ).equals("") )

...{
str.append("账户类型不能为空 ");
}
if( ( keymap.get("email") ).equals("") )

...{
str.append("邮箱不能为空 ");
}else

...{
if( ( keymap.get("email").toString() ).indexOf("@") == -1 )
str.append("email 格式不对!");
}
return str;
}

}
2.ShowListAction功能复杂,要介绍关于分页、以及spring的HibernateCallback()回调功能。
ShowListAction:
再来看看分页,用taglib来实现:
<bean name="/jsp/ShowListAction" class="com.test.common.struts.actions.ShowListAction" singleton="false">
<property name="showListDAO">
<ref local="ShowListDAOProxy" />
</property>
</bean>
import java.util.ArrayList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
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 com.test.common.hibernate.daos.Customer;
import com.test.common.hibernate.daos.ShowListDAO;


/** *//**
* 请按一下注释开发!!
* <p>
* Title: list person info action
* </p>
* <p>
* Description: struts action show the person info
* </p>
* <p>
* Copyright: Copyright (c) 2006
* </p>
* <p>
* Company: digitalArchive
* </p>
*
* @author wangghost
* @version 1.0
*/

public class ShowListAction extends Action ...{


/** *//**
* super
*/

public ShowListAction() ...{
super();
}

private static Logger log = Logger.getLogger(AddPersonAction.class);

private ShowListDAO showListDAO;


/** *//**
* @return Returns the showListDAO.
*/

public ShowListDAO getShowListDAO() ...{
return showListDAO;
}


/** *//**
* @param showListDAO
* The showListDAO to set.
*/

public void setShowListDAO(ShowListDAO showListDAO) ...{
this.showListDAO = showListDAO;
}

public ActionForward execute(ActionMapping mapping, ActionForm actionform,

HttpServletRequest request, HttpServletResponse response) ...{

String encoding = request.getCharacterEncoding();// 或取当前编码格式!
if (encoding != null && encoding.equalsIgnoreCase("utf-8"))// 如果是utf-8格式转成gb2312编码格式
response.setContentType("text/html; charset=gb2312");

ArrayList personDetailList = new ArrayList();
String _page = "1"; //当前页号
String _size = "10"; //总页数
String _choice = ""; //分页标签类型

if (request.getParameter("pageNo") != null

&& request.getParameter("pageSize") != null) ...{
_page = request.getParameter("pageNo");
_size = request.getParameter("pageSize");
_choice = request.getParameter("choice");
}
String total = request.getParameter("total"); // 初识化为0
if (total != null)
_page = currentPageNumber(_choice, _page, total, _size); //获取当前页号

Object[] objectList = (Object[]) showListDAO.GetPersonDetails(
new Customer(), Integer.parseInt(_size), Integer
.parseInt(_page)); //通过showlistdao接口获取总页数和结果集!
personDetailList = (ArrayList) objectList[0];
total = objectList[1].toString();
// set value of page
request.setAttribute("personDetailList",personDetailList);
request.setAttribute("pageNo",_page);
request.setAttribute("pageSize",_size);
request.setAttribute("total",total);
return mapping.findForward("showlist");
}


/** *//**
* <p>
* Description:根据choice类型获取当前页号
* </p>
*
* @param choice
* @param _page
* @param _total
* @param _size
* @return
*/
public String currentPageNumber(String choice, String _page, String _total,

String _size) ...{
int pageNo = Integer.parseInt(_page);
int total = Integer.parseInt(_total);
int pageSize = Integer.parseInt(_size);
// 计算总页数注意格式!
int pages = (total % pageSize == 0) ? total / pageSize : total
/ pageSize + 1;

// 根据操作,重新确定当前页号
if (choice.equals("next"))
pageNo++;
if (choice.equals("prev"))
pageNo--;
if (choice.equals("first"))
pageNo = 1;
if (choice.equals("last"))
pageNo = pages;

// 页号越界处理
if (pageNo > pages)
pageNo = pages;
if (pageNo <= 0)
pageNo = 1;

return String.valueOf(pageNo);
}

}
其中注入了ShowListDAO,下面介绍ShowListDAO和ShowListDAOImpl的内容:

/** *//**
* @author wangghost
*实际的服务类接口
* 更改所生成类型注释的模板为
* 窗口 > 首选项 > Java > 代码生成 > 代码和注释
*/

public interface ShowListDAO ...{

public abstract Object[] GetPersonDetails(Customer customer,int size,final int page);//分页业务方法
}
在application-context.xml中的配置:
<bean id="showListDAO" class="com.test.common.hibernate.daos.ShowListDAOImpl">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.test.common.struts.actionforms.PersonDetail;


/** *//**
* @author wangghost
* @see showListDao.java
* 实现服务类接口。
* 更改所生成类型注释的模板为 窗口 > 首选项 > Java > 代码生成 > 代码和注释
*/

public class ShowListDAOImpl extends HibernateDaoSupport implements ShowListDAO ...{


/** *//**
*
*/

public ShowListDAOImpl() ...{
super();
}


/**//*
* (非 Javadoc)
*
* @see com.test.common.hibernate.daos.ShowListDAO#GetPersonDetails(com.test.common.hibernate.daos.Customer,
* int, int)
*/


public Object[] GetPersonDetails(Customer customer, int size, final int page) ...{//
Object[] ob = new Object[2]; //用来获得条目数,数据记录
ArrayList list = new ArrayList();
int countList = 0;
// Account account = null;
String sql = "select count(c) from Customer c";
// getHibernateTemplate().getSessionFactory().openSession().createCriteria(Customer.class).createAlias()
countList = ((Integer) (getHibernateTemplate().find(sql)).iterator().next()).intValue(); //通过getHibernateTemplate()获取当前主表的总记录数!
final int pagesize = size; //总页数
// 启用spring hibernate回调功能实现分页
list = (ArrayList) getHibernateTemplate().execute(

new HibernateCallback() ...{
public Object doInHibernate(Session session)

throws HibernateException, SQLException ...{
ArrayList personlist = new ArrayList();
//转换sql=select * from Customer c,Account a where c.id = a.id
List list = session.createCriteria(Customer.class)
.createAlias("accounts", "a")
.setFirstResult((page - 1) * pagesize)
.setMaxResults(pagesize)
.list();

// getHibernateTemplate().flush();
// insert into java bean

for (Iterator person = list.iterator(); person.hasNext();) ...{//取出customer表中相应的信息
PersonDetail personDetail = new PersonDetail();
Customer customer = (Customer) person.next();
// personDetail.setBalance(String.valueOf(customer.getBalance()));
personDetail.setName(customer.getFirstName()
+ customer.getLastName());
personDetail.setEmail(customer.getEmail());
personDetail.setPassword(customer.getPassword());
personDetail.setUserid(customer.getUserId());

for (Iterator table = customer.getAccounts().iterator(); table.hasNext();) ...{//取出每条customer表信息对应的account表的信息
Account _account = (Account) table.next();
personDetail.setAccountname(_account
.getAccountName());
personDetail.setCreatedate(_account
.getCreateDate().toString());
personDetail.setBalance(String.valueOf(_account
.getBalance()));
personDetail.setAccounttype(_account.getType());
}
personlist.add(personDetail);
}

return personlist;
}
});

ob[0] = list.clone();
ob[1] = String.valueOf(countList);

return ob;
}
}
1、page.tld
<?xml version="1.0" encoding="GB2312"?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">

<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>page</shortname>

<!--====================page:pager begin=====================-->
<tag>
<name>wangghost</name>
<tagclass>com.test.common.struts.taglib.page.GhostPageTagSupport</tagclass>
<bodycontent>JSP</bodycontent>
<info>
pager tag provide the frame of the page divider
</info>

<attribute>
<name>total</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>defaultPageSize</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<!--======================page:pager end=========================-->

<!--====================page:navigator begin=====================-->
<tag>
<name>showghost</name>
<tagclass>com.test.common.struts.taglib.page.ShowPageTextTagSupport</tagclass>

<bodycontent>JSP</bodycontent>
<info>
navigator tag output the Navigator bar which pre-designed
</info>
<attribute>
<name>actionLocation</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<!--======================page:navigator end=========================-->
</taglib>
节约时间下面就直接把代码贴出来了:
2、GhostPageTagSupport:
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;


/** *//**
* @author wangghost
*
* TODO 要更改此生成的类型注释的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/

public class GhostPageTagSupport extends BodyTagSupport...{


/** *//**
*
*/
private static final long serialVersionUID = 1L;



/** *//**
* ghost page !
*/

public GhostPageTagSupport() ...{
super();
}
private StringBuffer output; //保存输出
private int pageNo; //当前页面
private int pageSize; //每页记录数
private int index = 1; //起始记录数,缺省为0
private int pages; //总页数
private int total = 0; //记录总数,即需要分页显示的记录总数,初始化默认为0
private int defaultPageSize = 10; //缺省每页记录数,可在导航条中改变每页记录数的值

public int getDefaultPageSize()

...{
return this.defaultPageSize;
}
public void setDefaultPageSize(int newDefaultPageSize)

...{
this.defaultPageSize = newDefaultPageSize;
}
public void setTotal(int newTotal)

...{
this.total = newTotal;
}

public int doStartTag() throws JspTagException

...{
output = new StringBuffer();
handleActionNow(); //初始化分页参数,遍历request中参数
return EVAL_BODY_BUFFERED;
}


/** *//**
* 获得标记内的记录列表内容
*/

public int doAfterBody() throws JspTagException ...{
BodyContent bodyContent = getBodyContent();

if (bodyContent != null) ...{
output.append(bodyContent.getString());

try ...{
bodyContent.clear();
}

catch (IOException ex) ...{
throw new JspTagException("buffer IO Error");
}
}
return SKIP_BODY;
}

/** *//**
* 输出标记内的内容
*/

public int doEndTag() throws JspTagException ...{
BodyContent bodyContent = getBodyContent();

try ...{

if (bodyContent != null) ...{
//输出结束标记
output.append("</form> ");
//输出全部内容
bodyContent.getEnclosingWriter().write(output.toString());
}
}

catch (IOException ex) ...{
throw new JspTagException("Fatal IO Error");
}

return EVAL_PAGE;
}

/** *//**
*
*/

private void handleActionNow() ...{
StringBuffer paramBuffer = new StringBuffer();
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
HttpSession session = request.getSession();
HashMap params = new HashMap();
String choice = ParamUtil.getParameter(request, "choice");
//获取每页记录数,若没指定,使用默认值
pageSize = ParamUtil.getIntParameter(request, "pageSize", defaultPageSize);

//获取页号
pageNo = ParamUtil.getIntParameter(request, "pageNo", 1);
// 每页记录数越界处理
if (pageSize <= 0)
pageSize = 1;

//计算总页数
pages = (total % pageSize == 0) ? total / pageSize : total / pageSize + 1;

//根据操作,重新确定当前页号
if (choice.equals("next"))
pageNo++;
if (choice.equals("prev"))
pageNo--;
if (choice.equals("first"))
pageNo = 1;
if (choice.equals("last"))
pageNo = pages;

//页号越界处理
if (pageNo > pages)
pageNo = pages;
if (pageNo <= 0)
pageNo = 1;

//起始记录号
index = (pageNo - 1) * pageSize + 1;

//输出表单的头
output.append("<form method='post' name='pager'> ");
//枚举传到的参数!
Enumeration enum;
String name;
String value;
//获取所有提交的参数,并设置表单"<input type='hidden' name='' value=''>"
enum = request.getParameterNames();


while (enum.hasMoreElements()) ...{
name = (String) enum.nextElement();
value = ParamUtil.getParameter(request, name);
//保存查询参数和值
params.put(name, value);


if (name.equals("pageNo") || name.equals("pageSize") || name.equals("choice")) ...{
continue;
}
paramBuffer.append("<input type='hidden' name='" + name + "' value='" + value +
"'> ");
}

//保存分页参数和值
params.put("pageNo", new Integer(pageNo));
params.put("pageSize", new Integer(pageSize));

//保存到session
session.setAttribute("pagerParameters", params);

//保存当前的URI
session.setAttribute("pageURI", request.getRequestURI());
//输出分页参数表单
paramBuffer.append("<input type='hidden' name='pageNo' value='" + pageNo + "'> ");
paramBuffer.append("<input type='hidden' name='pageSize' value='" + pageSize + "'> ");
paramBuffer.append("<input type='hidden' name='choice' value='" + choice + "'> ");
paramBuffer.append("<input type='hidden' name='total' value='" + total + "'> ");

output.append(paramBuffer.toString());
pageContext.setAttribute("pageSize", new Integer(pageSize));
pageContext.setAttribute("pageNo", new Integer(pageNo));
pageContext.setAttribute("total", new Integer(total));
pageContext.setAttribute("pages", new Integer(pages));
pageContext.setAttribute("index", new Integer(index));
}
}

3、ShowPageTextTagSupport:
import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.tagext.TagSupport;


/** *//**
* @author wangghost
*分页样式类
* TODO 要更改此生成的类型注释的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/

public class ShowPageTextTagSupport extends TagSupport...{


/** *//**
*
*/
private static final long serialVersionUID = 1L;


/** *//**
*
*/

public ShowPageTextTagSupport() ...{
super();
// TODO 自动生成构造函数存根
}
private String actionLocation = ""; //tld 中所跳转的action类路径!
public void setActionLocation(String str)

...{
this.actionLocation = str;
}

public int doStartTag() throws JspException ...{

try ...{
String bar = getNavigatorBar("text");
pageContext.getOut().write(bar);
return SKIP_BODY;
}

catch (IOException ioe) ...{
throw new JspException(ioe.getMessage());
}
}

/** *//**
* @param string
* @return
*/

private String getNavigatorBar(String type) ...{
String bar = "";
String pageNo = ((Integer) pageContext.getAttribute("pageNo")).toString();
String pages = ((Integer) pageContext.getAttribute("pages")).toString();
String total = ((Integer) pageContext.getAttribute("total")).toString();
String pageSize = ((Integer) pageContext.getAttribute("pageSize")).toString();
String nextDisabled = "";
String prevDisabled = "";
if (Integer.parseInt(pageNo) >= Integer.parseInt(pages))
nextDisabled = "disabled";
if (Integer.parseInt(pageNo) <= 1)
prevDisabled = "disabled";
//-------------------------文字型----------------------------//

if (type.equalsIgnoreCase("TEXT")) ...{
String pageSizeInput = "<input type='text' size='2' value='" + pageSize + "' "
+ "onChange="document.pager.choice.value='current';"
+ "this.form.pageSize.value=this.value;this.form.submit();">";
String firstText = "首 页";
String prevText = "上一页";
String nextText = "下一页";
String lastText = "最后一页";

if (prevDisabled.equalsIgnoreCase("")) ...{
firstText = "<a href='' "
+
"onClick="javascript:document.all.choice.value='first';document.forms[0].action='"+actionLocation+"';document.forms[0].submit();return false;">"
+ "首 页"
+ "</a>";
prevText = "<a href='' "
+
"onClick="javascript:document.all.choice.value='prev';document.forms[0].action='"+actionLocation+"';document.forms[0].submit();return false;">"
+ "上一页"
+ "</a>";
}

if (nextDisabled.equalsIgnoreCase("")) ...{
nextText = "<a href='' "
+
"onClick="javascript:document.all.choice.value='next';document.forms[0].action='"+actionLocation+"';document.forms[0].submit();return false;">"
+ "下一页"
+ "</a>";
lastText = "<a href='' "
+
"onClick="javascript:document.all.choice.value='last';document.forms[0].action='"+actionLocation+"';document.forms[0].submit();return false;">"
+ "最后一页"
+ "</a>";
}
String pageNoInput = "<input type='text' size='3' size='2' value='" + pageNo + "' "
+ "onChange="javascript:document.forms[0].pageNo.value=this.value">";

bar = "每页pageSize条记录 | "
+ "共pages页/total条记录 | "
+ "first prev next last | 第pageNo页 "
+
" <input type='submit' value='go' onClick="javascript:document.forms[0].choice.value='current';"> ";

bar = StringUtil.replace(bar, "pageSize", pageSizeInput);
bar = StringUtil.replace(bar, "pages", pages);
bar = StringUtil.replace(bar, "total", total);
bar = StringUtil.replace(bar, "first", firstText);
bar = StringUtil.replace(bar, "prev", prevText);
bar = StringUtil.replace(bar, "next", nextText);
bar = StringUtil.replace(bar, "last", lastText);
bar = StringUtil.replace(bar, "pageNo", pageNoInput);
} /////end of if(text)
return bar;
}


public int doEndTag() throws JspTagException

...{
return EVAL_PAGE;
}

}

最后贴出struts view层的代码:
1、showlist.jsp


<%...@ page language="java" contentType="text/html; charset=GB2312"%>

<%...@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>

<%...@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>

<%...@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>

<%...@ taglib uri="/WEB-INF/page.tld" prefix="page"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>列表页面</title>
</head>

<Style>...

Input {...}{font-family: verdana;font-size: 9pt;text-decoration: none;background-color: #FFFFFF;height: 20px;border: 1px solid #666666;color:#000000;}

.TableStyle {...}{font-family: verdana;text-decoration: none;width: 170;background-color: #C0D0E8;font-size: 9pt;border:1px dotted #666666;}
</Style>
<body>
<br><br><br>

<%...int total = Integer.parseInt(request.getAttribute("total").toString());%>
<logic:present name="personDetailList">
<p>列表信息为:</p>
<page:wangghost total="<%=total%>" defaultPageSize="10">
<table align="center" cellpadding="0" cellspacing="0" border="1" class="TableStyle" width="100%">
<tr>
<td><font size="3" color="red">姓名</font></td>
<td><font size="3" color="red">密码</font></td>
<td><font size="3" color="red">编码</font></td>
<td><font size="3" color="red">邮箱</font></td>
<td><font size="3" color="red">账户名</font></td>
<td><font size="3" color="red">账户类型</font></td>
<td><font size="3" color="red">创建时间</font></td>
<td><font size="3" color="red">钱</font></td>
</tr>
<logic:iterate name="personDetailList" id="person" scope="request" type="com.test.common.struts.actionforms.PersonDetail">
<tr>
<td><bean:write name="person" property="name" filter="true"/></td>
<td><bean:write name="person" property="password" filter="true"/></td>
<td><bean:write name="person" property="userid" filter="true"/></td>
<td><bean:write name="person" property="email" filter="true"/></td>
<td><bean:write name="person" property="accountname" filter="true"/></td>
<td><bean:write name="person" property="accounttype" filter="true"/></td>
<td><bean:write name="person" property="createdate" filter="true"/></td>
<td><bean:write name="person" property="balance" filter="true"/></td>
</tr>
</logic:iterate>
<tr>
<page:showghost actionLocation="/test/jsp/ShowListAction.do"/>
</tr>
</table>
<table align="center" cellpadding="0" cellspacing="0" border="0">
<tr><td></page:wangghost></td></tr>
</table>
</logic:present>
<logic:notPresent name="personDetailList">
<table align="center" cellpadding="0" cellspacing="0">
<tr><TH><font color="red" size="4">列表初始化失败!</font></TH></tr>
</table>
</logic:notPresent>
</body>
</html>

2.addperson.jsp

<%...@ page contentType="text/html;charset=GBK"%>

<%...@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<html:html>

<body>
<p><font size=4 color=red>The Test for Hibernate + Spring + Struts:</font></p>
<html:form action="/jsp/addPerson" method="post">
<table border=0>
<tr>
<td>姓:</td><td><html:text property="fristname"/></td>
<td>名:</td><td><html:text property="lastname"/></td>
</tr>
<tr>
<td>邮箱:</td><td><html:text property="email"/></td>
<tr>
<tr>
<td>密码:</td><td><html:password property="password"/></td>
</tr>
<tr>
<td>账户名称:</td><td><html:text property="accountname"/></td>
</tr>
<tr>
<td>账户类型:</td><td><html:text property="accounttype"/></td>
</tr>
<tr>
<td>客户编码:</td><td><html:text property="userid"/></td>
</tr>
<tr align="center">
<td><html:submit/><html:reset/></td>
</tr>
</table>
</html:form>
</body>
</html:html>
希望您给出宝贵意见,谢谢。