Struts作为MVC 2的Web框架,自推出以来不断受到开发者的追捧,得到广泛的应用。作为最成功的Web框架,Struts自然拥有众多的优点:MVC 2模型的使用、功能齐全的标志库(Tag Library)、开放源代码。而Spring的出现,在某些方面极大的方面了Struts的开发。同时,Hibernate作为对象持久化的框架,能显示的提高软件开发的效率与生产力。这三种流行框架的整合应用,可以发挥它们各自的优势,使软件开发更加的快速与便捷。
struts2发布已经很久了,但关于如何使用它的教程及实例并不多。特别是与Spring及Hibernate等流行框架的集成,并不多见。现在就将笔者使用Myeclipse工具应用struts2 + spring2 +hibernate3 实现CRUD操作的步骤一一纪录下来,为初学者少走弯路略尽绵薄之力!在本文中,笔者将Struts2.0.6、Spring2.0.6和Hibernate3.1进行整合,希望通过这样的整合示例,让读者了解这些框架各自的特点,以便于在自己的项目中,根据实际情况,尽快的过渡到Struts2的时代。本文的内容基于Struts2.0.6。
一、准备工作
spring2与1.x区别不大,可以平滑的过度,笔者也是把spring1.28换成了spring2.0.6,算是升级到spring 2.0了。struts2基本就是webwork2.2,与以前的struts1.x可以说没任何关系了。因为是第一次用struts2,也是第一次用webwork,所以有很多不完善,不规范的地方,还望大家来拍砖。
开发环境:MyEclipse5.0+Eclipse3.2+JDK5.0+
Tomcat5.5+struts2+Spring2.0.6+Hibernate3.1。本示例通过对一个图书进行管理的系统,提供基本的增加、删除、修改、查询等功能。
lib包需要以下右图所示的这些包。其中Struts2.0.6的下载地址为:
http://people.apache.org/builds/struts/2.0.6
Hibernate3.1的下载地址为:
http://www.hibernate.org
spring2.0.6的下载地址为:
http://www.springframework.org
使用的数据库为mysql 5.0,使用的JDBC驱动JAR包为:mysql-connection-java-5.0.4-bin
创建数据表的sql语句为:
createdatabase game
CREATETABLE `books` (
`book_id`int(11) NOT NULL default ‘0‘,
`book_name`varchar(200) character set gb2312 default NULL,
`book_author`varchar(100) character set gb2312 default NULL,
`book_publish`varchar(100) character set gb2312 default NULL,
`book_date`date default NULL,
`book_isbn`varchar(20) default NULL,
`book_page`int(11) default NULL,
`book_price`decimal(10,2) default NULL,
`book_content`varchar(100) character set gb2312 default NULL,
PRIMARYKEY (`book_id`)
)ENGINE=InnoDB DEFAULT CHARSET=gbk ROW_FORMAT=COMPRESSED;
二、建立公共类
1、AbstractAction类
Struts2和Struts1.x的差别,最明显的就是Struts2是一个pull-MVC架构。Struts1.x 必须继承org.apache.struts.action.Action或者其子类,表单数据封装在FormBean中。Struts 2无须继承任何类型或实现任何接口,表单数据包含在Action中,通过Getter和Setter获取。
虽然,在理论上Struts2的Action无须实现任何接口或者是继承任何的类,但是,在实际编程过程中,为了更加方便的实现Action,大多数情况下都会继承com.opensymphony.xwork2.ActionSupport类,并且重载(Override)此类里的String execute()方法。因此先建立抽象类,以供其它Action类使用。
packagecom.sterning.commons;
importcom.opensymphony.xwork2.ActionSupport;
publicclass AbstractAction extends ActionSupport {
}
com.sterning.commons.AbstractAction.java
参考JavaDoc,可知ActionSupport类实现了接口:
com.opensymphony.xwork2.Action
com.opensymphony.xwork2.LoaleProvider
com.opensymphony.xwork2.TextProvider
com.opensymphony.xwork2.Validateable
com.opensymphony.xwork2.ValidationAware
com.uwyn.rife.continuations.ContinuableObject
java.io.Searializable
java.lang.Cloneable
2、Pager分页类
为了增加程序的分页功能,特意建立共用的分页类。
packagecom.sterning.commons;
importjava.math.*;
publicclass Pager {
privateint totalRows; //总行数
private int pageSize = 5; //每页显示的行数
private int currentPage; //当前页号
private int totalPages; //总页数
private int startRow; //当前页在数据库中的起始行
publicPager() {
}
publicPager(int _totalRows) {
totalRows= _totalRows;
totalPages=totalRows/pageSize;
intmod=totalRows%pageSize;
if(mod>0){
totalPages++;
}
currentPage= 1;
startRow= 0;
}
publicint getStartRow() {
returnstartRow;
}
publicint getTotalPages() {
returntotalPages;
}
publicint getCurrentPage() {
returncurrentPage;
}
publicint getPageSize() {
returnpageSize;
}
publicvoid setTotalRows(int totalRows) {
this.totalRows= totalRows;
}
publicvoid setStartRow(int startRow) {
this.startRow= startRow;
}
publicvoid setTotalPages(int totalPages) {
this.totalPages= totalPages;
}
publicvoid setCurrentPage(int currentPage) {
this.currentPage= currentPage;
}
publicvoid setPageSize(int pageSize) {
this.pageSize= pageSize;
}
publicint getTotalRows() {
returntotalRows;
}
publicvoid first() {
currentPage= 1;
startRow= 0;
}
publicvoid previous() {
if(currentPage == 1) {
return;
}
currentPage--;
startRow= (currentPage - 1) * pageSize;
}
publicvoid next() {
if(currentPage < totalPages) {
currentPage++;
}
startRow= (currentPage - 1) * pageSize;
}
publicvoid last() {
currentPage= totalPages;
startRow= (currentPage - 1) * pageSize;
}
publicvoid refresh(int _currentPage) {
currentPage= _currentPage;
if(currentPage > totalPages) {
last();
}
}
}
com.sterning.commons.Pager.java
同时,采用PagerService类来发布成为分页类服务PagerService,代码如下:
packagecom.sterning.commons;
publicclass PagerService {
publicPager getPager(String currentPage,String pagerMethod,int totalRows) {
// 定义pager对象,用于传到页面
Pager pager = new Pager(totalRows);
// 如果当前页号为空,表示为首次查询该页
// 如果不为空,则刷新pager对象,输入当前页号等信息
if (currentPage != null) {
pager.refresh(Integer.parseInt(currentPage));
}
// 获取当前执行的方法,首页,前一页,后一页,尾页。
if (pagerMethod != null) {
if(pagerMethod.equals("first")) {
pager.first();
}else if (pagerMethod.equals("previous")) {
pager.previous();
}else if (pagerMethod.equals("next")) {
pager.next();
}else if (pagerMethod.equals("last")) {
pager.last();
}
}
returnpager;
}
}
com.sterning.commons.PagerService.java
三、建立数据持久化层
1、编写实体类Books及books.hbm.xml映射文件。
packagecom.sterning.books.model;
importjava.util.Date;
publicclass Books {
// Fields
private String bookId;//编号
private String bookName;//书名
private String bookAuthor;//作者
private String bookPublish;//出版社
private Date bookDate;//出版日期
private String bookIsbn;//ISBN
private String bookPage;//页数
private String bookPrice;//价格
private String bookContent;//内容提要
// Constructors
public Books(){}
// Property accessors
public String getBookId() {
returnbookId;
}
publicvoid setBookId(String bookId) {
this.bookId= bookId;
}
publicString getBookName() {
returnbookName;
}
publicvoid setBookName(String bookName) {
this.bookName= bookName;
}
publicString getBookAuthor() {
returnbookAuthor;
}
publicvoid setBookAuthor(String bookAuthor) {
this.bookAuthor= bookAuthor;
}
publicString getBookContent() {
returnbookContent;
}
publicvoid setBookContent(String bookContent) {
this.bookContent= bookContent;
}
publicDate getBookDate() {
returnbookDate;
}
publicvoid setBookDate(Date bookDate) {
this.bookDate= bookDate;
}
publicString getBookIsbn() {
returnbookIsbn;
}
publicvoid setBookIsbn(String bookIsbn) {
this.bookIsbn= bookIsbn;
}
publicString getBookPage() {
returnbookPage;
}
publicvoid setBookPage(String bookPage) {
this.bookPage= bookPage;
}
publicString getBookPrice() {
returnbookPrice;
}
publicvoid setBookPrice(String bookPrice) {
this.bookPrice= bookPrice;
}
publicString getBookPublish() {
returnbookPublish;
}
publicvoid setBookPublish(String bookPublish) {
this.bookPublish= bookPublish;
}
}
com.sterning.books.model.Books.java
接下来要把实体类Books的属性映射到books表,编写下面的books.hbm.xml文件:
<?xmlversion="1.0"?>
<!DOCTYPEhibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<classname="com.sterning.books.model.Books" table="books" >
<id name="bookId"type="string">
<column name="book_id"length="5" />
<generatorclass="assigned" />
</id>
<property name="bookName"type="string">
<columnname="book_name" length="100" />
</property>
<propertyname="bookAuthor" type="string">
<columnname="book_author" length="100" />
</property>
<propertyname="bookPublish" type="string">
<columnname="book_publish" length="100" />
</property>
<property name="bookDate"type="java.sql.Timestamp">
<columnname="book_date" length="7" />
</property>
<propertyname="bookIsbn" type="string">
<columnname="book_isbn" length="20" />
</property>
<property name="bookPage"type="string">
<columnname="book_page" length="11" />
</property>
<property name="bookPrice"type="string">
<columnname="book_price" length="4" />
</property>
<propertyname="bookContent" type="string">
<columnname="book_content" length="100" />
</property>
</class>
</hibernate-mapping>
com.sterning.books.model.books.hbm.xml
2、hibernate.cfg.xml配置文件如下:(注意它的位置在scr/hibernate.cfg.xml)
<?xmlversion="1.0" encoding="ISO-8859-1"?>
<!DOCTYPEhibernate-configuration PUBLIC
"-//Hibernate/HibernateConfiguration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<propertyname="show_sql">true</property>
<mappingresource="com/sterning/books/model/books.hbm.xml"></mapping>
</session-factory>
</hibernate-configuration>
Com.sterning.bean.hibernate.hibernate.cfg.xml