随笔-33  评论-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 阅读(44415) 评论(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是合法的属性。可能是Struts 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
你知道什么了  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: