理想蝸牛@*

          ***用心生活***

             :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            2 隨筆 :: 0 文章 :: 1 評論 :: 0 Trackbacks

          Struts2+Spring+Hibernate整合
             


            本文主要目的是通過整合Struts2,Spring,Hibernate,開發出一個簡易的圖書管理系統,該系統具有增刪改查的基本功能。


          首先準備所需的JAR包,如下:

          把jar包拷貝到WEB-INF/lib下,然后在工程中引用這些包。
          注意該處使用的Struts版本為2.0.11.2,Spring版本為2.5.5,Hibernate版本為3.3.1


          修改web.xml:

          <?xml version="1.0" encoding="UTF-8"?>
          <web-app version="2.5"
           xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
           http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
           
           <!-- spring的applicationContext載入 -->
           <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/*.xml</param-value>
           </context-param>
           <!-- 定義log4j配置文件所在位置 -->
           <context-param>
            <param-name>log4jConfigLocation</param-name>
            <param-value>/WEB-INF/classes/log4j.properties</param-value>
           </context-param>
           
           <filter>
            <filter-name>struts2</filter-name>
            <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
           </filter>
           <!-- 這里用的是spring自帶的編碼過濾器,不用自己寫了,其中主要代碼
             是request.setCharacterEncoding(encoding)和
             response.setCharacterEncoding(encoding),對請求和響應設置編碼。
             有兩個參數:encoding和forceEncoding,其中forceEncoding默認是false,
             (此種情況不能改變response的編碼方式)如果設置成true則不管請求是否已有編碼
             都強制轉換成encoding指定的編碼,同時在響應可設置編碼的前提下設置響應編碼。 -->
           <filter>
            <filter-name>encodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</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-mapping>
            <filter-name>struts2</filter-name>
            <url-pattern>/*</url-pattern>
           </filter-mapping>
           <filter-mapping>
            <filter-name>encodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
           </filter-mapping> 
            
           <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
           </listener> 
           <!-- 
            web應用關閉時IntrospectorCleanupListener類負責對javabean
            內省緩存進行清除;該類實現接口ServletContextListener,
            對緩存在context中的javabean類進行清除操作的。
            -->
           <listener>
            <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
           </listener>
           <!-- Listener log4jConfigLocation -->
             <listener>
               <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
             </listener>
              
             <!-- 定義session的超時時間,單位為分鐘 -->
           <session-config>
            <session-timeout>10</session-timeout>
           </session-config>
           
            <welcome-file-list>
              <welcome-file>index.jsp</welcome-file>
            </welcome-file-list>
          </web-app>

          幾點需要注意的地方:1)對于spring的配置文件和log4j日志配置文件的讀取我們用的是spring的ContextLoaderListener和Log4jConfigListener這兩個個監聽器。2)對瀏覽器發送的請求,通過配置的Struts2的過濾器(FilterDispatcher)可以對不同的url進行過濾,此處我們配置處理該web應用的所有請求。3)配置了一個spring自帶的編碼過濾器,用來處理請求和響應的編碼,本應用配置對所有請求和響應都采用該編碼過濾器,這里我們采用的utf-8。

          在WEB-INF/spring/目錄下新建applicationContext.xml,內容如下:

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
          <!-- 該處的default-autowire對所有bean提供一種默認的自動裝配方式,如果bean需要不同的方式,
          可以在bean中配置配置autowire屬性。自動裝配方式有以下幾種:
          1) no 不使用自動裝配。必須通過ref元素指定依賴,這是默認設置。
          2) byName 根據屬性名自動裝配。此選項將檢查容器并根據名字查找與屬性完全一致的bean,并將其與屬性自動裝配。
          3) byType 如果容器中存在一個與指定屬性類型相同的bean,那么將與該屬性自動裝配。
          4) constructor 與byType的方式類似,不同之處在于它應用于構造器參數。
          5) autodetect 通過bean類的自省機制(introspection)來決定是使用constructor還是byType方式進行自動裝配。 -->
          <beans>
           <!-- 如果實體定義用的是xml配置文件,則sessionFactory的class
            應為"org.springframework.orm.hibernate3.LocalSessionFactoryBean" -->
           <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="configLocation">
             <value>classpath:hibernate.cfg.xml</value>
            </property>
             <!--   配置多個hibernate.cfg.xml
                  <property name="configLocations">
                     <list>
                       <value>classpath:hibernate_admin1.cfg.xml</value>
                       <value>classpath:hibernate_admin2.cfg.xml</value>
                      </list>
                  </property>
                  -->
           </bean>
           
           <!-- 配置事務管理 -->
           <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"></property>
           </bean>
           
           <!-- 這里的abstract屬性說明該bean是抽象的,不能實例化,只能用來被繼承,在這里他被BookService繼承 -->
           <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
            <property name="transactionManager" ref="transactionManager"></property>
            <property name="transactionAttributes">
             <props>
              <!-- PROPAGATION_REQUIRED代表必須在事務中執行,-Exception表示
              當有Exception拋出時事務回滾 -->
              <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                          <prop key="persist*">PROPAGATION_REQUIRED,-Exception</prop>
                          <prop key="remove*">PROPAGATION_REQUIRED,-Exception</prop>
             </props>
            </property>
           </bean>
           <bean id="BookService" parent="baseTransactionProxy">
            <property name="target">
             <bean class="com.css.ravollen.sshtest.service.impl.BookServiceImpl">
              <property name="dao">
               <bean class="com.css.ravollen.sshtest.dao.impl.BookDAOImpl">
                 <property name="sessionFactory" ref="sessionFactory"/>    
                </bean>
              </property>
             </bean>
            </property>
           </bean>
           <bean id="BookAction" class="com.css.ravollen.sshtest.action.BookAction">
            <property name="bookService" ref="BookService"></property>
           </bean>
          </beans>

          這里幾點要注意的地方:1)sessionFactory的真正定義是在hibernate.cfg.xml里面,sessionFactory Bean通過configLocation屬性提供的路徑去找,因為hibernate.cfg.xml是在/WEB-INF/classes/下,所以可以通過classpath:hibernate.cfg.xml定位。2)該處配置的sessionFactory是基于Annotation對實體進行管理的。3)對于持久化操作可以配置事務管理機制保證數據的安全和合法,本實例對于目標類(BookServiceImpl)中的以find,persist,remove開頭的方法都采用事務機制。

          接下來看WEB-INF/classes/下的hibernate.cfg.xml

          <?xml version="1.0" encoding="UTF-8"?>
          <!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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.username">ravollen</property>
            <property name="hibernate.connection.password">726321</property>
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/book?useUnicode=true&amp;characterEncoding=UTF-8</property>
            <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
            <property name="hibernate.show_sql">true</property>
              <!-- 
                該屬性默認為none,有以下幾種:
                1)validate 加載hibernate時,驗證創建數據庫表結構
                2) create 每次加載hibernate,重新創建數據庫表結構,這就是導致數據庫表數據丟失的原因。
                3) create-drop 加載hibernate時創建,退出是刪除表結構
                4) update 加載hibernate自動更新數據庫結構
             -->
            <!--
            <property name="hibernate.hbm2ddl.auto">create</property>
              -->
              <!--
              這里由于我們采用的是annotation方式,所以直接指向實體對應的類即可,如果是采用實體配置文件則寫成
              <mapping resource="com/css/ravollen/sshtest/entity/Book.hbm.xml"></mapping>
               -->
            <mapping class="com.css.ravollen.sshtest.entity.Book"></mapping>
           </session-factory>
          </hibernate-configuration>

          該文件主要配置了數據庫底層連接的一些信息。需要注意的地方有:1)數據庫url需加上useUnicode=true&amp;characterEncoding=UTF-8,可以解決中文亂碼問題。(其中&amp;是&的轉義符)
          2)屬性"hibernate.hbm2ddl.auto"可以用來建數據庫,省事不少,但一定要在第一次運行后注銷掉該屬性否則每次啟動該應用都會把建好的數據庫刪掉造成數據丟失。3)由于我們采用的annotation方式(從jdk5開始)配置實體,所以mapping屬性通過class子屬性找到對應的實體類。

          下面是WEB-INF/classes/下的struts.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>
           <!-- extends說明該配置文件繼承自struts-default.xml -->
           <package name="test" extends="struts-default">
            <global-results>
             <result name="listAllBooks">/WEB-INF/ui/booklist.jsp</result>
             <result name="bookInfo">/WEB-INF/ui/editBook.jsp</result>
            </global-results>
            <action name="LoadBookById" class="BookAction" method="findBookById"></action>
            <action name="LoadBookByParam" class="BookAction" method="findBookByParam"></action>
            <action name="LoadAllBooks" class="BookAction" method="findAllBooks"></action>
            <action name="editBook" class="BookAction" method="loadBook"></action>
            <action name="saveBook" class="BookAction" method="saveBook">
              <!--
            都是struts2的默認攔截器
            param攔截器 將Request請求的參數設置到相應Action對象的屬性中
            validation攔截器  實現使用xml配置文件({Action}-validation.xml)對Action屬性值進行驗證
             -->
             <interceptor-ref name="params" />
             <interceptor-ref name="validation" />
             <result name="input">/editBook.jsp</result>
             <result name="success" type="redirect">LoadAllBooks.action</result>
            </action>
            <action name="removeBook" class="BookAction" method="removeBook">
            </action>
           </package>
          </struts>

          注意這幾項:1)package的extends屬性說明該配置文件是繼承自strut-default.xml,該配置文件在struts2-core-2.0.11.2.jar包內。2)對于大量重復的result,我們可以配置成全局的result,可以減少文件冗余。3)在"保存書"這個活動中,加入了struts2的校驗框架,在該action中加入兩個攔截器"params"和“validation"就可以,此外在該Action的同一級目錄下新建一個校驗配置文件即可,命名規則:活動名+"-"+方法名+"-"+"validation.xml,如果該校驗文件引用了消息文件,則還要在同一級目錄下建一個.properties的消息文件文件,前綴與活動名一樣。(需要對消息文件進行ascii碼轉換,命令為 native2ascii "源文件" "新文件")


          在src目錄的dao包(可自定義,只要與配置文件的路徑相同就行)下定義BookDAO接口和實現該接口的BookDAOImpl類,dao數據訪問層主要通過Hibernate進行數據的增刪改查的操作。如下:

          接口:
          package com.css.ravollen.sshtest.dao;
          import java.util.List;
          import com.css.ravollen.sshtest.entity.Book;

          public interface BookDAO {
           public Book findBookById(Long id);
           public List<Book> findBookByParam(String type,String value);
           public List<Book> findAllBooks();
           public void persistBook(Book book);
           public void removeBook(Book book);
           public void removeById(Long id);
          }

          實現類:

          package com.css.ravollen.sshtest.dao.impl;

          import java.util.List;
          import org.hibernate.Session;
          import org.springframework.orm.hibernate3.HibernateCallback;
          import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
          import com.css.ravollen.sshtest.dao.BookDAO;
          import com.css.ravollen.sshtest.entity.Book;

          public class BookDAOImpl extends HibernateDaoSupport implements BookDAO {
           public BookDAOImpl() {
            super();
           }
           
          /**
            * 通過自定義類型查找,比如可通過書名,作者查找
            */

           public List<Book> findBookByParam(final String type,final String value) {
            // TODO Auto-generated method stub
            String sql="";
            sql="FROM Book where "+type+" like '%"+value+"%'"+"ORDER BY bookName";
            return getHibernateTemplate().find(sql);
           }

           public List<Book> findAllBooks() {
            // TODO Auto-generated method stub
            return getHibernateTemplate().loadAll(Book.class);
           }

           public Book findBookById(Long id) {
            // TODO Auto-generated method stub
            return (Book)getHibernateTemplate().get(Book.class, id);
           }

           public void persistBook(Book book) {
            // TODO Auto-generated method stub
            getHibernateTemplate().saveOrUpdate(book);
           }

           public void removeBook(Book book) {
            // TODO Auto-generated method stub
            getHibernateTemplate().delete(book);
           }

           public void removeById(final Long id) {
            // TODO Auto-generated method stub
            getHibernateTemplate().execute(new HibernateCallback() {
             public Object doInHibernate(Session session) {
              session.createQuery("delete from Book o where o.bookId="+id+"").executeUpdate();
              return 1;
             }
            });
           }
          }



          再看看業務層的services包,該包有BookService接口和實現該接口的BookServiceImpl類,這個包用來銜接數據訪問層和表現層,一定程度上起到解耦作用。代碼如下:

          接口:

          package com.css.ravollen.sshtest.service;
          import java.util.List;
          import com.css.ravollen.sshtest.entity.Book;

          public interface BookService {
           public Book findBookById(Long id) throws Exception;
           
           public List<Book> findBookByParam(String type,String value) throws Exception;

           public List<Book> findAllBooks() throws Exception;

           public void persistBook(Book book) throws Exception;

           public void removeBook(Book book) throws Exception;

           public void removeBookById(Long id) throws Exception;
          }

          實現類:

          package com.css.ravollen.sshtest.service.impl;
          import java.util.List;
          import org.springframework.context.ApplicationContext;
          import com.css.ravollen.sshtest.dao.BookDAO;
          import com.css.ravollen.sshtest.entity.Book;
          import com.css.ravollen.sshtest.service.BookService;

          public class BookServiceImpl implements BookService {
           private  BookDAO dao;
           private static final String SERVICE_BEAN_ID = "BookService";
           public BookServiceImpl() {
            super();
           }
           public static BookService getInstance(ApplicationContext context) {
            return (BookService)context.getBean(SERVICE_BEAN_ID);
           }
           public List<Book> findAllBooks() throws Exception {
            try {
             return getDao().findAllBooks();
            }catch(RuntimeException e) {
             throw new Exception("findAllBooks failed :"+e.getMessage());
            }
           }

           public Book findBookById(Long id) throws Exception {
            try {
             return getDao().findBookById(id);
            }catch(RuntimeException e) {
             throw new Exception("findBookById failed with the id " + id + ": " + e.getMessage());
            }
           }
           public List<Book> findBookByParam(String type,String value) throws Exception {
            try {
             return getDao().findBookByParam(type,value);
            }catch(RuntimeException e) {
             throw new Exception("findBookByParam failed with type is :"+type+" and queryContent is:"+value+" :"+e.getMessage());
            }
           }

           public void persistBook(Book book) throws Exception {
            try {
             getDao().persistBook(book);
            }catch(RuntimeException e) {
             throw new Exception("persistBook failed: " + e.getMessage());
            }
           }

           public void removeBook(Book book) throws Exception {
            try {
             getDao().removeBook(book);
            }catch(RuntimeException e) {
             throw new Exception("removeBook failed: " + e.getMessage());
            }
           }

           public void removeBookById(Long id) throws Exception {
            try {
                     getDao().removeById(id);
                }catch(RuntimeException e) {
                        throw new Exception("removeBookById failed: " + e.getMessage());
                }
           }

           public BookDAO getDao() {
            return dao;
           }

           public void setDao(BookDAO dao) {
            this.dao = dao;
           }
          }

          注意:1)BookServiceImpl實例通過ApplicationContext從Spring的上下文中得到。2)BookDAO通過Spring的IOC注入到里面。

          接下來寫BookAction,主要負責處理前臺傳來的請求,繼承自ActionSupport工具類,因而能提供數據校驗功能。

          package com.css.ravollen.sshtest.action;
          import java.util.List;
          import org.apache.log4j.Logger;
          import com.css.ravollen.sshtest.entity.Book;
          import com.css.ravollen.sshtest.service.BookService;
          import com.opensymphony.xwork2.ActionSupport;

          /**
           * ActionSupport工具類比Action接口多了一個validate()方法,可提供數據校驗,
           * 實際上在本例中我們校驗采用的是Struts的校驗框架,而不是通過改寫ActionSupport
           * 的validate()方法去校驗數據
           * @author Administrator
           */
          public class BookAction extends ActionSupport {

           private static Logger logger = Logger.getLogger(BookAction.class);
           private BookService bookService;
           private Book book;
           private List books;
           private String searchType,searchContent;
           private Long bookId;
           private int addBookFlag;

           public Long getBookId() {
            return bookId;
           }

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

           public String getSearchType() {
            return searchType;
           }

           public void setSearchType(String searchType) {
            this.searchType = searchType;
           }

           public String getSearchContent() {
            return searchContent;
           }

           public void setSearchContent(String searchContent) {
            this.searchContent = searchContent;
           }

           public String findBookById(Long id) {
            try {
             this.book = getBookService().findBookById(id);
             return "bookInfo";
            }catch(Exception e) {
             logger.error("BookAction中findBookById()出錯!");
             return ERROR;
            }
           }
           
           public String findBookByParam() {
            try {
             this.books = getBookService().findBookByParam(getSearchType(),getSearchContent());
             return "listAllBooks";
            }catch(Exception e) {
             logger.error("BookAction中findBookByParam()出錯!");
             return ERROR;
            }
           }
           
           public String findAllBooks() {
            try {
             this.books = getBookService().findAllBooks();
             return "listAllBooks";
            }catch(Exception e) {
             logger.error("BookAction中findAllBooks()出錯!");
             return ERROR;
            }
           }
           
           /**
            *
            * @return result對應的名字
            * @throws Exception
            */
           public String loadBook() throws Exception {
            if(getAddBookFlag()==1) {
             addBookFlag = 0;
             book = null;
            }
            else if(bookId!=null) {
             book = getBookService().findBookById(bookId);
            }  
               return "bookInfo";
           }
           public String saveBook() throws Exception {
             getBookService().persistBook(getBook());
            return SUCCESS;
           }
           public String removeBook() throws Exception {
            if(null!=bookId) {
             getBookService().removeBookById(bookId);
            }
            return "listAllBooks";
           }
           
           public Book getBook() {
            return book;
           }
           public void setBook(Book book) {
            this.book = book;
           }
           public List getBooks() {
            return books;
           }
           public void setBooks(List books) {
            this.books = books;
           }
           public BookService getBookService() {
            return bookService;
           }
           public void setBookService(BookService bookService) {
            this.bookService = bookService;
           }

           public int getAddBookFlag() {
            return addBookFlag;
           }

           public void setAddBookFlag(int addBookFlag) {
            this.addBookFlag = addBookFlag;
           }
          }

          說明一下:1)Struts的攔截器解析前臺參數然后將值賦給Action里的對應屬性,使得我們不用跟請求和響應直接打交道。2)對于增加書和編輯書我們用同一個方法處理,通過isAddBook來標識, addBookFlag==1是增加,==0是編輯。(不知為何用布爾型來標識前臺無法返回正確的布爾值,所以在這里用的是整形

          校驗框架使用的配置文件命名為BookAction-saveBook-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>
          </validators>

          這里用到了消息資源,因此在同級目錄下還要有一個名為BookAction.properties的資源文件。

          下面貼出booklist.jsp,基于Struts2強大的標簽:

          <%@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;
                  }
                 
                  table tbody tr td {
                      border: 1px solid black;
                      padding: 3px;
                  }
              </style>
              <script language="JavaScript">  
               function doSearch(){
             if(document.all.queryContent.value=="")
             { 
              alert("請輸入查詢關鍵字!");
             }else{
              window.location.href="LoadBookByParam.action?searchType="+document.all.queryType.value+"&&searchContent="+document.all.queryContent.value;
              }
            }
           </script>
          <body>
          <table cellspacing="0" align="center">
           <thead>
           <tr>
            <th><a href='<s:url action="editBook"><s:param name="addBookFlag" value="1" /></s:url>'>增加</a></th>
            <th></th><th></th>
           </tr>
           <tr align="center">
            <th>
             <select name="queryType">
              <option value="bookId">Id</option>
              <option value="bookName">書名</option>
             </select>
            </th>
            <th><input type="text" name="queryContent" value="" size="10"/></th>
            <th><input type="button" value="查詢" onClick="doSearch();"></th>
           </tr>
              <tr>
                  <th>書名</th>
                  <th>描述</th>
                  <th>刪除</th>
              </tr>
              </thead>
              <tbody>
              <s:iterator value="books">
                  <tr class="trs">
                      <td>
                      <a href='<s:url action="editBook" ><s:param name="bookId" value="bookId" /></s:url>'>
                      <s:property value="bookName"/>
                      </a>
                      </td>
                      <td><s:property value="description" /></td>
                      <td><a href='<s:url action="removeBook"><s:param name="bookId" value="bookId" /></s:url>'>刪除</a></td>
                  </tr>
              </s:iterator>
               </tbody>
          </table>
          </body>
          </html>


          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="saveBook" validate="true"> 
             <s:textfield label="書名" name="book.bookName"/>
             <s:textfield label="作者" name="book.author"/>
             <s:textfield label="出版社" name="book.publisher"/>
                <s:datetimepicker label="出版日期" name="book.pubDate"></s:datetimepicker>
             <s:textfield label="內容摘要" name="book.description"/>
             <s:if test="null == book">
              <s:hidden name="book.bookId" value="%{bookId}"/>
             </s:if>   
                <s:else>
              <s:hidden name="book.bookId" />
             </s:else>
             <s:submit value="%{getText('保存')}" />
           </s:form>
          <p><a href="<s:url action="LoadAllBooks"/>">返回</a></p>
          </body>
          </html>



          至此我們完成了一個完整的Web Project,把它發布到tomcat下看看吧!(祝你成功)

          2008年10月29日17:45:21

          posted on 2008-10-29 17:44 理想蝸牛 閱讀(2662) 評論(1)  編輯  收藏

          評論

          # re: struts2+spring+hibernate整合 2009-03-18 18:36 xxhh
          com.css.ravollen.sshtest.entity.Book;


          在那里在?????  回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 聊城市| 焉耆| 仁布县| 澄城县| 云阳县| 双鸭山市| 镇赉县| 沙坪坝区| 石景山区| 夹江县| 神农架林区| 凌海市| 南平市| 泗阳县| 竹溪县| 高青县| 谷城县| 临颍县| 吉水县| 万载县| 河间市| 华亭县| 惠来县| 宁远县| 平邑县| 泗阳县| 白银市| 青铜峡市| 鄂托克前旗| 肃南| 松滋市| 顺义区| 孟州市| 石棉县| 岗巴县| 合肥市| 安徽省| 孝感市| 大田县| 来凤县| 扶沟县|