Struts2、Spring和Hibernate应用实例

本文详细介绍了如何使用MyEclipse工具结合Struts2、Spring2和Hibernate3实现图书管理系统的CRUD操作,包括数据持久化、业务逻辑层设计、Action类实现以及Web页面展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Struts2SpringHibernate应用实例

Struts作为MVC 2Web框架,自推出以来不断受到开发者的追捧,得到广泛的应用。作为最成功的Web框架,Struts自然拥有众多的优点:MVC 2模型的使用、功能齐全的标志库(Tag Library)、开放源代码。而Spring的出现,在某些方面极大的方面了Struts的开发。同时,Hibernate作为对象持久化的框架,能显示的提高软件开发的效率与生产力。这三种流行框架的整合应用,可以发挥它们各自的优势,使软件开发更加的快速与便捷。

struts2发布已经很久了,但关于如何使用它的教程及实例并不多。特别是与SpringHibernate等流行框架的集成,并不多见。现在就将笔者使用Myeclipse工具应用struts2 + spring2 +hibernate3 实现CRUD操作的步骤一一纪录下来,为初学者少走弯路略尽绵薄之力!在本文中,笔者将Struts2.0.6Spring2.0.6Hibernate3.1进行整合,希望通过这样的整合示例,让读者了解这些框架各自的特点,以便于在自己的项目中,根据实际情况,尽快的过渡到Struts2的时代。本文的内容基于Struts2.0.6

一、准备工作

spring21.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;

二、建立公共类

1AbstractAction

Struts2Struts1.x的差别,最明显的就是Struts2是一个pull-MVC架构。Struts1.x 必须继承org.apache.struts.action.Action或者其子类,表单数据封装在FormBean中。Struts 2无须继承任何类型或实现任何接口,表单数据包含在Action中,通过GetterSetter获取。

虽然,在理论上Struts2Action无须实现任何接口或者是继承任何的类,但是,在实际编程过程中,为了更加方便的实现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

2Pager分页类

为了增加程序的分页功能,特意建立共用的分页类。

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、编写实体类Booksbooks.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

2hibernate.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

四、建立DAO

DAO访问层负责封装底层的数据访问细节,不仅可以使概念清晰,而且可以提高开发效率。

1、建立DAO的接口类:BooksDao

packagecom.sterning.books.dao.iface;

importjava.util.List;

importcom.sterning.books.model.Books;

publicinterface BooksDao {

ListgetAll();//获得所有记录

List getBooks(int pageSize, intstartRow);//获得所有记录

int getRows();//获得总行数

int getRows(String fieldname,Stringvalue);//获得总行数

List queryBooks(String fieldname,Stringvalue);//根据条件查询

List getBooks(String fieldname,Stringvalue,int pageSize, int startRow);//根据条件查询

Books getBook(String bookId);//根据ID获得记录

String getMaxID();//获得最大ID

void addBook(Books book);//添加记录

void updateBook(Books book);//修改记录

void deleteBook(Books book);//删除记录

}

com.sterning.books.dao.iface.BooksDao.java

2、实现此接口的类文件,BooksMapDao

packagecom.sterning.books.dao.hibernate;

importjava.sql.SQLException;

importjava.util.Iterator;

importjava.util.List;

importorg.hibernate.HibernateException;

importorg.hibernate.Query;

importorg.hibernate.Session;

importorg.springframework.orm.hibernate3.HibernateCallback;

importorg.springframework.orm.hibernate3.support.HibernateDaoSupport;

importcom.sterning.books.dao.iface.BooksDao;

importcom.sterning.books.model.Books;

importcom.sterning.commons.PublicUtil;

/**

*@author cwf

*

*/

publicclass BooksMapDao extends HibernateDaoSupport implements BooksDao {

publicBooksMapDao(){}

/**

* 函数说明:添加信息

* 参数说明:对象

* 返回值:

*/

public void addBook(Books book) {

this.getHibernateTemplate().save(book);

}

/**

* 函数说明:删除信息

* 参数说明:对象

* 返回值:

*/

public void deleteBook(Books book) {

this.getHibernateTemplate().delete(book);

}

/**

* 函数说明:获得所有的信息

* 参数说明:

* 返回值:信息的集合

*/

public List getAll() {

Stringsql="FROM Books ORDER BY bookName";

returnthis.getHibernateTemplate().find(sql);

}

/**

* 函数说明:获得总行数

* 参数说明:

* 返回值:总行数

*/

public int getRows() {

Stringsql="FROM Books ORDER BY bookName";

Listlist=this.getHibernateTemplate().find(sql);

returnlist.size();

}

/**

* 函数说明:获得所有的信息

* 参数说明:

* 返回值:信息的集合

*/

public List getBooks(int pageSize, intstartRow) throws HibernateException {

finalint pageSize1=pageSize;

finalint startRow1=startRow;

returnthis.getHibernateTemplate().executeFind(new HibernateCallback(){

publicList doInHibernate(Session session) throws HibernateException, SQLException {

//TODO 自动生成方法存根

Queryquery=session.createQuery("FROM Books ORDER BY bookName");

query.setFirstResult(startRow1);

query.setMaxResults(pageSize1);

returnquery.list();

}

});

}

/**

* 函数说明:获得一条的信息

* 参数说明: ID

* 返回值:对象

*/

public Books getBook(String bookId) {

return(Books)this.getHibernateTemplate().get(Books.class,bookId);

}

/**

* 函数说明:获得最大ID

* 参数说明:

* 返回值:最大ID

*/

public String getMaxID() {

Stringdate=PublicUtil.getStrNowDate();

Stringsql="SELECT MAX(bookId)+1 FROM Books";

StringnoStr = null;

Listll = (List) this.getHibernateTemplate().find(sql);

Iteratoritr = ll.iterator();

if(itr.hasNext()) {

Objectnoint = itr.next();

if(noint== null){

noStr= "1";

}else{

noStr= noint.toString();

}

}

if(noStr.length()==1){

noStr="000"+noStr;

}elseif(noStr.length()==2){

noStr="00"+noStr;

}elseif(noStr.length()==3){

noStr="0"+noStr;

}else{

noStr=noStr;

}

returnnoStr;

}

/**

* 函数说明:修改信息

* 参数说明:对象

* 返回值:

*/

public void updateBook(Books pd) {

this.getHibernateTemplate().update(pd);

}

/**

* 函数说明:查询信息

* 参数说明:集合

* 返回值:

*/

public List queryBooks(Stringfieldname,String value) {

System.out.println("value:"+value);

Stringsql="FROM Books where "+fieldname+" like'%"+value+"%'"+"ORDER BY bookName";

returnthis.getHibernateTemplate().find(sql);

}

/**

* 函数说明:获得总行数

* 参数说明:

* 返回值:总行数

*/

public int getRows(String fieldname,Stringvalue) {

Stringsql="";

if(fieldname==null||fieldname.equals("")||fieldname==null||fieldname.equals(""))

sql="FROMBooks ORDER BY bookName";

else

sql="FROMBooks where "+fieldname+" like'%"+value+"%'"+"ORDER BY bookName";

Listlist=this.getHibernateTemplate().find(sql);

returnlist.size();

}

/**

* 函数说明:查询信息

* 参数说明:集合

* 返回值:

*/

publicList getBooks(String fieldname,String value,int pageSize, int startRow) {

finalint pageSize1=pageSize;

finalint startRow1=startRow;

finalString queryName=fieldname;

finalString queryValue=value;

Stringsql="";

if(queryName==null||queryName.equals("")||queryValue==null||queryValue.equals(""))

sql="FROMBooks ORDER BY bookName";

else

sql="FROMBooks where "+fieldname+" like'%"+value+"%'"+"ORDER BY bookName";

finalString sql1=sql;

returnthis.getHibernateTemplate().executeFind(new HibernateCallback(){

publicList doInHibernate(Session session) throws HibernateException, SQLException {

//TODO 自动生成方法存根

Queryquery=session.createQuery(sql1);

query.setFirstResult(startRow1);

query.setMaxResults(pageSize1);

returnquery.list();

}

});

}

}

