隨筆-34  評論-1965  文章-0  trackbacks-0

          CRUD是Create(創建)、Read(讀取)、Update(更新)和Delete(刪除)的縮寫,它是普通應用程序的縮影。如果您掌握了某框架的CRUD編寫,那么意味可以使用該框架創建普通應用程序了,所以大家使用新框架開發OLTP(Online Transaction Processing)應用程序時,首先會研究一下如何編寫CRUD。這類似于大家在學習新編程語言時喜歡編寫“Hello World”。

          本文旨在講述Struts 2上的CRUD開發,所以為了例子的簡單易懂,我不會花時間在數據庫的操作上。取而代之的是一個模擬數據庫的哈希表(Hash Map)。

          具體實現

          首先,讓我們看看的“冒牌”的DAO(Data Access Object,數據訪問對象),代碼如下:

          package tutorial.dao;

          import java.util.Collection;
          import java.util.concurrent.ConcurrentHashMap;
          import java.util.concurrent.ConcurrentMap;

          import tutorial.model.Book;

          public class BookDao {
             
          private static final BookDao instance;
             
          private static final ConcurrentMap<String, Book> data;
             
             
          static {
                 instance
          = new BookDao();
                 data
          = new ConcurrentHashMap<String, Book>();
                 data.put(
          "978-0735619678", new Book("978-0735619678", "Code Complete, Second Edition", 32.99));
                 data.put(
          "978-0596007867", new Book("978-0596007867", "The Art of Project Management", 35.96));
                 data.put(
          "978-0201633610", new Book("978-0201633610", "Design Patterns: Elements of Reusable Object-Oriented Software", 43.19));
                 data.put(
          "978-0596527341", new Book("978-0596527341", "Information Architecture for the World Wide Web: Designing Large-Scale Web Sites", 25.19));
                 data.put(
          "978-0735605350", new Book("978-0735605350", "Software Estimation: Demystifying the Black Art", 25.19));
             }

             
             
          private BookDao() {}
             
             
          public static BookDao getInstance() {
                 
          return instance;
             }

             
             
          public Collection<Book> getBooks() {
                 
          return data.values();
             }

             
             
          public Book getBook(String isbn) {
                 
          return data.get(isbn);
             }

             
             
          public void storeBook(Book book) {
                 data.put(book.getIsbn(), book);
             }

                 
             
          public void removeBook(String isbn) {
                 data.remove(isbn);
             }

             
             
          public void removeBooks(String[] isbns) {
                 
          for(String isbn : isbns) {
                     data.remove(isbn);
                 }

             }

          }
          清單1 src/tutorial/dao/BookDao.java

          以上代碼相信不用解釋大家也清楚,我使用ConcurrentMap數據結構存儲Book對象,這主要是為了方便檢索和保存Book對象;另外,我還將data變量設為靜態唯一來模擬應用程序的數據庫。

          接下來是的數據模型Book類,代碼如下:

          package tutorial.model;

          public class Book {
             
          private String isbn;
             
          private String title;
             
          private double price;
             
             
          public Book() {        
             }

             
             
          public Book(String isbn, String title, double price) {
                 
          this.isbn = isbn;
                 
          this.title = title;
                 
          this.price = price;
             }


             
          public String getIsbn() {
                 
          return isbn;
             }


             
          public void setIsbn(String isbn) {
                 
          this.isbn = isbn;
             }


             
          public double getPrice() {
                 
          return price;
             }


             
          public void setPrice(double price) {
                 
          this.price = price;
             }


             
          public String getTitle() {
                 
          return title;
             }


             
          public void setTitle(String title) {
                 
          this.title = title;
             }
             
          }
          清單2 src/tutorial/model/Book.java

          Book類有三個屬性isbn,、title和price分別代表書籍的編號、名稱和價格,其中編號用于唯一標識書籍(相當數據庫中的主鍵)。

          然后,我們再來看看Action類的代碼:

          package tutorial.action;

          import java.util.Collection;

          import tutorial.dao.BookDao;
          import tutorial.model.Book;

          import com.opensymphony.xwork2.ActionSupport;

          public class BookAction extends ActionSupport {
             
          private static final long serialVersionUID = 872316812305356L;
             
             
          private String isbn;
             
          private String[] isbns;
             
          private Book book;
             
          private Collection<Book> books;
             
          private BookDao dao =  BookDao.getInstance();
                 
             
          public Book getBook() {
                 
          return book;
             }


             
          public void setBook(Book book) {
                 
          this.book = book;
             }


             
          public String getIsbn() {
                 
          return isbn;
             }


             
          public void setIsbn(String isbn) {
                 
          this.isbn = isbn;
             }


             
          public String[] getIsbns() {
                 
          return isbns;
             }


             
          public void setIsbns(String[] isbns) {
                 
          this.isbns = isbns;
             }

                 
             
          public Collection<Book> getBooks() {
                 
          return books;
             }


             
          public void setBooks(Collection<Book> books) {
                 
          this.books = books;
             }


             
          public String load() {
                 book
          = dao.getBook(isbn);
                 
          return SUCCESS;
             }


             
          public String list() {
                 books
          = dao.getBooks();
                 
          return SUCCESS;
             }

                 
             
          public String store() {
                 dao.storeBook(book);
                 
          return SUCCESS;
             }

             
             
          public String remove() {
                 
          if(null != isbn) {
                     dao.removeBook(isbn);
                 }
          else {
                     dao.removeBooks(isbns);
                 }

                 
          return SUCCESS;
             }

          }
          清單3 src/tutorial/action/BookAction.java

          BookAction類中屬性isbn用于表示待編輯或刪除的書籍的編號,屬性isbns用于表示多個待刪除的書籍的編號數組,屬性book表示當前書籍,屬性books則表示當前的書籍列表。BookAction有四個Action方法分別是load、list、store和remove,也即是CRUD都集中在BookAction中實現。

          再下來是Action的配置代碼:

          <?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="Struts2_CRUD_DEMO" extends="struts-default" namespace="/Book">
                 
          <action name="List" class="tutorial.action.BookAction" method="list">
                     
          <result>List.jsp</result>
                 
          </action>
                 
          <action name="Edit" class="tutorial.action.BookAction" method="load">
                     
          <result>Edit.jsp</result>
                 
          </action>
                 
          <action name="Store" class="tutorial.action.BookAction" method="store">
                     
          <result type="redirect">List.action</result>
                 
          </action>
                 
          <action name="Remove" class="tutorial.action.BookAction" method="remove">
                     
          <result type="redirect">List.action</result>
                 
          </action>
             
          </package>
          </struts>
          清單4 src/struts.xml

          以上的配置中,我使用了四個Action定義。它們都在“/Book”名值空間內。這樣我就可以分別通過“http://localhost:8080/Struts2_CRUD/Book/List.action”、“http://localhost:8080/Struts2_CRUD/Book/Edit.action”、“http://localhost:8080/Struts2_CRUD/Book/Store.action”和“http://localhost:8080/Struts2_CRUD/Book/Remove.action”來調用BookAction的四個Action方法進行CRUD操作。當然,這只是個人喜好,你大可以只定義一個Action(假設其名稱為“Book”),之后通過“http://localhost:8080/Struts2_CRUD/Book!list.action”的方式來訪問,詳細做法請參考《Struts 2.0的Action講解》。另外,我由于希望在完成編輯或刪除之后回到列表頁,所以使用類型為redirect(重定向)的result。

          下面是列表頁面的代碼:

          <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
          <%@ taglib prefix="s" uri="/struts-tags" %>

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml">
          <head>
             
          <title>Book List</title>
             
          <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>
          </head>
          <body>    
             
          <h2>Book List</h2>
             
          <s:form action="Remove" theme="simple">
                 
          <table cellspacing="0">
                     
          <thead>
                         
          <tr>
                             
          <th>Select</th>
                             
          <th>ISBN</th>
                             
          <th>Title</th>
                             
          <th>Price</th>
                             
          <th>Operation</th>
                         
          </tr>
                     
          </thead>
                     
          <tbody>
                         
          <s:iterator value="books">
                             
          <tr>
                                 
          <td><input type="checkbox" name="isbns" value='<s:property value="isbn" />' /></td>
                                 
          <td><s:property value="isbn" /></td>
                                 
          <td><s:property value="title" /></td>
                                 
          <td>$<s:property value="price" /></td>
                                 
          <td>
                                     
          <a href='<s:url action="Edit"><s:param name="isbn" value="isbn" /></s:url>'>
                                          Edit
                                     
          </a>
                                     
          &nbsp;
                                     
          <a href='<s:url action="Remove"><s:param name="isbn" value="isbn" /></s:url>'>
                                          Delete
                                     
          </a>
                                 
          </td>
                             
          </tr>
                         
          </s:iterator>
                     
          </tbody>
                 
          </table>
                 
          <s:submit value="Remove" /><a href="Edit.jsp">Add Book</a>
             
          </s:form>    
          </body>
          </html>
          清單5 WebContent\Book\List.jsp

          以上代碼,值得注意的是在<s:form>標簽,我設置了theme屬性為“simple”,這樣可以取消其默認的表格布局。之前,有些朋友問我“如果不希望提交按鈕放在右邊應該怎樣做?”,上述做汗是答案之一。當然,更佳的做法自定義一個theme,并將其設為默認應用到整個站點,如此一來就可以得到統一的站點風格。我會在以后的文章中會對此作詳細的描述。

          編輯或添加書籍的頁面代碼如下:

          <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
          <%@ taglib prefix="s" uri="/struts-tags" %>

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml">
          <head>
             
          <title>Book</title>
          </head>
          <body>    
             
          <h2>
                 
          <s:if test="null == book">
                      Add Book
                 
          </s:if>
                 
          <s:else>
                      Edit Book
                 
          </s:else>
             
          </h2>
             
          <s:form action="Store" >
                 
          <s:textfield name="book.isbn" label="ISBN" />
                 
          <s:textfield name="book.title" label="Title" />
                 
          <s:textfield name="book.price" label="Price" />
                 
          <s:submit />
             
          </s:form>
          </body>
          </html>
          清單6 WebContent/Book/Edit.jsp

          如果book為null,則表明該頁面用于添加書籍,反之則為編輯頁面。

          為了方便大家運行示例,我把web.xml的代碼也貼出來,如下:

          <?xml version="1.0" encoding="UTF-8"?>
          <web-app id="WebApp_9" version="2.4"
              xmlns
          ="http://java.sun.com/xml/ns/j2ee"
              xmlns:xsi
          ="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation
          ="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

             
          <display-name>Struts 2 Fileupload</display-name>
              
             
          <filter>
                 
          <filter-name>struts2</filter-name>
                 
          <filter-class>
                      org.apache.struts2.dispatcher.FilterDispatcher
                 
          </filter-class>
             
          </filter>

             
          <filter-mapping>
                 
          <filter-name>struts2</filter-name>
                 
          <url-pattern>/*</url-pattern>
             
          </filter-mapping>

             
          <welcome-file-list>
                 
          <welcome-file>index.html</welcome-file>
             
          </welcome-file-list>

          </web-app>
          清單7 WebContent/WEB-INF/web.xml

          大功告成,下面發布運行應用程序,在瀏覽器中鍵入:http://localhost:8080/Struts2_CRUD/Book/List.action,出現如下圖所示頁面:


          清單8 列表頁面

          點擊“Add Book”,出現如下圖所示頁面:


          清單9 添加書籍頁面

          后退回到列表頁面,點擊“Edit”,出現如下圖所示頁面:


          清單10 編輯書籍頁面

          總結

          本文只是粗略地了介紹Struts 2的CRUD實現方法,所以有很多功能沒有實現,如國際化和數據校驗等。大家可以在上面例子的基礎將其完善,當作練習也不錯。如果過程中有不明白之處,可以參考我早前的文章或給我發E-Mail:max.m.yuan@gmail.com。

          posted on 2007-04-13 01:37 Max 閱讀(44907) 評論(74)  編輯  收藏 所屬分類: Struts 2.0系列

          評論:
          # re: 在Struts 2中實現CRUD 2007-04-13 03:45 | 山風小子
          一直關注著您的這一系列教程,辛苦了 :)  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-13 10:40 | 藍色天空的囚徒
          辛苦,辛苦!!!  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-13 12:21 | Long
          CRUD - Create, Retrieve, Update, and Delete ?
          雖然沒有必要為這些字眼來討論什么  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-13 22:47 | Max
          @Long
          謝謝,你的提醒。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-14 18:54 | furong
          MAX
          很感謝你這一系列的文章
          不知道能不能傳個關于struts2.0中樹控件運用的例子?
          非常感謝  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-15 12:10 | hushsky
          MAX你好,謝謝你的教程,我按照你的這個例子寫了一個可以正常運行,但是我加入對book.isbn的requiredstring校驗(在BookAction包下加入BookAction-validation.xml,主要部分如下:)
          <validators>
          <field name="book.isbn">
          <field-validator type="requiredstring">
          <message> The id is requiredstring!!</message>
          </field-validator>
          </field>
          </validators>
          另將struts.xml中Store.action修改為
          <action name="Store" class="..." method="store">
          <result type="redirect">List.action</result>
          <result name="input">edit.jsp</result>

          在edit.jsp中可以正常對isbn校驗
          但是由于設置的是對BookAction校驗,因此在執行List.action時也會進行檢驗并返回"input”,導致無法運行BookAction.list()方法
          這種情況應該怎么進行校驗,請指教,不勝感激
            回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-15 14:34 | Max
          最簡單的方法就是將你的BookAction-validation.xml文件改名為“BookAction-Store-validation.xml”。這樣validation的配置只對Store起作用。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-15 19:16 | hushsky
          @Max
          收到,十分感謝  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-16 14:48 | 千山鳥飛絕
          @Max
          請問“BookAction-Store-validation.xml”必須這樣寫嗎?為什么需要這樣寫呢?

          還有請問strust.xml必須寫在根目錄下嗎?
            回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-16 14:53 | hushsky
          MAX你好,不好意思又麻煩你
          本例中,我對book.isbn進行rquiredstring校驗,一切正常,但是我在“BookAction-Store-validation.xml”文件中的的<field-validator >加入short-circuit屬性實現短路校驗(我從webwork里看的,不知道struts2.0里是否可行)。
          代碼如下:<field-validator type="requiredstring" short-circuit="true">
          之后,程序可以運行,但是校驗框架就不起作用了,即便在Edit.jsp里不輸入isbn仍可以提交

          能請教一下原因嗎?  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-16 19:19 | crayz
          感謝,你的struts2系列文章
          我是新手,這個例子我調試成功了
          但我發現這個。不能輸入中文。一出來就是亂碼
          我查了查資料。自己加了個spring 里包含的一個filter 解決了encoding
          問題,添加是沒問題了,但是編輯仍然有問題。一點就是空白
          再添上去就是。新添加非。編輯了。不知道如果解決
          可能我問的太初級。可struts2資源實在有限 沒辦法了麻煩你了
          或者能提供些編碼方面的參考資料呢。歇息  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-16 23:41 | Max
          @千山鳥飛絕
          1、請參考我的《在Struts 2.0中實現表單數據校驗(Validation)》中“配置文件查找順序”
          2、不是,你可以通過以下設置改變struts.xml位置:
          <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,config/struts.xml</param-value>
          </init-param>
          </filter>  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-17 10:02 | Max
          @hushsky
          加入<field-validator type="requiredstring" short-circuit="true"> 之后,運行,例子會出現
          org.xml.sax.SAXParseException: Attribute "short-circuit" must be declared for element type "field-validator".
          但是,按照DTD的定義,short-ciruit是合法的屬性??赡苁荢truts 2的BUG。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-17 10:07 | Max
          @crayz
          亂碼問題不是三言兩語能夠說得清楚的,因為這跟你的JVM區域(locale)、頁面編碼和IE的設置都有關。你可以GOOGLE一下,應該有很多不錯的文章。
          通常的做法是盡量將所有編碼類型都認為utf-8。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-17 10:59 | hermit
          Max在線么?validate驗證如何使一個.xml文件的驗證只對action的一個方法有效?就是說我一個action有CRUD方法,我如何讓在刪除和查詢時跳過驗證?  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-17 19:04 | Max
          @hermit
          請參考上面的評論  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-18 10:18 | hermit
          謝謝,你指的是“BookAction-Store-validation.xml”對么?我昨天看到了。但是還是沒有配置出來,后來我把Store改成了action訪問的全路徑(action!方法名)就可以了。但是還有個問題就是,增刪改我想讓他返回不同的頁面。昨天調了一天。沒搞定!好像這個1.x的版本也是有這個問題。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-19 01:56 | Z
          你好,我在調試你的這個例子時,為什么從struts.xml的result里跳到

          List.action時會出現
          The requested resource (/test/Book/List.action) is not available.
          錯誤,

          而直接用http://localhost:8080/test/Book/List.action訪問時卻可以呢?

          麻煩解釋一下,謝謝  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-24 16:10 | ddd
          很好的文章。。。謝謝。。
          我這2天也才知道Struts2.0(汗),馬上看了看。。
          LZ的教程非常有幫組。。

          另外, 我對apache struts官方網上的教程也作了一次。。。
          http://struts.apache.org/2.x/docs/tutorials.html
          那個Struts 2 + Spring 2 + JPA + AJAX 里提到的CRUD,
          與LZ介紹的方法一致,不過,偶連Spring都沒用過,所以這2天
          就看了Spring的一些文章, 才有點明白了。。開始。。。

          不過,對于web.xml中關于encoding的設置,還是有點迷惑。。
          spring的filter沒搞定, 不知道使用自己寫的方法是否可行。。
          自己定義servletFilter類,web.xml中記述servletFilter, <init-param>
            回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-25 09:12 | Max
          @Z
          應該是路徑配錯了。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-25 09:13 | Max
          @ddd
          可能要具體問題,具體分析。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-04-26 09:15 | 123
          為什么不用中文的做例子?
            回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-05-08 10:11 | S
          Edit雖然能夠讀取數據,但是點submit就會“添加”新數據,而不是對原數據進行修改。。。。
          麻煩max看一下  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-05-08 23:19 | Max
          這是因為你改了isbn,我是用isbn作為數據的索引。理論上isbn是不可以修改的。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-05-15 18:41 | Niuzai
          好棒啊...高手...謝謝你了謝謝大家...  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-05-25 14:14 | bruy
          請問Max,如果我一次要增加多條Book,該怎么做呢?
          這在開發中很常見,不是一條條的去點添加按鈕,而是在頁面上添加多行后,一次提交,請問這個應該怎么實現呢?  回復  更多評論
            
          # attempt to create saveOrUpdate event with null entity 2007-06-11 18:02 | sapphire
          這是什么錯誤?  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-08-11 10:37 | liy
          MAX大哥,能不能發個源碼給我,我后面做你這上面的例子都會有錯.麻煩你了.
          我的郵箱是followmephoe@yahoo.com.cn  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-08-13 19:59 | louleigh
          MAX
          大哥。
          我看你的源碼..點remove button的時候應該執行的是全部操作.
          為什么我的是null pointer exception..
          我跟蹤發現..
          this.getisbns()沒有獲取到值.請問為什么  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-08-14 09:40 | sjtde
          MAX,如果在這上面加上 token 該如何加呢?  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-08-20 23:56 | 羅文飛
          book是建在那個文件下啊/  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-08-31 15:37 | tf
          我按照上面的代碼輸入運行怎么出現這個錯誤呢?
          type Exception report

          message

          description The server encountered an internal error () that prevented it from fulfilling this request.

          exception

          file:/C:/lomboz/eclipse/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/webapps/Struts2_CRUD/WEB-INF/classes/struts.xml:2:8
          com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadConfigurationFile(XmlConfigurationProvider.java:678)
          com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.init(XmlConfigurationProvider.java:117)
          com.opensymphony.xwork2.config.impl.DefaultConfiguration.reload(DefaultConfiguration.java:87)
          com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:46)
          org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:218)


          note The full stack trace of the root cause is available in the Apache Tomcat/5.5.17 logs.


          --------------------------------------------------------------------------------
            回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-09-12 15:54 | tigershi10
          max你好
          我想問一下
          <td><s:checkbox name="isbns" value="isbn"/></td>
          <td><input type="checkbox" name="isbns" value='<s:property value="isbn" />' /></td>
          這2條語句為什么上面那面就不行  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-10-09 16:36 | buddha
          @Max
          加入<field-validator type="requiredstring" short-circuit="true"> 之后,運行,例子會出現
          org.xml.sax.SAXParseException: Attribute "short-circuit" must be declared for element type "field-validator".
          但是,按照DTD的定義,short-ciruit是合法的屬性。可能是Struts 2的BUG。

          我也碰到這個問題,真不敢相信,struts2竟會出這種低級問題。
          請問max兄有沒有查過struts的bug庫?或這類問題的討論?  回復  更多評論
            
          # re: 在Struts 2中實現CRUD[未登錄] 2007-10-10 10:39 | Eric


          message

          description The server encountered an internal error () that prevented it from fulfilling this request.

          exception

          No result defined for action tutorial.action.BookAction and result input - action - file:/E:/JavaProject/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/DBStruts2/WEB-INF/classes/struts.xml:17:80
          com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:350)
          com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:253)
          com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:150)
          org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:48)
          com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:86)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
          com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
          com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
          com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:123)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
          com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
          com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
          com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:167)
          com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:86)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
          com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
          com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
          com.opensymphony.xwork2.interceptor. com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
          org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:170)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
          com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
          com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
          com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:123)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
          com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
          com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
          com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
          com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
          com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
          com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
          org.apache.struts2.impl.StrutsActionProxy.execute

            回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-10-22 15:46 | xjxy
          @buddha
          我也遇到相同的問題,但是google一下說在xml中設置為<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd" >可解決問題,試了一下,使用short-circuit是不會報錯了,但是完全不起作用,跟沒使用short-circuit一樣,那位有更好的解決方法?  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2007-11-05 13:49 | cowboy
          想請教一個小問題:
          為什么我把 List.jsp 頁面里的“<input type="checkbox" name="isbns" value='<s:property value="isbn" />' />”
          改為:“<s:checkbox type="checkbox" name="isbns" value='<s:property value="isbn" />' />”

          選擇一個isbn后按Remove按鈕就會出錯:
          No result defined for action com.struts2.action.UserManagerAction and result input
          這樣的錯誤。
          如果不改就沒有錯誤,這是為什么。
          還有,struts2.0里的“checkbox”標簽跟html里的“input type="checkbox"”有什么區別?  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-02-03 11:57 | 大漠落日
          @cowboy
          “<s:checkbox type="checkbox" name="isbns" value='<s:property value="isbn" />' />”
          --》“<s:checkbox name="isbns" value='<s:property value="isbn" />' />”
          這樣試試。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-02-21 09:41 | solong1980
          我實在忍不住了,對樓主的贊美猶如滔滔江水,連綿不絕  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-02-27 17:30 | tarzan
          好人啊,對樓主無限敬佩中.........  回復  更多評論
            
          # re: 在Struts 2中實現CRUD[未登錄] 2008-02-29 23:23 | Nick
          樓主,我照你的代碼寫了。但list.jsp沒有數據,iterator沒有循環。怎么回事啊?
          謝謝。。。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD[未登錄] 2008-03-01 09:00 | Song
          LZ,我按上面代碼寫的。怎么沒有先調用list()啊,頁面沒有出現數據。。。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-03-01 11:43 | labeille
          @Nick / Song
          去掉驗證validate() 就可以了。。。 :-)  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-03-11 13:57 | lastsweetop
          程序需要做些小修改哦
          因為修改isbn的話 原來的沒刪除 又出現個新的

          在dao中存放一個靜態isbn存放要修改的isbn就可以了

          呵呵 總之 很不錯 感謝了  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-03-11 13:58 | lastsweetop
          DEBUG 2008-03-11 13:56:59.571 [freemark] (): Could not find template in cache, creating new one; id=[template/simple/scripting-events.ftl[zh_CN,UTF-8,parsed] ]
          DEBUG 2008-03-11 13:56:59.586 [freemark] (): Compiling FreeMarker template template/simple/scripting-events.ftl[zh_CN,UTF-8,parsed] from jar:file:/F:/tomcat/apache-tomcat-5.5.23/webapps/struts1/WEB-INF/lib/struts2-core-2.0.11.1.jar!/template/simple/scripting-events.ftl
          DEBUG 2008-03-11 13:56:59.586 [freemark] (): Could not find template in cache, creating new one; id=[template/simple/common-attributes.ftl[zh_CN,UTF-8,parsed] ]

          每次加載或刷新頁面都會出現這樣的debug 請問又什么好的辦法解決。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD[未登錄] 2008-03-19 15:35 | king
          真正的界面不會那么簡單,我想問一下,如果我想彈出一個窗口來做增加和修改操作,應該怎么做?  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-04-26 17:19 | helen
          寫的好精彩啊 ,看懂了,但是 我用的maven ,mvn jetty:run ,后運行http://localhost:8080/Struts2_CRUD/Book/List.action,頁面不顯示,后臺 報錯,請問是什么原因呢 ?是 web.xml我沒改,strut2和maven配置不同么?不懂啊 。。。

          Exception in thread "btpool0-1" java.lang.Error: Untranslated exception
          at sun.nio.ch.Net.translateToSocketException(Net.java:65)
          at sun.nio.ch.SocketAdaptor.close(SocketAdaptor.java:354)
          at org.mortbay.io.nio.ChannelEndPoint.close(ChannelEndPoint.java:100)
          at org.mortbay.jetty.nio.SelectChannelConnector$SelectChannelEndPoint.cl
          ose(SelectChannelConnector.java:716)
          at org.mortbay.jetty.nio.HttpChannelEndPoint.close(HttpChannelEndPoint.j
          ava:329)
          at org.mortbay.jetty.nio.HttpChannelEndPoint$IdleTask.expire(HttpChannel
          EndPoint.java:369)
          at org.mortbay.jetty.nio.SelectChannelConnector$SelectSet.accept(SelectC
          hannelConnector.java:458)
          at org.mortbay.jetty.nio.SelectChannelConnector.accept(SelectChannelConn
          ector.java:175)
          at org.mortbay.jetty.AbstractConnector$Acceptor.run(AbstractConnector.ja
          va:630)
          at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool
          .java:475)
          Caused by: java.io.IOException: An operation was attempted on something that is
          not a socket
          at sun.nio.ch.SocketDispatcher.close0(Native Method)
          at sun.nio.ch.SocketDispatcher.preClose(SocketDispatcher.java:44)
          at sun.nio.ch.SocketChannelImpl.implCloseSelectableChannel(SocketChannel
          Impl.java:684)
          at java.nio.channels.spi.AbstractSelectableChannel.implCloseChannel(Abst
          ractSelectableChannel.java:201)
          at java.nio.channels.spi.AbstractInterruptibleChannel.close(AbstractInte
          rruptibleChannel.java:97)
          at sun.nio.ch.SocketAdaptor.close(SocketAdaptor.java:352)
          ... 8 more  回復  更多評論
            
          # re: 在Struts 2中實現CRUD[未登錄] 2008-04-30 19:13 | jackey
          @大漠落日
          這樣設置不會報錯,但進行刪除操作時不能真正進行。值已經變為true/false
            回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-05-12 10:42 | tt
          好人啊,對樓主無限敬佩中.........   回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-05-15 17:32 | lrm
          謝謝!  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-06-17 11:24 | hover
          @Max
          樓主,我發現這個例子不能實現連續Add Book,就是說我第一次Add成功了,但接著Add時路徑就變了,(因為我是把jsp放在一個文件夾中的,這樣利于管理)  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-06-17 11:40 | hover
          @Max
          問題解決了,原來是因為我把namespace="/operate"去掉,而把<result>List.jsp</result>改成了<result>/operate/List.jsp</result>,把它改成樓主的方法就可以了。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-07-04 16:10 | yellow race
          Thanks!  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-07-29 15:31 | se
          @louleigh
          @louleigh
          看下Book.java得構造函數public Book(){}有沒漏寫   回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-07-30 10:46 | dxm
          @xjxy
          我按你說的這樣寫了,結果可以實現啊。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD[未登錄] 2008-08-07 14:19 | matrix
          每篇文章都是精品,頂。期待MAX兄更多好文章。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-09-04 10:21 | ren
          @tf
          Book類中少了構造函數
          public Book() {
          }  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-09-04 11:10 | 非主流@bin
          max朋友你好,我也是最近開始研究struts2的。覺得這個框架很經濟。配置很完善。目前我在一一的看你的教程,很好很強大。希望你可以給我發個這些教程的src源代碼好嗎?
          lanisha00006@163.com
          不勝感激~~~  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-09-05 14:35 | walkes
          DEBUG 2008-09-05 14:33:01.406 [freemark] (): Could not find template in cache, creating new one; id=[template/simple/form.ftl[zh_CN,UTF-8,parsed] ]
          DEBUG 2008-09-05 14:33:01.421 [freemark] (): Compiling FreeMarker template template/simple/form.ftl[zh_CN,UTF-8,parsed] from jar:file:/D:/workspace/struts2_helloworld/WebRoot/WEB-INF/lib/struts2-core-2.0.11.2.jar!/template/simple/form.ftl
          DEBUG 2008-09-05 14:33:02.250 [freemark] (): Could not find template in cache, creating new one; id=[template/simple/submit.ftl[zh_CN,UTF-8,parsed] ]
          DEBUG 2008-09-05 14:33:02.265 [freemark] (): Compiling FreeMarker template template/simple/submit.ftl[zh_CN,UTF-8,parsed] from jar:file:/D:/workspace/struts2_helloworld/WebRoot/WEB-INF/lib/struts2-core-2.0.11.2.jar!/template/simple/submit.ftl
          DEBUG 2008-09-05 14:33:02.515 [freemark] (): Could not find template in cache, creating new one; id=[template/simple/scripting-events.ftl[zh_CN,UTF-8,parsed] ]
          DEBUG 2008-09-05 14:33:02.515 [freemark] (): Compiling FreeMarker template template/simple/scripting-events.ftl[zh_CN,UTF-8,parsed] from jar:file:/D:/workspace/struts2_helloworld/WebRoot/WEB-INF/lib/struts2-core-2.0.11.2.jar!/template/simple/scripting-events.ftl
          DEBUG 2008-09-05 14:33:02.531 [freemark] (): Could not find template in cache, creating new one; id=[template/simple/common-attributes.ftl[zh_CN,UTF-8,parsed] ]
          DEBUG 2008-09-05 14:33:02.546 [freemark] (): Compiling FreeMarker template template/simple/common-attributes.ftl[zh_CN,UTF-8,parsed] from jar:file:/D:/workspace/struts2_helloworld/WebRoot/WEB-INF/lib/struts2-core-2.0.11.2.jar!/template/simple/common-attributes.ftl
          DEBUG 2008-09-05 14:33:02.546 [freemark] (): Could not find template in cache, creating new one; id=[template/simple/form-close.ftl[zh_CN,UTF-8,parsed] ]
          DEBUG 2008-09-05 14:33:02.546 [freemark] (): Compiling FreeMarker template template/simple/form-close.ftl[zh_CN,UTF-8,parsed] from jar:file:/D:/workspace/struts2_helloworld/WebRoot/WEB-INF/lib/struts2-core-2.0.11.2.jar!/template/simple/form-close.ftl

          好多次都有這個DUBUG信息,不過沒有看明白什么意思,max老大知道解釋下,另外方便的話給我發一份這個系列教程的源代碼,謝謝。
          mail to: walkes@163.com  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-11-19 14:07 | lrl
          相見恨晚啊。。。max大哥  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2008-11-27 11:09 | struts2
          有后續的文章么?期待啊1  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2009-01-15 11:31 | min
          徹頭徹尾的感謝,看了你的“在Struts 2中實現CRUD”,讓我在struts2方面有了大的突破。
          以后一定常來光顧 新年快樂!  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2009-02-12 12:22 | adming
          to All :
          關于<s:checkbox/>和<input type="checkbox"/>的不同:
          <s:checkbox />的fieldValue屬性才相當于<input type="checkbox"/>的value屬性,可以通過查看頁面的源代碼得知  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2009-04-28 15:45 | scorris
          有個小小問題,樓主以book對象是否為空,判斷是新增還是修改,這個方法不可行。原因是:
          在“新增頁面”,假設使用驗證框架,驗證不通過就會返回“新增頁面”,這時候book對象已經不為空了,原來的“新增頁面”就會變成“修改頁面”  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2009-10-28 21:31 | 2008iava
          很有用的知識。。謝謝了。動手去試試。。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2010-01-21 14:19 |
          樓主很容易被累死  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2010-01-22 12:22 | liuxiao
          Max兄:您好!這里我有些疑問,還望不吝賜教
          程序的執行過程是首先通過List.action調用tutorial.action.BookAction,
          這時會對通過BookDao dao = BookDao.getInstance()進行dao的實例化,實例化之后會在對象dao中形成一個ConcurrentMap類型的data對象。這個對象中包括初始化的那些書籍。程序到這一步沒什么問題,但是當點擊edit、add book、delete之后進入相應的edit.jsp頁面或action處理之后又通過List.action跳轉到List.jsp頁面,這時在每一步跳轉中tutorial.action.BookAction都會通過BookDao dao = BookDao.getInstance()進行初始化,那么其中dao.data這個對象不是每次都會被重新賦值了嗎?但是為什么沒有發生這種情況呢?

            回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2010-03-11 12:05 | j
          j  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2011-05-15 15:01 | 肖碩
          你寫的真是太好了,好神奇啊  回復  更多評論
            
          # re: 在Struts 2中實現CRUD[未登錄] 2012-01-30 10:40 | Bruce
          @Z
          Struts.xml中的配置有可能沒寫對
          是<result type="redirect">List.action</result>
          而不是<result>List.action</result>  回復  更多評論
            
          # re: 在Struts 2中實現CRUD[未登錄] 2012-02-03 14:26 | Bruce
          照例子實踐了,非常不錯。感謝  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2012-06-07 23:36 | ying
          @liuxiao
          BookDao是單例。  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2014-08-13 09:57 | witleo
          3Q  回復  更多評論
            
          # re: 在Struts 2中實現CRUD 2014-08-13 10:00 | @。@
          @witleo
          你知道什么了  回復  更多評論
            
          主站蜘蛛池模板: 循化| 武夷山市| 苍南县| 五大连池市| 蓬莱市| 石柱| 子洲县| 景东| 安泽县| 叶城县| 化德县| 鹤庆县| 开远市| 陕西省| 汾阳市| 手机| 石门县| 和硕县| 浦江县| 武陟县| 黔东| 洪泽县| 罗平县| 温泉县| 满洲里市| 公主岭市| 临桂县| 镇安县| 安国市| 健康| 台湾省| 玉山县| 巴彦县| 扎鲁特旗| 沾益县| 夹江县| 忻州市| 张家港市| 揭阳市| 齐河县| 新绛县|