转 Struts2+Spring2+Hibernate3 图书管理

这篇文章是从网友http://www.blogjava.net/sterning/archive/2007/09/30/149775.html转来的,
他真是一位大好人,虽然在别的网站有很多转走的这篇文章,但我也想在自己的BLOG上再转一次,
理由很简单,想自己收藏一份,感谢原创sterning

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语句为:

create database game

CREATE  TABLE  `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 ,
  
PRIMARY  KEY   (`book_id`)
) ENGINE
= InnoDB  DEFAULT  CHARSET = gbk ROW_FORMAT = COMPRESSED;

 

二、       建立公共类

1、AbstractAction

 

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

虽然,在理论上Struts2Action无须实现任何接口或者是继承任何的类,但是,在实际编程过程中,为了更加方便的实现Action,大多数情况下都会继承com.opensymphony.xwork2.ActionSupport类,并且重载(Override

package  com.sterning.commons;

import  com.opensymphony.xwork2.ActionSupport;

public  class  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分页类

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

package  com.sterning.commons;

import  java.math. * ;

public  class  Pager  {
    
private int totalRows; //总行数
    private int pageSize = 5//每页显示的行数
    private int currentPage; //当前页号
    private int totalPages; //总页数
    private int startRow; //当前页在数据库中的起始行
    
    
public Pager() {
    }

    
    
public Pager(int _totalRows) {
        totalRows 
= _totalRows;
        totalPages
=totalRows/pageSize;
        
int mod=totalRows%pageSize;
        
if(mod>0){
            totalPages
++;
        }

        currentPage 
= 1;
        startRow 
= 0;
    }

    
    
public int getStartRow() {
        
return startRow;
    }

    
public int getTotalPages() {
        
return totalPages;
    }

    
public int getCurrentPage() {
        
return currentPage;
    }

    
public int getPageSize() {
        
return pageSize;
    }

    
public void setTotalRows(int totalRows) {
        
this.totalRows = totalRows;
    }

    
public void setStartRow(int startRow) {
        
this.startRow = startRow;
    }

    
public void setTotalPages(int totalPages) {
        
this.totalPages = totalPages;
    }

    
public void setCurrentPage(int currentPage) {
        
this.currentPage = currentPage;
    }

    
public void setPageSize(int pageSize) {
        
this.pageSize = pageSize;
    }

    
public int getTotalRows() {
        
return totalRows;
    }

    
public void first() {
        currentPage 
= 1;
        startRow 
= 0;
    }

    
public void previous() {
        
if (currentPage == 1{
            
return;
        }

        currentPage
--;
        startRow 
= (currentPage - 1* pageSize;
    }

    
public void next() {
        
if (currentPage < totalPages) {
            currentPage
++;
        }

        startRow 
= (currentPage - 1* pageSize;
    }

    
public void last() {
        currentPage 
= totalPages;
        startRow 
= (currentPage - 1* pageSize;
    }

    
public void refresh(int _currentPage) {
        currentPage 
= _currentPage;
        
if (currentPage > totalPages) {
            last();
        }

    }

}

com.sterning.commons.Pager.java

同时,采用PagerService类来发布成为分页类服务PagerService,代码如下:

同时,采用PagerService类来发布成为分页类服务PagerService,代码如下:
package  com.sterning.commons;

public  class  PagerService  {
    
public Pager 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();
            }

        }

        
return pager;
    }

}

com.sterning.commons.PagerService.java

三、       建立数据持久化层

1、编写实体类Books及books.hbm.xml映射文件。

package  com.sterning.books.model;

import  java.util.Date;

public  class  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() {
        
return bookId;
    }


    
public void setBookId(String bookId) {
        
this.bookId = bookId;
    }


    
public String getBookName() {
        
return bookName;
    }


    
public void setBookName(String bookName) {
        
this.bookName = bookName;
    }


    
public String getBookAuthor() {
        
return bookAuthor;
    }


    
public void setBookAuthor(String bookAuthor) {
        
this.bookAuthor = bookAuthor;
    }


    
public String getBookContent() {
        
return bookContent;
    }


    
public void setBookContent(String bookContent) {
        
this.bookContent = bookContent;
    }


    
public Date getBookDate() {
        
return bookDate;
    }


    
public void setBookDate(Date bookDate) {
        
this.bookDate = bookDate;
    }


    
public String getBookIsbn() {
        
return bookIsbn;
    }


    
public void setBookIsbn(String bookIsbn) {
        
this.bookIsbn = bookIsbn;
    }


    
public String getBookPage() {
        
return bookPage;
    }


    
public void setBookPage(String bookPage) {
        
this.bookPage = bookPage;
    }


    
public String getBookPrice() {
        
return bookPrice;
    }


    
public void setBookPrice(String bookPrice) {
        
this.bookPrice = bookPrice;
    }


    
public String getBookPublish() {
        
return bookPublish;
    }


    
public void setBookPublish(String bookPublish) {
        
this.bookPublish = bookPublish;
    }

}

   com.sterning.books.model.Books.java

       接下来要把实体类Books的属性映射到books表,编写下面的books.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.sterning.books.model.Books"  table ="books"  >
         
< id  name ="bookId"  type ="string" >
            
< column  name ="book_id"  length ="5"  />
            
< generator  class ="assigned"  />
        
</ id >
        
< property  name ="bookName"  type ="string" >
            
< column  name ="book_name"  length ="100"  />
        
</ property >
         
< property  name ="bookAuthor"  type ="string" >
            
< column  name ="book_author"  length ="100"  />
        
</ property >
        
< property  name ="bookPublish"  type ="string" >
            
< column  name ="book_publish"  length ="100"  />
        
</ property >
         
< property  name ="bookDate"  type ="java.sql.Timestamp" >
            
< column  name ="book_date"  length ="7"  />
        
</ property >
          
< property  name ="bookIsbn"  type ="string" >
            
< column  name ="book_isbn"  length ="20"  />
        
</ property >
        
< property  name ="bookPage"  type ="string" >
            
< column  name ="book_page"  length ="11"  />
        
</ property >
        
< property  name ="bookPrice"  type ="string" >
            
< column  name ="book_price"  length ="4"  />
        
</ property >  
         
< property  name ="bookContent"  type ="string" >
            
< column  name ="book_content"  length ="100"  />
        
</ property >
     
</ class >
</ hibernate-mapping >
         com.sterning.books.model.books.hbm.xml

2、hibernate.cfg.xml配置文件如下:(注意它的位置在scr/hibernate.cfg.xml

<? xml version="1.0" encoding="ISO-8859-1" ?>
<! DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"
>
< hibernate-configuration >
< session-factory >
    
< property  name ="show_sql" > true </ property >

    
< mapping  resource ="com/sterning/books/model/books.hbm.xml" ></ mapping >
</ session-factory >
</ hibernate-configuration >
   Com.sterning.bean.hibernate.hibernate.cfg.xml

四、       建立DAO 

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

1、建立DAO的接口类:BooksDao

package  com.sterning.books.dao.iface;

import  java.util.List;

import  com.sterning.books.model.Books;

public  interface  BooksDao  {
    List getAll();
//获得所有记录
    List getBooks(int pageSize, int startRow);//获得所有记录
    int getRows();//获得总行数
    int getRows(String fieldname,String value);//获得总行数
    List queryBooks(String fieldname,String value);//根据条件查询
    List getBooks(String fieldname,String value,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

package  com.sterning.books.dao.hibernate;

import  java.sql.SQLException;
import  java.util.Iterator;
import  java.util.List;

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

import  com.sterning.books.dao.iface.BooksDao;
import  com.sterning.books.model.Books;
import  com.sterning.commons.PublicUtil;


/**
 * 
@author cwf
 *
 
*/

public  class  BooksMapDao  extends  HibernateDaoSupport  implements  BooksDao  {

    
public BooksMapDao(){}

    
/**
     * 函数说明:添加信息
     * 参数说明:对象 
     * 返回值:
     
*/

    
public void addBook(Books book) {
        
this.getHibernateTemplate().save(book);
    }


    
/**
     * 函数说明:删除信息
     * 参数说明: 对象
     * 返回值:
     
*/

    
public void deleteBook(Books book) {
        
this.getHibernateTemplate().delete(book);
    }


    
/**
     * 函数说明:获得所有的信息
     * 参数说明: 
     * 返回值:信息的集合
     
*/

    
public List getAll() {
        String sql
="FROM Books ORDER BY bookName";
        
return this.getHibernateTemplate().find(sql);
    }

    
    
/**
     * 函数说明:获得总行数
     * 参数说明: 
     * 返回值:总行数
     
*/

    
public int getRows() {
        String sql
="FROM Books ORDER BY bookName";
        List list
=this.getHibernateTemplate().find(sql);
        
return list.size();
    }

    
    
/**
     * 函数说明:获得所有的信息
     * 参数说明: 
     * 返回值:信息的集合
     
*/

    
public List getBooks(int pageSize, int startRow) throws HibernateException {
        
final int pageSize1=pageSize;
        
final int startRow1=startRow;
        
return this.getHibernateTemplate().executeFind(new HibernateCallback(){

            
public List doInHibernate(Session session) throws HibernateException, SQLException {
                
// TODO 自动生成方法存根
                Query query=session.createQuery("FROM Books ORDER BY bookName");
                query.setFirstResult(startRow1);
                query.setMaxResults(pageSize1);
                
return query.list();
            }

        }
);
    }


    
/**
     * 函数说明:获得一条的信息
     * 参数说明: ID
     * 返回值:对象
     
*/

    
public Books getBook(String bookId) {
        
return (Books)this.getHibernateTemplate().get(Books.class,bookId);
    }


    
/**
     * 函数说明:获得最大ID
     * 参数说明: 
     * 返回值:最大ID
     
*/

    
public String getMaxID() {
        String date
=PublicUtil.getStrNowDate();
        String sql
="SELECT MAX(bookId)+1 FROM Books  ";
        String noStr 
= null;
        List ll 
= (List) this.getHibernateTemplate().find(sql);
        Iterator itr 
= ll.iterator();
        
if (itr.hasNext()) {
            Object noint 
= itr.next();
            
if(noint == null){
                noStr 
= "1";                
            }
else{
                noStr 
= noint.toString();
            }

        }

        
        
if(noStr.length()==1){
            noStr
="000"+noStr;
        }
else if(noStr.length()==2){
            noStr
="00"+noStr;
        }
else if(noStr.length()==3){
            noStr
="0"+noStr;
        }
else{
            noStr
=noStr;
        }

        
return noStr;
    }


    
/**
     * 函数说明:修改信息
     * 参数说明: 对象
     * 返回值:
     
*/

    
public void updateBook(Books pd) {
        
this.getHibernateTemplate().update(pd);
    }


    
/**
     * 函数说明:查询信息
     * 参数说明: 集合
     * 返回值:
     
*/

    
public List queryBooks(String fieldname,String value) {
        System.out.println(
"value: "+value);
        String sql
="FROM Books where "+fieldname+" like '%"+value+"%'"+"ORDER BY bookName";
        
return this.getHibernateTemplate().find(sql);
    }

    
    
/**
     * 函数说明:获得总行数
     * 参数说明: 
     * 返回值:总行数
     
*/

    
public int getRows(String fieldname,String value) {
        String sql
="";
        
if(fieldname==null||fieldname.equals("")||fieldname==null||fieldname.equals(""))
            sql
="FROM Books ORDER BY bookName";
        
else    
            sql
="FROM Books where "+fieldname+" like '%"+value+"%'"+"ORDER BY bookName";
        List list
=this.getHibernateTemplate().find(sql);
        
return list.size();
    }

    
    
/**
     * 函数说明:查询信息
     * 参数说明: 集合
     * 返回值:
     
*/

    
public List getBooks(String fieldname,String value,int pageSize, int startRow) {
        
final int pageSize1=pageSize;
        
final int startRow1=startRow;
        
final String queryName=fieldname;
        
final String queryValue=value;
        String sql
="";
        
        
if(queryName==null||queryName.equals("")||queryValue==null||queryValue.equals(""))
            sql
="FROM Books ORDER BY bookName";
        
else    
            sql
="FROM Books where "+fieldname+" like '%"+value+"%'"+"ORDER BY bookName";
        
        
final String sql1=sql;
        
return this.getHibernateTemplate().executeFind(new HibernateCallback(){

            
public List doInHibernate(Session session) throws HibernateException, SQLException {
                
// TODO 自动生成方法存根
                Query query=session.createQuery(sql1);
                query.setFirstResult(startRow1);
                query.setMaxResults(pageSize1);
                
return query.list();
            }

        }
);
    }


}

  com.sterning.books.dao.hibernate.BooksMapDao.java

五、       业务逻辑层

 

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

1、创建服务接口类IBookService

1 、    创建服务接口类IBookService
package  com.sterning.books.services.iface;

import  java.util.List;

import  com.sterning.books.model.Books;

public   interface  IBooksService  {
    List getAll();
//获得所有记录
    List getBooks(int pageSize, int startRow);//获得所有记录
    int getRows();//获得总行数
    int getRows(String fieldname,String value);//获得总行数
    List queryBooks(String fieldname,String value);//根据条件查询
    List getBooks(String fieldname,String value,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:

package  com.sterning.books.services;

import  java.util.List;

import  com.sterning.books.dao.iface.BooksDao;
import  com.sterning.books.model.Books;
import  com.sterning.books.services.iface.IBooksService;

public   class  BooksService  implements  IBooksService {
    
private BooksDao booksDao;
    
    
public BooksService(){}
    
    
/**
     * 函数说明:添加信息
     * 参数说明:对象 
     * 返回值:
     
*/

    
public void addBook(Books book) {
        booksDao.addBook(book);
    }


    
/**
     * 函数说明:删除信息
     * 参数说明: 对象
     * 返回值:
     
*/

    
public void deleteBook(String bookId) {
        Books book
=booksDao.getBook(bookId);
        booksDao.deleteBook(book);
    }


    
/**
     * 函数说明:获得所有的信息
     * 参数说明: 
     * 返回值:信息的集合
     
*/

    
public List getAll() {
        
return booksDao.getAll();
    }

    
    
/**
     * 函数说明:获得总行数
     * 参数说明: 
     * 返回值:总行数
     
*/

    
public int getRows() {
        
return booksDao.getRows();
    }

    
    
/**
     * 函数说明:获得所有的信息
     * 参数说明: 
     * 返回值:信息的集合
     
*/

    
public List getBooks(int pageSize, int startRow) {
        
return booksDao.getBooks(pageSize, startRow);
    }


    
/**
     * 函数说明:获得一条的信息
     * 参数说明: ID
     * 返回值:对象
     
*/

    
public Books getBook(String bookId) {
        
return booksDao.getBook(bookId);
    }


    
/**
     * 函数说明:获得最大ID
     * 参数说明: 
     * 返回值:最大ID
     
*/

    
public String getMaxID() {
        
return booksDao.getMaxID();
    }


    
/**
     * 函数说明:修改信息
     * 参数说明: 对象
     * 返回值:
     
*/

    
public void updateBook(Books book) {
        booksDao.updateBook(book);
    }


    
/**
     * 函数说明:查询信息
     * 参数说明: 集合
     * 返回值:
     
*/

    
public List queryBooks(String fieldname,String value) {
        
return booksDao.queryBooks(fieldname, value);
    }

    
    
/**
     * 函数说明:获得总行数
     * 参数说明: 
     * 返回值:总行数
     
*/

    
public int getRows(String fieldname,String value) {
        
return booksDao.getRows(fieldname, value);
    }

    
    
/**
     * 函数说明:查询信息
     * 参数说明: 集合
     * 返回值:
     
*/

    
public List getBooks(String fieldname,String value,int pageSize, int startRow) {
        
return booksDao.getBooks(fieldname, value,pageSize,startRow);
    }


    
public BooksDao getBooksDao() {
        
return booksDao;
    }


    
public void setBooksDao(BooksDao booksDao) {
        
this.booksDao = booksDao;
    }


}

  com.sterning.books.services.BookService.java

六、        创建Action类:BookAction 

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

 
 

Struts 1.x

Stuts 2.0

接口

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

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

表单数据

表单数据封装在FormBean中

表单数据包含在Action中,通过Getter和Setter获取

1、建立BookAction

package com.sterning.books.web.actions;

import java.util.Collection;

import com.sterning.books.model.Books;
import com.sterning.books.services.iface.IBooksService;
import com.sterning.commons.AbstractAction;
import com.sterning.commons.Pager;
import com.sterning.commons.PagerService;

public   class  BooksAction  extends  AbstractAction  {
    
    
private IBooksService booksService;
    private PagerService pagerService;
    
    private Books 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());
        int totalRow=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(IBooksService booksService) {
        
this.booksService = booksService;
    }

    public Collection getAvailableItems() {
        
return availableItems;
    }

    public String getCurrentPage() {
        
return currentPage;
    }

    public void setCurrentPage(String currentPage) {
        
this.currentPage = currentPage;
    }

    public String getPagerMethod() {
        
return pagerMethod;
    }

    public void setPagerMethod(String pagerMethod) {
        
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(String queryValue) {
        
this.queryValue = queryValue;
    }
    
    public String getSearchName() {
        
return searchName;
    }

    public void setSearchName(String searchName) {
        
this.searchName = searchName;
    }

    public String getSearchValue() {
        
return searchValue;
    }

    public void setSearchValue(String searchValue) {
        
this.searchValue = searchValue;
    }
    
    public String getQueryMap() {
        
return queryMap;
    }

    public void setQueryMap(String queryMap) {
        
this.queryMap = queryMap;
    }
    
    public PagerService getPagerService() {
        
return pagerService;
    }


    public void 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.java中Action方法(execute)返回都是SUCCESS。这个属性变量我并没有定义,所以大家应该会猜到它在ActionSupport或其父类中定义。没错,SUCCESS在接口com.opensymphony.xwork2.Action中定义,另外同时定义的还有ERRORINPUTLOGINNONE

此外,我在配置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),可以帮助您快捷地获得这几个对象。

HttpServletRequest request = ServletActionContext.getRequest();

HttpServletResponse response = ServletActionContext.getResponse();

HttpSession session = 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

<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd" >
< validators >
    
<!--  Field-Validator Syntax  -->
    
< field  name ="book.bookName" >
        
< field-validator  type ="requiredstring" >
            
< message  key ="book.bookName.required" />
        
</ field-validator >
    
</ field >
    
< field  name ="book.bookAuthor" >
        
< field-validator  type ="requiredstring" >
            
< message  key ="book.bookAuthor.required" />
        
</ field-validator >
    
</ field >
    
< field  name ="book.bookPublish" >
        
< field-validator  type ="requiredstring" >
            
< message  key ="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:i18n name="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.x与Struts 2.0的标志库(Tag Library)作比较。

Struts 1.x

Struts 2.0

分类

将标志库按功能分成HTML、Tiles、Logic和Bean等几部分

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

表达式语言(expression languages)

不支持嵌入语言(EL)

OGNL、JSTL、Groovy和Velcity

 

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

 

<% @page pageEncoding = " UTF-8 "  contentType = " text/html; charset=UTF-8 "  %>
<% @ taglib prefix = " s "  uri = " /struts-tags "  %>
< html >
< head >
< meta http - equiv = " Content-Type "  content = " text/html; charset=GBK " />
< title > 图书管理系统 </ title >
</ head >
< body >
< p >< a href = " <s:url action= " list "  /> " > 进入图书管理系统 </ a ></ p >
</ body >
</ html >

 

WebRoot/index.jsp

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

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

2、列表页面:list.jsp

 

<%@page pageEncoding="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>

    
<script language="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>

<table align="center">
<tr align="center">
    
<td>
        
<select name="searchName">
            
<option value="bookName">书名</option>
            
<option value="bookAuthor">作者</option>
            
<option value="bookPublish">出版社</option>
            
<option value="bookDate">出版日期</option>
            
<option value="bookIsbn">ISNB</option>
            
<option value="bookPage">页数</option>
        
</select>
        
<input type="text" name="searchValue" value="" size="10"/>
        
<input type="button" value="查询" onClick="doSearch();">
    
</td>
</tr>
<tr align="center">    
    
<td>
        
<a href="<s:url action="list" includeParams="none"/>">全部</a>
        
<a href='<s:url action="edit" ></s:url>'>增加</a>
    
</td>
</tr>
<tr>
<td>
<table cellspacing="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:iterator value="availableItems">
        
<tr class="trs">
            
<td>
            
<a href='<s:url action="edit" ><s:param name="bookId" value="bookId" /></s:url>'>
            
<s:property value="bookName"/>
            
</a>
            
</td>
            
<td><s:property value="bookAuthor"/></td>
            
<td><s:property value="bookPublish"/></td>
            
<td><s:text name="format.date"><s:param value="bookDate"/></s:text></td>     
            
<td><s:property value="bookIsbn" /></td>
            
<td><s:property value="bookPage" /></td>
            
<td><s:property value="bookPrice"/></td>
            
<td><s:property value="bookContent"/></td>
            
            
<td><a href='<s:url action="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:property value="pager.getTotalPages()"/>&nbsp;
            
<a href="<s:url value="list.action">
                <s:param name=
"currentPage" value="currentPage"/>
                <s:param name=
"pagerMethod" value="'first'"/>
                
            </s:url>
">首页</a>
            
<a href="<s:url value="list.action">
                <s:param name=
"currentPage" value="currentPage"/>
                <s:param name=
"pagerMethod" value="'previous'"/>
            </s:url>
">上一页</a>
            
<a href="<s:url value="list.action">
                <s:param name=
"currentPage" value="currentPage"/>
                <s:param name=
"pagerMethod" value="'next'"/>
            </s:url>
">下一页</a>
            
<a href="<s:url value="list.action">
                <s:param name=
"currentPage" value="currentPage"/>
                <s:param name=
"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和表单中为HTML的id属性

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

名称

必需

默认

类型

描述

status

String

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

value

Object/String

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

id

Object/String

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

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

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

<param name="color" value="blue"/><!-- (B) -->
(A)参数值会以String的格式放入statck. 
(B)该值会以java.lang.Object的格式放入statck.

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

名称

必需

默认

类型

描述

name

String

参数名

value

String

value表达式

id

Object/String

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

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

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

(5)、list.jsp文件中:

<s:text name="format.date"><s:param value="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:text name="format.date"><s:param value="bookDate"/></s:text>。这样就解决了日期(时间)的显示格式化问题。

 

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

 

 

<%@page pageEncoding="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:hidden name="book.bookId" value="%{bookId}"/>
         
</s:if>         
         
<s:else>
             
<s:hidden name="book.bookId" />
         
</s:else>
         
<s:hidden name="queryName" />
         
<s:hidden name="queryValue" />
         
<s:submit value="%{getText('保存')}" />
    
</s:form>

<p><a href="<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和表单中为HTML的id属性

 

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

名称

必需

默认

类型

描述

name

 

String

资源属性的名字

id

 

Object/String

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

八、       配置Struts2

 

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

a)        Struts的配置文件如下:

 

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

<struts>

    
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
    
<constant name="struts.devMode" value="true" />
    
<constant name="struts.i18n.encoding" value="GBK" />   

    
<!-- Add packages here -->

</struts>

 

Src/struts.xml

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

 

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

<struts>

    
<package name="products" extends="struts-default">
        
<!--default-interceptor-ref name="validation"/-->
         
<!-- Add actions here -->
        
<action name="list" class="bookAction" method="list">            
            
<result>/list.jsp</result>
        
</action>

    
<action name="delete" class="bookAction" method="delete">            
            
<result type="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-ref name="params"/>
           
<interceptor-ref name="validation"/>
            
<result name="input">/editBook.jsp</result>
            
<result type="redirect">list.action?queryMap=${queryMap}</result>
              
        
</action>
    
</package>
</struts>

 

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

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

在struts-default.xml中已经配置了大量的拦截器。如果您想要使用这些已有的拦截器,只需要在应用程序struts.xml文件中通过“<include file="struts-default.xml" />”将struts-default.xml文件包含进来,并继承其中的struts-default包(package),最后在定义Action时,使用“<interceptor-ref name="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

 

1、Spring的配置文件如下:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans 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">

        
<property name="dataSource">
            
<ref bean="dataSource"/>
        
</property>
        
<property name="configLocation">
            
<value>classpath:com\sterning\bean\hibernate\hibernate.cfg.xml</value>
        
</property>        
    
</bean>
    
    
<!-- TransactionManager  不过这里暂时没注入-->
    
<bean id="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager">
        
<property name="sessionFactory">
            
<ref local="sessionFactory"/>
        
</property>
    
</bean>
    
    
<!-- DAO -->
    
<bean id="booksDao" class="com.sterning.books.dao.hibernate.BooksMapDao">
        
<property name="sessionFactory">
            
<ref bean="sessionFactory"/>
        
</property>
    
</bean>
    
    
<!-- Services -->
    
<bean id="booksService" class="com.sterning.books.services.BooksService">
        
<property name="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">
            
<ref bean="booksService"/>
        
</property>
        
<property name="pagerService">
            
<ref bean="pagerService"/>
        
</property>
    
</bean>  
    
</beans>


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

2、Struts.properties.xml

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

 

struts.objectFactory = spring  
struts.locale=zh_CN
struts.i18n.encoding = GBK

 

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

struts.locale:The default locale for the Struts application。 默认的国际化地区信息。

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

十、       Web.xml配置

 


<?xml version="1.0" encoding="GB2312"?>
<!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>
    
<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>

 

在Struts 2中,配置有少许改变,最明显的是分发器(dispatcher)已由Servlet转为Servlet Filter, 其配置和Servlet一样简单。和Servlet配置一样,Filter配置中定义了Filter的名称(作为引用)和类名。Filter Mapping通过URI和名称匹配来调用相应的Filter。默认情况下,扩展名为“.action”,这是在default.properties文件(在Struts 2 JAR文件里)的“struts.action.extension”属性定义的。


十一、       运行结果

1、主页面


 

2、图书列表页面


 

3、增加页面


 

4、修改页面



 

十二、       总结

从上面的struts2.0.6+spring2.0.6+hibernate3.1的示例代码可以看出,从struts1过渡到Struts2的时候,发现非常方便,标签变得更加的简洁,从而使代码量简缩了,同时整个体系沿用了webwork的精华和struts1的精髓,Struts2的Action不再依耐于Servlet容器,从而可以进行单独的测试。另外对于表达式语言方面,不仅支持原有的JSTL,还支持OGNL(全称是Object Graph Notation Language)。在校验方面,没有再直接使用Common-validator,用的是xwork框架校验。其实说这些,主要把webwork2的特性简单描述一下而已,话说回来,发现struts2跟ajax的某些框架结合得不好,比如流行的dwr,连最简单的页面theme都用不了ajax,这个问题主要出在模版上面,具体位置在Struts2-core-2.0.6.jar包的template/ajax里面的form-close.ftl等几个文件的代码有bug,比如dojo.widget.html.Tooltip问题,是没有这个属性的,应为dojo.widget.Tooltip,这个已经在官方的bug跟踪系统提出了,官方说会在2.1版本时解决(其实在Struts2.0.8中已经有解决的痕迹了)。当然,还有其他一系列的bug,不过大体沿用了webwork2的东西,拿官方说: struts2 = webwork2 + struts 。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一共四个,其中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、Classpath和JAVA_HOME 3.2 验证JDK是否安装成功 3.3 建立J2EE的开发环境 3.3.1 下载SDK 3.3.2 安装SDK 3.3.3 设定Path、Classpath和J2EE_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 整合Eclipse和Tomcat 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、付费专栏及课程。

余额充值