五、业务逻辑层

在业务逻辑层需要认真思考每个业务逻辑所能用到的持久层对象和DAODAO层之上是业务逻辑层,DAO类可以有很多个,但业务逻辑类应该只有一个,可以在业务逻辑类中调用各个DAO类进行操作。

1、创建服务接口类IBookService

packagecom.sterning.books.services.iface;

importjava.util.List;

importcom.sterning.books.model.Books;

publicinterface IBooksService ...{

List getAll();//获得所有记录

List getBooks(int pageSize, intstartRow);//获得所有记录

int getRows();//获得总行数

int getRows(String fieldname,Stringvalue);//获得总行数

List queryBooks(String fieldname,Stringvalue);//根据条件查询

List getBooks(String fieldname,Stringvalue,int pageSize, int startRow);//根据条件查询

Books getBook(String bookId);//根据ID获得记录

String getMaxID();//获得最大ID

void addBook(Books pd);//添加记录

void updateBook(Books pd);//修改记录

void deleteBook(String bookId);//删除记录

}

com.sterning.books.services.iface.IBookService.java

2、实现此接口类:BookService

packagecom.sterning.books.services;

importjava.util.List;

importcom.sterning.books.dao.iface.BooksDao;

importcom.sterning.books.model.Books;

importcom.sterning.books.services.iface.IBooksService;

publicclass BooksService implements IBooksService{

privateBooksDao booksDao;

publicBooksService(){}

/**

* 函数说明:添加信息

* 参数说明:对象

* 返回值:

*/

public void addBook(Books book) {

booksDao.addBook(book);

}

/**

* 函数说明:删除信息

* 参数说明:对象

* 返回值:

*/

public void deleteBook(String bookId) {

Booksbook=booksDao.getBook(bookId);

booksDao.deleteBook(book);

}

/**

* 函数说明:获得所有的信息

* 参数说明:

* 返回值:信息的集合

*/

public List getAll() {

returnbooksDao.getAll();

}

/**

* 函数说明:获得总行数

* 参数说明:

* 返回值:总行数

*/

public int getRows() {

returnbooksDao.getRows();

}

/**

* 函数说明:获得所有的信息

* 参数说明:

* 返回值:信息的集合

*/

public List getBooks(int pageSize, intstartRow) {

returnbooksDao.getBooks(pageSize, startRow);

}

/**

* 函数说明:获得一条的信息

* 参数说明: ID

* 返回值:对象

*/

public Books getBook(String bookId) {

returnbooksDao.getBook(bookId);

}

/**

* 函数说明:获得最大ID

* 参数说明:

* 返回值:最大ID

*/

public String getMaxID() {

returnbooksDao.getMaxID();

}

/**

* 函数说明:修改信息

* 参数说明:对象

* 返回值:

*/

public void updateBook(Books book) {

booksDao.updateBook(book);

}

/**

* 函数说明:查询信息

* 参数说明:集合

* 返回值:

*/

public List queryBooks(Stringfieldname,String value) {

returnbooksDao.queryBooks(fieldname, value);

}

/**

* 函数说明:获得总行数

* 参数说明:

* 返回值:总行数

*/

public int getRows(String fieldname,Stringvalue) {

returnbooksDao.getRows(fieldname, value);

}

/**

* 函数说明:查询信息

* 参数说明:集合

* 返回值:

*/

public List getBooks(Stringfieldname,String value,int pageSize, int startRow) {

returnbooksDao.getBooks(fieldname, value,pageSize,startRow);

}

publicBooksDao getBooksDao() {

returnbooksDao;

}

publicvoid setBooksDao(BooksDao booksDao) {

this.booksDao= booksDao;

}

}

六、创建Action类:BookAction

Struts 1.x经验的朋友都知道ActionStruts的核心内容,当然Struts 2.0也不例外。不过,Struts 1.xStruts 2.0Action模型很大的区别。

Struts 1.x

Stuts 2.0

接口

必须继承org.apache.struts.action.Action或者其子类

无须继承任何类型或实现任何接口

表单数据

表单数据封装在FormBean

表单数据包含在Action中,通过GetterSetter获取

1、建立BookAction

packagecom.sterning.books.web.actions;

importjava.util.Collection;

importcom.sterning.books.model.Books;

importcom.sterning.books.services.iface.IBooksService;

importcom.sterning.commons.AbstractAction;

importcom.sterning.commons.Pager;

importcom.sterning.commons.PagerService;

publicclass BooksAction extends AbstractAction {

private IBooksService booksService;

private PagerService pagerService;

privateBooks book;

private Pager pager;

protected Collection availableItems;

protected String currentPage;

protected String pagerMethod;

protected String totalRows;

protected String bookId;

protected String queryName;

protected String queryValue;

protected String searchName;

protected String searchValue;

protected String queryMap;

public String list() throws Exception {

if(queryMap==null||queryMap.equals("")){

}else{

String[]str=queryMap.split("~");

this.setQueryName(str[0]);

this.setQueryValue(str[1]);

}

System.out.println("asd"+this.getQueryValue());

inttotalRow=booksService.getRows(this.getQueryName(),this.getQueryValue());

pager=pagerService.getPager(this.getCurrentPage(), this.getPagerMethod(),totalRow);

this.setCurrentPage(String.valueOf(pager.getCurrentPage()));

this.setTotalRows(String.valueOf(totalRow));

availableItems=booksService.getBooks(this.getQueryName(),this.getQueryValue(),pager.getPageSize(),pager.getStartRow());

this.setQueryName(this.getQueryName());

this.setQueryValue(this.getQueryValue());

this.setSearchName(this.getQueryName());

this.setSearchValue(this.getQueryValue());

return SUCCESS;

}

public String load() throws Exception {

if(bookId!=null)

book =booksService.getBook(bookId);

else

bookId=booksService.getMaxID();

return SUCCESS;

}

public String save() throws Exception {

if(this.getBook().getBookPrice().equals("")){

this.getBook().setBookPrice("0.0");

}

String id=this.getBook().getBookId();

Books book=booksService.getBook(id);

if(book == null)

booksService.addBook(this.getBook());

else

booksService.updateBook(this.getBook());

this.setQueryName(this.getQueryName());

this.setQueryValue(this.getQueryValue());

if(this.getQueryName()==null||this.getQueryValue()==null||this.getQueryName().equals("")||this.getQueryValue().equals("")){

}else{

queryMap=this.getQueryName()+"~"+this.getQueryValue();

}

return SUCCESS;

}

public String delete() throws Exception {

booksService.deleteBook(this.getBookId());

if(this.getQueryName()==null||this.getQueryValue()==null||this.getQueryName().equals("")||this.getQueryValue().equals("")){

}else{

queryMap=this.getQueryName()+"~"+this.getQueryValue();

}

return SUCCESS;

}

public Books getBook() {

return book;

}

public void setBook(Books book) {

this.book = book;

}

public IBooksService getBooksService() {

return booksService;

}

public void setBooksService(IBooksServicebooksService) {

this.booksService = booksService;

}

public Collection getAvailableItems() {

return availableItems;

}

public String getCurrentPage() {

return currentPage;

}

public void setCurrentPage(StringcurrentPage) {

this.currentPage = currentPage;

}

public String getPagerMethod() {

return pagerMethod;

}

public void setPagerMethod(StringpagerMethod) {

this.pagerMethod = pagerMethod;

}

public Pager getPager() {

return pager;

}

public void setPager(Pager pager) {

this.pager = pager;

}

public String getTotalRows() {

return totalRows;

}

public void setTotalRows(String totalRows){

this.totalRows = totalRows;

}

public String getBookId() {

return bookId;

}

public void setBookId(String bookId) {

this.bookId = bookId;

}

public String getQueryName() {

return queryName;

}

public void setQueryName(String queryName){

this.queryName = queryName;

}

public String getQueryValue() {

return queryValue;

}

public void setQueryValue(StringqueryValue) {

this.queryValue = queryValue;

}

public String getSearchName() {

return searchName;

}

public void setSearchName(StringsearchName) {

this.searchName = searchName;

}

public String getSearchValue() {

return searchValue;

}

public void setSearchValue(StringsearchValue) {

this.searchValue = searchValue;

}

public String getQueryMap() {

return queryMap;

}

public void setQueryMap(String queryMap) {

this.queryMap = queryMap;

}

public PagerService getPagerService() {

return pagerService;

}

public void setPagerService(PagerServicepagerService) {

this.pagerService = pagerService;

}

}

com.sterning.books.web.actions.BookAction.java

1)、默认情况下,当请求bookAction.action发生时(这个会在后面的Spring配置文件中见到的)Struts运行时(Runtime)根据struts.xml里的Action映射集(Mapping),实例化com.sterning.books.web.actions.BookAction类,并调用其execute方法。当然,我们可以通过以下两种方法改变这种默认调用。这个功能(Feature)有点类似Struts 1.x中的LookupDispathAction

classes/sturts.xml中新建Action,并指明其调用的方法;

访问Action时,在Action名后加上“!xxx”(xxx为方法名)。

2)、细心的朋友应该可能会发现com.sterning.books.web.actions.BookAction.javaAction方法(execute)返回都是SUCCESS。这个属性变量我并没有定义,所以大家应该会猜到它在ActionSupport或其父类中定义。没错,SUCCESS在接口com.opensymphony.xwork2.Action中定义,另外同时定义的还有ERROR, INPUT, LOGIN, NONE

此外,我在配置Action时都没有为result定义名字(name),所以它们默认都为success。值得一提的是Struts 2.0中的result不仅仅是Struts 1.xforward的别名,它可以实现除forward外的很激动人心的功能,如将Action输出到FreeMaker模板、Velocity模板、JasperReports和使用XSL转换等。这些都过result里的type(类型)属性(Attribute)定义的。另外,您还可以自定义result类型。

3)、使用Struts 2.0,表单数据的输入将变得非常方便,和普通的POJO一样在Action编写GetterSetter,然后在JSPUI标志的name与其对应,在提交表单到Action时,我们就可以取得其值。

4)、Struts 2.0更厉害的是支持更高级的POJO访问,如this.getBook().getBookPrice()private Books book所引用的是一个关于书的对象类,它可以做为一个属性而出现在BookActoin.java类中。这样对我们开发多层系统尤其有用。它可以使系统结构更清晰。

5)、有朋友可能会这样问:“如果我要取得Servlet API中的一些对象,如requestresponsesession等,应该怎么做?这里的execute不像Struts 1.x的那样在参数中引入。”开发Web应用程序当然免不了跟这些对象打交道。在Strutx 2.0中可以有两种方式获得这些对象:非IoC(控制反转Inversion of Control)方式和IoC方式。

IoC方式

要获得上述对象,关键是Struts 2.0com.opensymphony.xwork2.ActionContext类。我们可以通过它的静态方法getContext()获取当前Action的上下文对象。另外,org.apache.struts2.ServletActionContext作为辅助类(Helper Class),可以帮助您快捷地获得这几个对象。

HttpServletRequestrequest = ServletActionContext.getRequest();

HttpServletResponseresponse = ServletActionContext.getResponse();

HttpSessionsession = request.getSession();

如果你只是想访问session的属性(Attribute),你也可以通过ActionContext.getContext().getSession()获取或添加session范围(Scoped)的对象。

IoC方式

要使用IoC方式,我们首先要告诉IoC容器(Container)想取得某个对象的意愿,通过实现相应的接口做到这点。如实现SessionAware,ServletRequestAware, ServletResponseAware接口,从而得到上面的对象。

1、对BookAction类的Save方法进行验证

正如《Writing Secure Code》文中所写的名言All input is evil:“所有的输入都是罪恶的”,所以我们应该对所有的外部输入进行校验。而表单是应用程序最简单的入口,对其传进来的数据,我们必须进行校验。Struts2的校验框架十分简单方便,只在如下两步:

Xxx-validation.xml文件中的<message>元素中加入key属性;

在相应的jsp文件中的<s:form>标志中加入validate="true"属性,就可以在用Javascript在客户端校验数据。

其验证文件为:BooksAction-save-validation.xml

<?xmlversion="1.0" encoding="UTF-8"?>

<!DOCTYPEvalidators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0//EN""http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd">

<validators>

<!-- Field-Validator Syntax -->

<fieldname="book.bookName">

<field-validatortype="requiredstring">

<messagekey="book.bookName.required"/>

</field-validator>

</field>

<fieldname="book.bookAuthor">

<field-validatortype="requiredstring">

<messagekey="book.bookAuthor.required"/>

</field-validator>

</field>

<fieldname="book.bookPublish">

<field-validator type="requiredstring">

<messagekey="book.bookPublish.required"/>

</field-validator>

</field>

</validators>

com.sterning.books.web.actions.BooksAction-save-validation.xml

1、对BookAction类的Save方法进行验证的资源文件

注意配置文件的名字应该是:配置文件(类名-validation.xml)的格式。BooksAction类的验证资源文件为:BooksAction.properties

book=Books

book.bookName.required=\u8bf7\u8f93\u5165\u4e66\u540d

book.bookAuthor.required=\u8bf7\u8f93\u5165\u4f5c\u8005

book.bookPublish.required=\u8bf7\u8f93\u5165\u51fa\u7248\u793e

format.date={0,date,yyyy-MM-dd}

com.sterning.books.web.actions.BooksAction.properties

资源文件的查找顺序是有一定规则的。之所以说Struts 2.0的国际化更灵活是因为它可以根据不同需要配置和获取资源(properties)文件。在Struts 2.0中有下面几种方法:

1)、使用全局的资源文件。这适用于遍布于整个应用程序的国际化字符串,它们在不同的包(package)中被引用,如一些比较共用的出错提示;

2)、使用包范围内的资源文件。做法是在包的根目录下新建名的package.propertiespackage_xx_XX.properties文件。这就适用于在包中不同类访问的资源;

3)、使用Action范围的资源文件。做法为Action的包下新建文件名(除文件扩展名外)与Action类名同样的资源文件。它只能在该Action中访问。如此一来,我们就可以在不同的Action里使用相同的properties名表示不同的值。例如,在ActonOnetitle为“动作一”,而同样用titleActionTwo表示“动作二”,节省一些命名工夫;

4)、使用<s:i18n>标志访问特定路径的properties文件。在使用这一方法时,请注意<s:i18n>标志的范围。在<s:i18nname="xxxxx"></s:i18n>之间,所有的国际化字符串都会在名为xxxxx资源文件查找,如果找不到,Struts 2.0就会输出默认值(国际化字符串的名字)。

例如:某个ChildAction中调用了getText("user.title")Struts 2.0的将会执行以下的操作:

查找ChildAction_xx_XX.properties文件或ChildAction.properties

查找ChildAction实现的接口,查找与接口同名的资源文件MyInterface.properties

查找ChildAction的父类ParentActionproperties文件,文件名为ParentAction.properties

判断当前ChildAction是否实现接口ModelDriven。如果是,调用getModel()获得对象,查找与其同名的资源文件;

查找当前包下的package.properties文件;

查找当前包的父包,直到最顶层包;

在值栈(Value Stack)中,查找名为user的属性,转到user类型同名的资源文件,查找键为title的资源;

查找在struts.properties配置的默认的资源文件,参考例1;

输出user.title

七、 Web页面

在这一节中,主要使用到了Struts2的标签库。在这里,会对所用到的主要标签做一个初步的介绍。更多的知识请读者访问Struts的官方网站做更多的学习。在编写Web页面之前,先从总体上,对Struts 1.xStruts 2.0的标志库(Tag Library)作比较。

Struts 1.x

Struts 2.0

分类

将标志库按功能分成HTMLTilesLogicBean等几部分

严格上来说,没有分类,所有标志都在URI为“/struts-tags”命名空间下,不过,我们可以从功能上将其分为两大类:非UI标志和UI标志

表达式语言(expression languages

不支持嵌入语言(EL

OGNLJSTLGroovyVelcity

1、主页面:index.jsp,其代码如下:

<%@pagepageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>

<%@taglib prefix="s" uri="/struts-tags" %>

<html>

<head>

<metahttp-equiv="Content-Type" content="text/html;charset=GBK"/>

<title>图书管理系统</title>

</head>

<body>

<p><ahref="<s:url action="list" />">进入图书管理系统</a></p>

</body>

</html>

WebRoot/index.jsp

要在JSP中使用Struts 2.0标志,先要指明标志的引入。通过在JSP的代码的顶部加入以下代码可以做到这点。<%@taglibprefix="s" uri="/struts-tags" %>

1<s:url>标签:该标签用于创建url,可以通过"param"标签提供request参数。当includeParams的值时'all'或者'get', param标签中定义的参数将有优先权,也就是说其会覆盖其他同名参数的值。

2、列表页面:list.jsp

<%@pagepageEncoding="gb2312" contentType="text/html;charset=UTF-8" %>

<%@taglib prefix="s" uri="/struts-tags" %>

<html>

<head><title>图书管理系统</title></head>

<style type="text/css">

table {

border: 1px solid black;

border-collapse: collapse;

}

table thead tr th {

border: 1px solid black;

padding: 3px;

background-color: #cccccc;

background-color:expression(this.rowIndex % 2 == 0 ? "#FFFFFF" : "#EEEEEE");

}

table tbody tr td {

border: 1px solid black;

padding: 3px;

}

.trs{

background-color: expression(this.rowIndex% 2 == 0 ? "#FFFFFF" : "#EEEEEE");

}

</style>

<scriptlanguage="JavaScript">

function doSearch(){

if(document.all.searchValue.value=="")

{

alert("请输入查询关键字!");

}else{

window.location.href="bookAdmin/list.action?queryName="+document.all.searchName.value+"&&queryValue="+document.all.searchValue.value;

}

}

</script>

<body>

<tablealign="center">

<tralign="center">

<td>

<selectname="searchName">

<optionvalue="bookName">书名</option>

<optionvalue="bookAuthor">作者</option>

<optionvalue="bookPublish">出版社</option>

<optionvalue="bookDate">出版日期</option>

<optionvalue="bookIsbn">ISNB</option>

<optionvalue="bookPage">页数</option>

</select>

<input type="text"name="searchValue" value="" size="10"/>

<input type="button"value="查询"onClick="doSearch();">

</td>

</tr>

<tralign="center">

<td>

<a href="<s:urlaction="list" includeParams="none"/>">全部</a>

<a href='<s:urlaction="edit" ></s:url>'>增加</a>

</td>

</tr>

<tr>

<td>

<tablecellspacing="0" align="center">

<thead>

<tr>

<th>书名</th>

<th>作者</th>

<th>出版社</th>

<th>出版日期</th>

<th>ISNB</th>

<th>页数</th>

<th>价格</th>

<th>内容提要</th>

<th>删除</th>

</tr>

</thead>

<tbody>

<s:iteratorvalue="availableItems">

<tr class="trs">

<td>

<a href='<s:urlaction="edit" ><s:param name="bookId"value="bookId" /></s:url>'>

<s:propertyvalue="bookName"/>

</a>

</td>

<td><s:propertyvalue="bookAuthor"/></td>

<td><s:propertyvalue="bookPublish"/></td>

<td><s:textname="format.date"><s:paramvalue="bookDate"/></s:text></td>

<td><s:propertyvalue="bookIsbn" /></td>

<td><s:propertyvalue="bookPage" /></td>

<td><s:propertyvalue="bookPrice"/></td>

<td><s:propertyvalue="bookContent"/></td>

<td><a href='<s:urlaction="delete"><s:param name="bookId"value="bookId" /></s:url>'>删除</a></td>

</tr>

</s:iterator>

<tr align="right">

<td colspan="9">

<s:property value="totalRows"/>&nbsp;

<s:property value="currentPage"/>&nbsp;

<s:propertyvalue="pager.getTotalPages()"/>&nbsp;

<a href="<s:urlvalue="list.action">

<s:paramname="currentPage" value="currentPage"/>

<s:paramname="pagerMethod" value="'first'"/>

</s:url>">首页</a>

<a href="<s:urlvalue="list.action">

<s:paramname="currentPage" value="currentPage"/>

<s:paramname="pagerMethod" value="'previous'"/>

</s:url>">上一页</a>

<a href="<s:urlvalue="list.action">

<s:paramname="currentPage" value="currentPage"/>

<s:paramname="pagerMethod" value="'next'"/>

</s:url>">下一页</a>

<a href="<s:urlvalue="list.action">

<s:paramname="currentPage" value="currentPage"/>

<s:paramname="pagerMethod" value="'last'"/>

</s:url>">尾页</a>

</td>

</tr>

</tbody>

</table>

</td>

</tr>

</table>

</body>

</html>

/WebRoot/list.jsp

(1)<s:property> :得到'value'的属性,如果value没提供,默认为堆栈顶端的元素。其相关的参数及使用如下表所示:

名称

必需

默认

类型

描述

default

String

如果属性是null则显示的default

escape

true

Booelean

是否escape HTML

value

栈顶

Object

要显示的值

id

Object/String

用来标识元素的id。在UI和表单中为HTMLid属性

(2)<s:Iterator>:用于遍历集合(java.util.Collection)或枚举值(java.util.Iterator)。其相关的参数及使用如下表所示:

名称

必需

默认

类型

描述

status

String

如果设置此参数,一个IteratorStatus的实例将会压入每个遍历的堆栈

value

Object/String

要遍历的可枚举的(iteratable)数据源,或者将放入新列表(List)的对象

id

Object/String

用来标识元素的id。在UI和表单中为HTMLid属性

(3)<s:param>:为其他标签提供参数,比如include标签和bean标签. 参数的name属性是可选的,如果提供,会调用Component的方法addParameter(String, Object),如果不提供,则外层嵌套标签必须实现UnnamedParametric接口(TextTag) value的提供有两种方式,通过value属性或者标签中间的text,不同之处我们看一下例子:

<paramname="color">blue</param><!-- (A) -->

<paramname="color" value="blue"/><!-- (B) -->

(A)参数值会以String的格式放入statck.

(B)该值会以java.lang.Object的格式放入statck.

其相关的参数及使用如下表所示:

名称

必需

默认

类型

描述

name

String

参数名

value

String

value表达式

id

Object/String

用来标识元素的id。在UI和表单中为HTMLid属性

4)、国际化是商业系统中不可或缺的一部分,所以无论您学习的是什么Web框架,它都是必须掌握的技能。其实,Struts 1.x在此部分已经做得相当不错了。它极大地简化了我们程序员在做国际化时所需的工作,例如,如果您要输出一条国际化的信息,只需在代码包中加入FILE-NAME_xx_XX.properties(其中FILE-NAME为默认资源文件的文件名),然后在struts-config.xml中指明其路径,再在页面用<bean:message>标志输出即可。

不过,所谓“没有最好,只有更好”。Struts 2.0并没有在这部分止步,而是在原有的简单易用的基础上,将其做得更灵活、更强大。

5)、list.jsp文件中:

<s:textname="format.date"><s:paramvalue="bookDate"/></s:text>,为了正确的输出出版日期的格式,采用在资源文件中定义输出的格式,并在页面上调用。format.date就是在资源文件com.sterning.books.web.actions.BooksAction.properties中定义。当然也可以别的文件,放在别的路径下,但此时需要在web.xml中注册才可以使用它。

正如读者所见,在pojo(本例为Books.java)中将日期字段设置为java.util.Date,在映射文件中(books.hbm.xml)设置为timestamp(包括日期和时间)。为了便于管理,将日期格式保存在国际化资源文件中。如:globalMessagesglobalMessages_zh_CN文件。

其内容为:

format.date={0,date,yyyy-MM-dd}

在页面显示日期时间时:<s:textname="format.date"><s:paramvalue="bookDate"/></s:text>。这样就解决了日期(时间)的显示格式化问题。

3、增加/修改页面:editBook.jsp

<%@pagepageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>

<%@taglib prefix="s" uri="/struts-tags" %>

<html>

<head>

<title>编辑图书</title>

<s:head/>

</head>

<body>

<h2>

<s:if test="null ==book">

增加图书

</s:if>

<s:else>

编辑图书

</s:else>

</h2>

<s:form name="editForm"action="save" validate="true">

<s:textfield label="书名"name="book.bookName"/>

<s:textfield label="作者" name="book.bookAuthor"/>

<s:textfield label="出版社"name="book.bookPublish"/>

<s:datetimepicker label="出版日期"name="book.bookDate"></s:datetimepicker>

<s:textfield label="ISBN"name="book.bookIsbn"/>

<s:textfield label="页数" name="book.bookPage"/>

<s:textfield label="价格()"name="book.bookPrice"/>

<s:textfield label="内容摘要"name="book.bookContent"/>

<s:if test="null ==book">

<s:hiddenname="book.bookId" value="%{bookId}"/>

</s:if>

<s:else>

<s:hiddenname="book.bookId" />

</s:else>

<s:hiddenname="queryName" />

<s:hiddenname="queryValue" />

<s:submit value="%{getText('保存')}" />

</s:form>

<p><ahref="<s:url action="list"/>">返回</a></p>

</body>

</html>

WebRoot/editBook.jsp

1)、<s:if><s:elseif><s:else> :执行基本的条件流转。其相关的参数及使用如下表所示:

名称

必需

默认

类型

描述

备注

test

Boolean

决定标志里内容是否显示的表达式

else标志没有这个参数

id

Object/String

用来标识元素的id。在UI和表单中为HTMLid属性

2)、<s:text>:支持国际化信息的标签。国际化信息必须放在一个和当前action同名的resource bundle,如果没有找到相应message,tag body将被当作默认message,如果没有tag body,messagename会被作为默认message其相关的参数及使用如下表所示:

名称

必需

默认

类型

描述

name

String

资源属性的名字

id

Object/String

用来标识元素的id。在UI和表单中为HTMLid属性

八、 配置Struts2

Struts的配置文件都会在web.xml中注册的。

a) Struts的配置文件如下:

<?xmlversion="1.0" encoding="UTF-8" ?>

<!DOCTYPEstruts PUBLIC

"-//Apache Software Foundation//DTDStruts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constantname="struts.enable.DynamicMethodInvocation" value="false"/>

<constantname="struts.devMode" value="true" />

<constantname="struts.i18n.encoding" value="GBK" />

<!-- Add packages here -->

</struts>

Src/struts.xml

b) struts_book.xml配置文件如下:

<?xmlversion="1.0" encoding="UTF-8" ?>

<!DOCTYPEstruts PUBLIC

"-//Apache SoftwareFoundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<package name="products"extends="struts-default">

<!--default-interceptor-refname="validation"/-->

<!-- Add actions here -->

<action name="list"class="bookAction" method="list">

<result>/list.jsp</result>

</action>

<action name="delete"class="bookAction" method="delete">

<resulttype="redirect">list.action?queryMap=${queryMap}</result>

</action>

<action name="*"class="com.sterning.commons.AbstractAction">

<result>/{1}.jsp</result>

</action>

<action name="edit"class="bookAction" method="load">

<result>/editBook.jsp</result>

</action>

<action name="save"class="bookAction" method="save">

<interceptor-refname="params"/>

<interceptor-refname="validation"/>

<resultname="input">/editBook.jsp</result>

<resulttype="redirect">list.action?queryMap=${queryMap}</result>

</action>

</package>

</struts>

文件中的<interceptor-refname="params"/>,使用了struts2自己的拦截器,拦截器在AOPAspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。

Struts2已经提供了丰富多样的,功能齐全的拦截器实现。大家可以到struts2-all-2.0.6.jarstruts2-core-2.0.6.jar包的struts-default.xml查看关于默认的拦截器与拦截器链的配置。

struts-default.xml中已经配置了大量的拦截器。如果您想要使用这些已有的拦截器,只需要在应用程序struts.xml文件中通过“<includefile="struts-default.xml" />”将struts-default.xml文件包含进来,并继承其中的struts-default包(package),最后在定义Action时,使用“<interceptor-refname="xx" />”引用拦截器或拦截器栈(interceptor stack)。一旦您继承了struts-default包(package),所有Action都会调用拦截器栈——defaultStack。当然,在Action配置中加入“<interceptor-ref name="xx" />”可以覆盖defaultStack

作为“框架(framework)”,可扩展性是不可或缺的,因为世上没有放之四海而皆准的东西。虽然,Struts 2为我们提供如此丰富的拦截器实现,但是这并不意味我们失去创建自定义拦截器的能力,恰恰相反,在Struts 2自定义拦截器是相当容易的一件事。所有的Struts 2的拦截器都直接或间接实现接口com.opensymphony.xwork2.interceptor.Interceptor。除此之外,大家可能更喜欢继承类com.opensymphony.xwork2.interceptor.AbstractInterceptor

九、配置Spring

1Spring的配置文件如下:

<?xmlversion="1.0" encoding="UTF-8"?>

<!DOCTYPEbeans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<!-- dataSource config -->

<bean id ="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<property name="driverClassName"value="com.mysql.jdbc.Driver" />

<property name="url"value="jdbc:mysql://localhost:3306/game" />

<property name="username"value="root" />

<property name="password"value="root"/>

</bean>

<!-- SessionFactory -->

<bean id="sessionFactory"

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<propertyname="dataSource">

<refbean="dataSource"/>

</property>

<propertyname="configLocation">

<value>classpath:com\sterning\bean\hibernate\hibernate.cfg.xml</value>

</property>

</bean>

<!-- TransactionManager 不过这里暂时没注入-->

<bean id="transactionManager"

class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<propertyname="sessionFactory">

<reflocal="sessionFactory"/>

</property>

</bean>

<!-- DAO -->

<bean id="booksDao"class="com.sterning.books.dao.hibernate.BooksMapDao">

<property name="sessionFactory">

<refbean="sessionFactory"/>

</property>

</bean>

<!-- Services -->

<bean id="booksService"class="com.sterning.books.services.BooksService">

<propertyname="booksDao">

<ref bean="booksDao"/>

</property>

</bean>

<bean id="pagerService"class="com.sterning.commons.PagerService"/>

<!-- view -->

<bean id="bookAction"class="com.sterning.books.web.actions.BooksAction"singleton="false">

<property name="booksService">

<refbean="booksService"/>

</property>

<propertyname="pagerService">

<refbean="pagerService"/>

</property>

</bean>

</beans>

WebRoot/WEB-INF/srping-content/applicationContent.xml

2Struts.properties.xml

本来此文件应该写在struts 配置一节,但主要是考虑这体现了集成spring的配置,所以放在spring的配置这里来讲。

struts.objectFactory= spring

struts.locale=zh_CN

struts.i18n.encoding= GBK

struts.objectFactoObjectFactory 实现了com.opensymphony.xwork2.ObjectFactory接口(spring)。struts.objectFactory=spring,主要是告知Struts 2运行时使用Spring来创建对象(如Action等)。当然,SpringContextLoaderListener监听器,会在web.xml文件中编写,负责SpringWeb容器交互。

struts.localeThe default locale for theStruts application默认的国际化地区信息。

struts.i18n.encoding:国际化信息内码。

十、Web.xml配置

<?xmlversion="1.0" encoding="GB2312"?>

<!DOCTYPEweb-app

PUBLIC "-//Sun Microsystems, Inc.//DTDWeb Application 2.3//EN"

"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<display-name>图书管理系统</display-name>

<context-param>

<param-name>log4jConfigLocation</param-name>

<param-value>/WEB-INF/classes/log4j.properties</param-value>

</context-param>

<!-- ContextConfigLocation -->

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/spring-context/applicationContext.xml</param-value>

</context-param>

<filter>

<filter-name>encodingFilter</filter-name>

<filter-class>com.sterning.commons.SetCharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param>

<init-param>

<param-name>forceEncoding</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<filter>

<filter-name>struts2</filter-name>

<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

<init-param>

<param-name>config</param-name>

<param-value>struts-default.xml,struts-plugin.xml,struts.xml,struts_books.xml</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<filter-mapping>

<filter-name>struts2</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<!-- Listener contextConfigLocation-->

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<!-- Listener log4jConfigLocation -->

<listener>

<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>

</listener>

<!-- The Welcome File List -->

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

</web-app>

publicvoid setQueryName(String queryName) {

this.queryName= queryName;

}

publicString getQueryValue() {

returnqueryValue;

}

publicvoid setQueryValue(String queryValue) {

this.queryValue= queryValue;

}

publicString getSearchName() {

returnsearchName;

}

publicvoid setSearchName(String searchName) {

this.searchName= searchName;

}

publicString getSearchValue() {

returnsearchValue;

}

publicvoid setSearchValue(String searchValue) {

this.searchValue= searchValue;

}

publicString getQueryMap() {

returnqueryMap;

}

publicvoid setQueryMap(String queryMap) {

this.queryMap= queryMap;

}

publicPagerService getPagerService() {

returnpagerService;

}

publicvoid setPagerService(PagerService pagerService) {

this.pagerService= pagerService;

}

}

com.sterning.books.web.actions.BookAction.java

1)、默认情况下,当请求bookAction.action发生时(这个会在后面的Spring配置文件中见到的)Struts运行时(Runtime)根据struts.xml里的Action映射集(Mapping),实例化com.sterning.books.web.actions.BookAction类,并调用其execute方法。当然,我们可以通过以下两种方法改变这种默认调用。这个功能(Feature)有点类似Struts 1.x中的LookupDispathAction

classes/sturts.xml中新建Action,并指明其调用的方法;

访问Action时,在Action名后加上“!xxx”(xxx为方法名)。

2)、细心的朋友应该可能会发现com.sterning.books.web.actions.BookAction.javaAction方法(execute)返回都是SUCCESS。这个属性变量我并没有定义,所以大家应该会猜到它在ActionSupport或其父类中定义。没错,SUCCESS在接口com.opensymphony.xwork2.Action中定义,另外同时定义的还有ERROR, INPUT, LOGIN, NONE

此外,我在配置Action时都没有为result定义名字(name),所以它们默认都为success。值得一提的是Struts 2.0中的result不仅仅是Struts 1.xforward的别名,它可以实现除forward外的很激动人心的功能,如将Action输出到FreeMaker模板、Velocity模板、JasperReports和使用XSL转换等。这些都过result里的type(类型)属性(Attribute)定义的。另外,您还可以自定义result类型。

3)、使用Struts 2.0,表单数据的输入将变得非常方便,和普通的POJO一样在Action编写GetterSetter,然后在JSPUI标志的name与其对应,在提交表单到Action时,我们就可以取得其值。

4)、Struts 2.0更厉害的是支持更高级的POJO访问,如this.getBook().getBookPrice()private Books book所引用的是一个关于书的对象类,它可以做为一个属性而出现在BookActoin.java类中。这样对我们开发多层系统尤其有用。它可以使系统结构更清晰。

5)、有朋友可能会这样问:“如果我要取得Servlet API中的一些对象,如requestresponsesession等,应该怎么做?这里的execute不像Struts 1.x的那样在参数中引入。”开发Web应用程序当然免不了跟这些对象打交道。在Strutx 2.0中可以有两种方式获得这些对象:非IoC(控制反转Inversion of Control)方式和IoC方式。

一共四个,其中pdf 三个包,源码一个包 第一章 J2EE快速入门 1.1 J2EE概述 1.1.1 J2EE的来源 1.1.2 J2EE整体框架 1.1.3 从J2EE到JavaEE 1.2 J2EE组件 1.2.1 客户端组件 1.2.2 Web组件 1.2.3 业务逻辑组件 1.3 J2EE容器 1.3.1 容器服务 1.3.2 容器类型 1.4 J2EE核心技术 1.4.1 Servlet 1.4.2 JSP(Java服务页面) 1.4.3 EJB(企业JavaBean) 1.4.4 JDBC(Java数据库连接) 1.4.5 JTA/JTS(Java事务) 1.4.6 JNDI(Java命名目录服务) 1.4.7 JavaMail(Java邮件服务) 1.4.8 RMI(远程方法调用) 1.4.9 JMS(Java消息服务) 1.4.10 JMX(Java分布式管理) 1.4.11 JACC(Java容器授权合同) 1.4.12 JCA(Java连接器体系) 1.5 小结 第二章 MVC模式介绍 2.1 MVC模式概述 2.1.1 MVC模式的设计思想 2.1.2 MVC模式的处理过程 2.2 Model规范 2.2.1 Model1规范 2.2.2 Model2规范 2.3 使用MVC的优劣 2.3.1 使用MVC模式的好处 2.3.2 使用MVC模式的不足之处 2.4 目前市场上常见的轻量级J2EE开发容器 2.5 小结 第二篇 建立使用J2EE的开发平台 第三章 建立Java的开发平台 3.1 建立Java的开发环境 3.1.1 下载JDK 3.1.2 安装JDK 3.1.3 设定Path、ClasspathJAVA_HOME 3.2 验证JDK是否安装成功 3.3 建立J2EE的开发环境 3.3.1 下载SDK 3.3.2 安装SDK 3.3.3 设定Path、ClasspathJ2EE_HOME 3.4 小结 第四章 Tomcat使用指南 4.1 Tomcat简介 4.1.1 Tomcat的目录结构 4.1.2 Tomcat的配置参数 4.2 建立Tomcat的开发环境 4.2.1 下载Tomcat 4.2.2 设定TOMCAT_HOME 4.3 验证Tomcat是否安装成功 4.4 创建发布Web应用 4.4.1 创建发布JSP应用程序 4.4.2 创建发布Servlet应用程序 4.5 小结 第五章 Eclipse使用指南 5.1 Eclipse简介 5.1.1 Eclipse的历史 5.1.2 Eclipse的运行机制 5.2 建立Eclipse的开发环境 5.2.1 下载Eclipse 5.2.2 配置Eclipse 5.3 整合EclipseTomcat 5.3.1 下载Eclipse的Tomcat插件 5.3.2 为Eclipse配置Tomcat插件 5.4 使用Eclipse建立Web开发项目 5.5 Eclipse的常用快捷键 5.5.1 有关格式化的快捷键 5.5.2 有关调试的快捷键 5.5.3 有关重构的快捷键 5.6 小结 第六章 Log4j使用指南 6.1 Log4j介绍 6.1.1 Log4j历史 6.1.2 Log4j组成 6.2 建立Log4j的开发环境 6.2.1 下载Log4j 6.2.2 配置Log4j 6.3 Log4j的使用方法 6.3.1 配置Log4j 6.3.2 配置根Logger 6.3.3 指定日志输出位置 6.3.4 指定日志输出格式 6.3.5 指定日志输出优先级 6.3.6 在代码中使用Log4j 6.4 改进Log4j 6.5 小结 第七章 Ant使用指南 7.1 Ant介绍 7.1.1 Ant简介 7.1.2 为什么要使用Ant 7.2 建立Ant的开发环境 7.2.1 下载Ant 7.2.2 配置Ant 7.3 Ant的使用方法 7.3.1 Ant能完成的工作 7.3.2 配置文件build.xml 7.3.3 编译源代码 7.3.4 创建JAR文件 7.4 小结 第八章 JUnit使用指南 8.1 JUnit介绍 8.1.1 JUnit简介 8.1.2 为什么要使用JUnit 8.2 建立JUnit的开发环境 8.2.1 下载JUnit 8.2.2 配置JUnit 8.3 JUnit的使用方法 8.3.1 继承TestCase 8.3.2 编写测试方法 8.3.3 编写断言 8.4 JUnit的新特性 8.4.1 改变测试方法的命名方式 8.4.2 不再继承TestCase 8.4.3 改变初始化销毁方式 8.4.4 改变异常处理的方式 8.5 小结 第九章 CVS使用指南 9.1 CVS介绍 9.1.1 CVS简介 9.1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值