随笔-34  评论-1965  文章-0  trackbacks-0

在我已往的Struts 1.x项目经验中,有个问题不时的出现——在创建FormBean时,对于某个属性到底应该用String还是其它类型?

开发Web应用程序与开发传统桌面应用程序不同,Web应用程序实际上是分布个不同的主机(当然也可以同一个主机,不过比较少见)上的两个进程之间互交。这种互交建立在HTTP之上,它们互相传递是都是字符串。换句话说, 服务器可以的接收到的来自用户的数据只能是字符串或字符数组,而在服务器上的对象中,这些数据往往有多种不同的类型,如日期(Date),整数(int),浮点数(float)或自定义类型(UDT)等,如图1所示。因此,我们需要服务器端将字符串转换为适合的类型。

图1 UI与服务器对象关系
图1 UI与服务器对象关系

同样的问题也发生在使用UI展示服务器数据的情况。HTML的Form控件不同于桌面应用程序可以表示对象,其值只能为字符串类型,所以我们需要通过某种方式将特定对象转换成字符串。

要实现上述转换,Struts 2.0中有位魔术师可以帮到你——Converter。有了它,你不用一遍又一遍的重复编写诸如此类代码:

Date birthday = DateFormat.getInstance(DateFormat.SHORT).parse(strDate);
<input type="text" value="<%= DateFormat.getInstance(DateFormat.SHORT).format(birthday) %>" />

好了,现在让我们来看一个例子。

转换器——Hello World

在我的上一篇文章《在Struts 2.0中国际化(i18n)您的应用程序》的最后我举了一个可以让用户方便地切换语言的例子,下面例子与其相似,但实现方法不同。

首先,如《在Struts 2.0中国际化(i18n)您的应用程序》的第一个例子一样,创建和配置默认的资源文件;

接着,新建源代码文件夹下的tutorial包创建HelloWorld.java文件,代码如下:

package tutorial;

import java.util.Locale;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.LocalizedTextUtil;

public class HelloWorld extends ActionSupport {
   
private String msg;
   
private Locale loc = Locale.US;
  
   
public String getMsg() {
       
return msg;        
   }

   
   
public Locale getLoc() {
       
return loc;
   }

   
   
public void setLoc(Locale loc) {
       
this .loc = loc;
   }

   
   @Override
   
public String execute() {
       
// LocalizedTextUtil是Struts 2.0中国际化的工具类,<s:text>标志就是通过调用它实现国际化的
       msg = LocalizedTextUtil.findDefaultText( " HelloWorld " , loc);
       
return SUCCESS;
   }

}

然后,在源代码文件夹下的struts.xml加入如下代码新建Action:

< package name ="ConverterDemo" extends ="struts-default" >
   
< action name ="HelloWorld" class ="tutorial.HelloWorld" >
       
< result > /HelloWorld.jsp </ result >
   
</ action >
</ package >

再在Web文件夹下,新建 HelloWorld.jsp,代码如下:

< %@ page   contentType ="text/html; charset=UTF-8" % >
< %@taglib prefix ="s" uri ="/struts-tags" % >
< html >
< head >
   
< title > Hello World </ title >
</ head >
< body >
   
< s:form action ="HelloWorld" theme ="simple" >            
        Locale:
< s:textfield name ="loc" /> &nbsp; < s:submit />
   
</ s:form >    
   
< h2 >< s:property value ="msg" /></ h2 >
</ body >
</ html >

接下来,在源代码文件夹的tutorial包中新建LocaleConverter.java文件,代码如下:

package tutorial;

import java.util.Locale;
import java.util.Map;

public class LocaleConverter extends ognl.DefaultTypeConverter {
   @Override
   
public Object convertValue(Map context, Object value, Class toType) {
       
if (toType == Locale. class ) {
           String locale
= ((String[]) value)[ 0 ];
           
return new Locale(locale.substring( 0 , 2 ), locale.substring( 3 ));
       }
else if (toType == String. class ) {
           Locale locale
= (Locale) value;
           
return locale.toString();
       }

       
return null ;
   }

}

再接下来,在源代码文件夹下新建xwork-conversion.properties,并在其中添加如下代码:

java.util.Locale = tutorial.LocaleConverter

发布运行应用程序,在浏览器中键入http://localhost:8080/Struts2_Converter/HelloWorld.action,输出页面如图2所示:
图2 HelloWorld英文输出
图2 HelloWorld英文输出

在Locale输入框中输入“zh_CN”,按“Submit”提交,出现如图3所示页面:
图3 HelloWorld中文输出
图3 HelloWorld中文输出

上述例子中,Locale文本输入框对应是Action中的类型为java.util.Locale的属性loc,所以需要创建一个自定义转变器实现两者间的转换。所有的Struts 2.0中的转换器都必须实现ognl.TypeConverter接口。 为了简单起见,OGNL包也为你提供了ognl.DefaultTypeConverter类去帮助您实现转换器。在例子中,LocaleConverter继承了ognl.DefaultTypeConverter,重载了其方法原型为“public Object convertValue(Map context, Object value, Class toType)”的方法。下面简单地介绍一下函数的参数:

  1. context——用于获取当前的ActionContext
  2. value——需要转换的值
  3. toType——需要转换成的目标类型
实现转换器,我们需要通过配置告诉Struts 2.0。我们可以通过以下两种方法做到这点:
  1. 配置全局的类型转换器,也即是上例的做法——在源代码文件夹下,新建一个名为“xwork-conversion.properties”的配置文件,并在文件中加入“待转换的类型的全名(包括包路径和类名)=转换器类的全名”对;
  2. 应用于某个特定类的类型转换器,做法为在该类的包中添加一个格式为“类名-conversion.properties”的配置文件,并在文件中加入“待转换的属性的名字=转换器类的全名”对。上面的例子也可以这样配置——在源代码文件夹的tutorial包下新建名为“HelloWorld-conversion.properties”文件,并在其中加入“loc=tutorial.LocaleConverter”。
在继承DefaultTypeConverter时,如果是要将value转换成其它非字符串类型时,要记住value是String[]类型,而不是String类型。它是通过request.getParameterValues(String arg)来获得的,所以不要试图将其强行转换为String类型。

已有的转换器

对于一此经常用到的转换器,如日期、整数或浮点数等类型,Struts 2.0已经为您实现了。下面列出已经实现的转换器。

  1. 预定义类型,例如int、boolean、double等;
  2. 日期类型, 使用当前区域(Locale)的短格式转换,即DateFormat.getInstance(DateFormat.SHORT);
  3. 集合(Collection)类型, 将request.getParameterValues(String arg)返回的字符串数据与java.util.Collection转换;
  4. 集合(Set)类型, 与List的转换相似,去掉相同的值;
  5. 数组(Array)类型, 将字符串数组的每一个元素转换成特定的类型,并组成一个数组。
对于已有的转换器,大家不必再去重新发明轮子。Struts在遇到这些类型时,会自动去调用相应的转换器。

批量封装对象(Bean)

不知道大家是否遇过这种情况,在一个页面里同时提交几个对象。例如,在发布产品的页面,同时发布几个产品。我在之前一个项目就遇到过这种需求,当时用的是Struts 1.x。那是一个痛苦的经历,我在Google搜了很久都没有理想的结果。幸运的是,在Struts 2.0中这种痛苦将一去不复返。下面我就演示一下如何实现这个需求。

首先,在源代码文件夹下的tutorial包中新建Product.java文件,内容如下:

package tutorial;

import java.util.Date;

publicclass Product {
   
private String name;
   
privatedouble price;
   
private Date dateOfProduction;
   
   
public Date getDateOfProduction() {
       
return dateOfProduction;
   }

   
   
publicvoid setDateOfProduction(Date dateOfProduction) {
       
this.dateOfProduction = dateOfProduction;
   }

   
   
public String getName() {
       
return name;
   }

   
   
publicvoid setName(String name) {
       
this.name = name;
   }

   
   
publicdouble getPrice() {
       
return price;
   }

   
   
publicvoid setPrice(double price) {
       
this.price = price;
   }
   
}

然后,在同上的包下添加ProductConfirm.java类,代码如下:

package tutorial;

import java.util.List;

import com.opensymphony.xwork2.ActionSupport;

publicclass ProductConfirm extends ActionSupport {
   
public List<Product> products;

   
public List<Product> getProducts() {
       
return products;
   }


   
publicvoid setProducts(List<Product> products) {
       
this.products = products;
   }

   
   @Override
   
public String execute() {
       
for(Product p : products) {
           System.out.println(p.getName()
+ " | "+ p.getPrice() +" | " + p.getDateOfProduction());
       }

       
return SUCCESS;
   }

}

接看,在同上的包中加入ProductConfirm-conversion.properties,代码如下:

Element_products=tutorial.Product

再在struts.xml文件中配置ProductConfirm Action,代码片段如下:

<action name="ProductConfirm" class="tutorial.ProductConfirm">
   
<result>/ShowProducts.jsp</result>
</action>

在WEB文件夹下新建AddProducts.jsp,内容如下:

<%@ page  contentType="text/html; charset=UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
   
<title>Hello World</title>
</head>
<body>
   
<s:form action="ProductConfirm" theme="simple">            
       
<table>
           
<tr style="background-color:powderblue; font-weight:bold;">
               
<td>Product Name</td>
               
<td>Price</td>
               
<td>Date of production</td>
           
</tr>
           
<s:iterator value="new int[3]" status="stat">
               
<tr>
                   
<td><s:textfield name="%{'products['+#stat.index+'].name'}"/></td>
                   
<td><s:textfield name="%{'products['+#stat.index+'].price'}"/></td>
                   
<td><s:textfield name="%{'products['+#stat.index+'].dateOfProduction'}"/></td>
               
</tr>
           
</s:iterator>
           
<tr>
               
<td colspan="3"><s:submit /></td>
           
</tr>
       
</table>
   
</s:form>    
</body>
</html>

在同样的文件夹下创建ShowProducts.jsp,内容如下:

<%@ page  contentType="text/html; charset=UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
   
<title>Hello World</title>
</head>
<body>    
   
<table>
       
<tr style="background-color:powderblue; font-weight:bold;">
           
<td>Product Name</td>
           
<td>Price</td>
           
<td>Date of production</td>
       
</tr>
       
<s:iterator value="products" status="stat">
           
<tr>
               
<td><s:property value="name"/></td>
               
<td>$<s:property value="price"/></td>
               
<td><s:property value="dateOfProduction"/></td>
           
</tr>
       
</s:iterator>
   
</table>
</body>
</html>

发布运行应用程序,在浏览器中键入http://localhost:8080/Struts2_Converter/AddProducts.jsp,出现如图4所示页面:
图4 添加产品页面
图4 添加产品页面

按图4所示,填写表单,按“Submit”提交,出现图5所示页面:
图5 查看产品页面
图5 查看产品页面

查看服务器的控制台,有如下输出:

Expert One-on-One J2EE Development without EJB | 39.99 | Mon Jun 2100:00:00 CST 2004
Pro Spring |
32.99 | Mon Jan 3100:00:00 CST 2005
Core J2EE Patterns: Best Practices and Design Strategies
, Second Edition | 34.64 | Sat May 1000:00:00 CST 2003

上面的代码并不复杂,但有几点需要说明:

  1. ProductConfirm文件中的for(Product p : productes)的写法是J2SE 5.0中的新特性,作用遍历products列表;
  2. List<Product>也是J2SE 5.0的才有的泛型(Generic);
  3. ProductConfirm-conversion.properties中“Element_products=tutorial.Product”是告诉Struts 2.0列表products的元素的类型为Product,而不是定义转换器;
  4. 在AddProducts.jsp的<s:textfield>的name为“%{'products['+#stat.index+'].name'}”,%{exp}格式表示使用OGNL表达式,上述表达式的相当于<%= "products[" + stat.index + "].name" %>,至于<s:iterator>标志的用法可以参考我之前的文章《常用的Struts 2.0的标志(Tag)介绍》。

转换错误处理

不知道大家在运行上面的例子时,有没有填错日期或数字情况,又或者您有没有思考过这种情况?如果还没有尝试的朋友可以试一下,在第一行的Price和Date of production中输入英文字母,然后按“Submit”提交。你会看到页面为空白,再看一下服务器的控制台输出,有如下语句: 警告: No result defined for action tutorial.ProductConfirm and result input,它提示我们没有为Action定义输入结果,所以,我们应该在源代码文件夹下的struts.xml中的ProductConfirm Action中加入以下代码:

<result name="input">/AddProducts.jsp</result>

重新加载应用程序,刷新浏览器重新提交请求,这时页面返回AddProducts.jsp,格式错误的输入框的值被保留,如下图6所示:
图6 没有提示的错返回页面
图6 没有提示的错返回页面

当然,我们还可以在页面上加上错误提示信息,通过在AddProducts.jsp的“<body>”后,加入下面代码可以实现:

<div style="color:red">
   
<s:fielderror />
</div>

刷新浏览器,重新提交请求,出现如图7所示页面:
图7 带提示的错返回页面
图7 带提示的错返回页面

以上的功能的都是通过Struts 2.0里的一个名为conversionError的拦截器(interceptor)工作,它被注册到默认拦截器栈(default interceptor stack)中。Struts 2.0在转换出错后,会将错误放到ActionContext中,在conversionError的作用是将这些错误封装为对应的项错误(field error),因此我们可以通过<s:fielderror />来将其在页面上显示出来。另外,大家看第二和第三行的Price都被赋为0.0的值,而第一行则保留其错误值。这同样是conversionError的功劳——没有出错的行调用的products[index].price(默认值为0.0),而出错的行则会被赋为页面所提交的错误值,这样可以提供更好的用户体验。

总结

Struts 2.0的转换器简化的WEB应用程序的模型,为我们的编程带来极大的方便。

posted on 2006-11-07 14:26 Max 阅读(42083) 评论(98)  编辑  收藏 所属分类: Struts 2.0系列

评论:
# re: 转换器(Converter)——Struts 2.0中的魔术师 2006-11-07 15:28 | 坏男孩
抢到沙发!
跑跑卡丁车  回复  更多评论
  
# 请求转载 2006-11-07 15:58 | zz3zcwb
站长:
你好,你的Struts 2系列写得很好,我想在我个人站点上转载收藏,不知可否,望你在百忙中回信.
陈伟波
我的站点:www.java3z.com
email:zz3zcwb@sina.com
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2006-11-20 15:16 | lxf
为什么我在图2和图3中都无法出现“hello world”和“你好,世界”  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-03-11 14:52 | praguesky
好文章.....  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2007-03-15 12:00 | hunter
剛接觸struts2!!學起來好吃力﹗﹗

要具備啥知識﹐有啥好學習方法﹗﹗

email hunter123456@126.com  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-03-22 09:59 | 应用之美
谢谢了 ,非常需要!!!  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2007-03-27 18:33 | tiger
在你帮助下成长  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-03-27 23:17 | Max
@tiger
@应用之美
过奖了,只是略尽绵力而已。最重要是文章对你们有所帮助。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-04-04 15:29 | 凌伟
啊   回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-04-07 10:48 | furong
谢谢你MAX
无意中发先了你的blog,受益匪浅!
希望可以学习到更多,期待你的文章  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-04-10 23:27 | ColinBin
非常感谢.受益非浅  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-04-18 19:49 | 杰克
关于类型转换错误提示的疑问:在图7中显示的错误提示应该有两份:一是conversion Error Interceptor的默认错误提示;一是手动添加的<s:fielderror />标签提供的错误提示。真正改写错误提示的方法应该是修改i18n key。官方网站原文摘录如下:
--------------------------------
By default, all conversion errors are reported using the generic i18n key xwork.default.invalid.fieldvalue, which you can override (the default text is Invalid field value for field "xxx", where xxx is the field name) in your global i18n resource bundle.

However, sometimes you may wish to override this message on a per-field basis. You can do this by adding an i18n key associated with just your action (Action.properties) using the pattern invalid.fieldvalue.xxx, where xxx is the field name.
-----------------------------------  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2007-04-19 10:33 | Tony
多谢你的struts2系列文章,在这些文章的帮助下我还是很有收获的。可是我最想知道的是:你在接触一个新的框架的时候是怎么开始学习的?
俗话说的好:授之以鱼不如授之以渔。还望你不吝赐教。
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-04-19 23:35 | Max
@Tony
我会先详细阅读它的文档,最好可以找到相关的书籍学习,对于入门书往往比文档要容易许多;
然后,尝试去写一些简单的应用;
熟悉之后,思考一下框架的实现原理。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-04-20 13:53 | gege
比较好,可是还是吃力啊,
怎样设置用户校验啊?那个验证的xml在什么时候加载啊?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2007-04-28 16:34 | soa
我在运行你这个例子的时候,出现了错误:
输入:http://localhost:8080/converter/AddProducts.jsp
报错:
org.apache.jasper.JasperException
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:373)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:245)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:248)


root cause

java.lang.NullPointerException
org.apache.struts2.components.UIBean.evaluateParams(UIBean.java:703)
org.apache.struts2.components.UIBean.end(UIBean.java:450)
org.apache.struts2.views.jsp.ComponentTagSupport.doEndTag(ComponentTagSupport.java:36)
org.apache.jsp.AddProducts_jsp._jspx_meth_s_textfield_0(org.apache.jsp.AddProducts_jsp:193)
org.apache.jsp.AddProducts_jsp._jspx_meth_s_iterator_0(org.apache.jsp.AddProducts_jsp:157)
org.apache.jsp.AddProducts_jsp._jspx_meth_s_form_0(org.apache.jsp.AddProducts_jsp:112)
org.apache.jsp.AddProducts_jsp._jspService(org.apache.jsp.AddProducts_jsp:69)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:99)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:325)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:245)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:248)

  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2007-04-28 16:35 | soa
是什么问题呢?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2007-04-28 17:00 | soa
不好意思,我有个属性文件放错位置了

解决了:)  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-04-30 16:41 | bruy
第一个简单的例子我这里测试不通过
第一步成功了,界面出来了,Locale那里显示的是en_US
但当我将en_US改为zh_CN提交时,报错:
No result defined for action tutorial.HelloWorld and result input

如果在struts.xml配置改action的input result,则不报错,但提交后还是原来的界面,没有显示预料中的中文

请问这是什么原因呢?   回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-05-08 10:13 | Max
@bruy
你的问题应该是转换或校验出错,所以会返回到输入页面。你可以在输入JSP页面加入<s:actionerror/>,查看出错信息。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-05-10 14:21 | EricaseJang
@bruy
将HelloWorld.java里边的
msg = LocalizedTextUtil.findDefaultText( " HelloWorld " , loc);
这句引号里边的空格去掉  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-05-10 14:27 | EricaseJang
不好意思,好像理解错了……有空格没有错误提示  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-05-10 17:34 | EricaseJang
问个问题:
struts2中的radio、checkbox是不是不能够设置默认选中?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-05-11 09:01 | Max
@EricaseJang
当然可以。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-05-11 11:21 | EricaseJang
怎么实现呢?比如:
<s:set name="male" value="%{getText('sex_male')}"/>
<s:set name="female" value="%{getText('sex_female')}"/>
<s:radio label="%{getText('reg_sex')}" name="Sex" list="#{'1':#male,'0':#female}" />
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-05-11 18:28 | EricaseJang
啊。会了。原来在MAX大大的另一篇里边提到了……
以后一定要看完了全部再提问  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-05-24 10:32 | min
批量封装对象
这个在我的项目中正好用到,谢谢MAX,但是我的项目中需要动态增加记录,意思是增加的对象个数不定,我看你的是只有3条,要是对象个数不定是怎么作呢?
MAX希望在百忙中帮解决一下.我的邮箱:cbz_com0826@163.com  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-06-28 16:31 | fuckjapan(法克哲潘)
好文章啊!谢谢  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-06-29 16:40 | lsmxcool
求救:为什么老是报下面的错,我类已经建好了啊
2007-6-29 16:36:02 com.opensymphony.xwork2.util.XWorkConverter loadConversionProperties
严重: Conversion registration error
java.lang.ClassNotFoundException: tutorial.LocaleConverterat org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1332)at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1181)  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-06-30 23:08 | Max
@lsmxcool
可能是类名输错了  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-07-09 18:10 | 任遨游
在做第二个例子时,productconfirm的execute方法中,取得的products为null,请问是什么原因,报错如下:

type Exception report

message

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

exception

javax.servlet.ServletException
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:515)
org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:419)
org.apache.struts2.dispatcher.ActionContextCleanUp.doFilter(ActionContextCleanUp.java:99)


root cause

java.lang.NullPointerException

  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-07-11 06:17 | petpig
你的文章写得非常不错,对我正在做的项目很有帮助。
最近刚从2.0.6升级到2.0.8后,发现类似如下的代码不能工作了。

<s:iterator value="products" status="stat">

<s:textfield name="%{'products['+#stat.index+'].name'}"/>

.....
</s:iterator>

其中textfield的显示没有问题,但是submit 到 action 时,无法得到products List。 显示 size()=0。 而在2.0.6中没有任何问题。不知道在2.0.8中应如何改写?非常感谢!!!
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-08-01 08:42 | 艺凡♂
严重: Conversion registration error
java.lang.ClassCastException: com.neusoft.softdev.struts2.converter.Product
at com.opensymphony.xwork2.util.XWorkConverter.createTypeConverter(XWorkConverter.java:760)
at com.opensymphony.xwork2.util.XWorkConverter.loadConversionProperties(XWorkConverter.java:778)
at com.opensymphony.xwork2.util.XWorkConverter.<init>(XWorkConverter.java:183)
at com.opensymphony.xwork2.util.AnnotationXWorkConverter.<init>(AnnotationXWorkConverter.java:79)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
at com.opensymphony.xwork2.inject.ContainerImpl$ConstructorInjector.construct(ContainerImpl.java:388)
at com.opensymphony.xwork2.inject.ContainerImpl.inject(ContainerImpl.java:461)
at com.opensymphony.xwork2.inject.ContainerImpl$7.call(ContainerImpl.java:501)
at com.opensymphony.xwork2.inject.ContainerImpl.callInContext(ContainerImpl.java:549)
at com.opensymphony.xwork2.inject.ContainerImpl.inject(ContainerImpl.java:499)
at com.opensymphony.xwork2.config.impl.LocatableFactory.create(LocatableFactory.java:32)
at com.opensymphony.xwork2.inject.ContainerBuilder$4.create(ContainerBuilder.java:134)
at com.opensymphony.xwork2.inject.Scope$2$1.create(Scope.java:49)
at com.opensymphony.xwork2.inject.ContainerImpl$ParameterInjector.inject(ContainerImpl.java:431)
at com.opensymphony.xwork2.inject.ContainerImpl.getParameters(ContainerImpl.java:446)
at com.opensymphony.xwork2.inject.ContainerImpl.access$000(ContainerImpl.java:48)
at com.opensymphony.xwork2.inject.ContainerImpl$MethodInjector.inject(ContainerImpl.java:288)
at com.opensymphony.xwork2.inject.ContainerImpl$2.call(ContainerImpl.java:117)
at com.opensymphony.xwork2.inject.ContainerImpl$2.call(ContainerImpl.java:115)
at com.opensymphony.xwork2.inject.ContainerImpl.callInContext(ContainerImpl.java:542)
at com.opensymphony.xwork2.inject.ContainerImpl.injectStatics(ContainerImpl.java:114)
at com.opensymphony.xwork2.inject.ContainerBuilder.create(ContainerBuilder.java:494)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reload(DefaultConfiguration.java:145)
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:52)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:395)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:452)
at org.apache.struts2.dispatcher.FilterDispatcher.init(FilterDispatcher.java:201)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:221)
at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:302)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:78)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3635)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4222)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:760)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:740)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:544)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:626)
at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:553)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:120)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1022)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:736)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1014)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:448)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:700)
at org.apache.catalina.startup.Catalina.start(Catalina.java:552)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:295)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:433)

在做这第二个例子时出现上述错误,请问Max大哥这是原因?我做第一个例子时用的全局类型转换器就好用,用“类名-conversion.proterties”也到与类相同的包下就不好用,不知道为什么,第二个也一样,但是如果我用全局的就出现上述错误,麻烦Max大哥百忙之中给予回答!  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-08-02 23:42 | Max
@艺凡♂
@petpig
我明天如果有空的话会源代码放到我们的Google讨论组(http://groups.google.com/group/struts2cn)上,到时请留意。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-08-03 09:26 | Max
@Max
源代码已经上传,请到http://groups.google.com/group/struts2cn/web/Struts2_Converter.rar下载。
我是用MyEclipse 5.1.0 GA创建的工程;将文件解压后,将其导入MyEclipse,再加入相应的JAR包即可用。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-08-10 23:26 | binger
@bruy
我一开始和你的错误一样,后来把struts.xml里的文件改成:
<action name="ProductConfirm" class="tutorial.ProductConfirm">
<result>/ShowProducts.jsp</result>
<result name="input">/AddProducts.jsp</result>
</action>

就好了,希望对你有用~.~  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-08-31 17:26 | tf
运行批量封装对象里的例子时我输入错误的数据既然不会提示错误?
请问MAX这是什么原因?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-09-12 17:21 | jarwang
想问一个max,你上边提到的一次发表多个对象.
我仔细看了这段代码.
<s:iterator value="new int[3]" status="stat">
<tr>
<td><s:textfield name="%{'products['+#stat.index+'].name'}"/></td>
<td><s:textfield name="%{'products['+#stat.index+'].price'}"/></td>
<td><s:textfield name="%{'products['+#stat.index+'].dateOfProduction'}"/></td>
</tr>
</s:iterator>
这只能发表三个产品,当然也可是多个,但这要事先固定.
有没有动态的呢?也就说发表多个产品,由使用者自行决定.
还有就是,通否添加,或撤销呢?
比如:原来准备发表3个,但点击到新增页面时发现要发表4个,怎么办?

我现在的做法是用innerHTML+innerCell来解决.
不知道用struts2可否实现???
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-09-13 00:13 | Max
@jarwang
可以,只要在新增的表单项中将name的值递增就行了,如
<tr>
<td><input type="text" name="products[4].name"/></td>
<td><input type="text" name="products[4].price"/></td>
<td><input type="text" name="products[4].dateOfProduction"/></td>
</tr>  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-09-19 10:18 | jarwang
多谢max指教,
原来,只要将name更改一下就可以呀!

不过,数据校检就不能用action实现了.因为是新行是用inserRow+innerHTML来实现动态添加的

而作数据校检时,在提交action后就消失了.为了避免此情况.

我的思路又回到用javascript来做数据校验.

不知道max有什么高招?
多谢!!!
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2007-09-19 13:28 | Spring
@bruy
我也遇到这个问题,第一步界面出来了,Locale那里显示的是en_US
但当我再次提交时,不管是en_US还是zh_CN,都报错(我用的是STRUTS2.0.9):
No result defined for action tutorial.HelloWorld and result input
检查了配置问题都没有问题。
请问此问题你们是怎么解决的?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2007-09-24 15:17 | Jackson
我在运行批量封装对象例子时,输入的日期:2004-6-21,可提交时总出现如下提示:
Invalid field value for field "products[1].dateOfProduction
Invalid field value for field "products[2].dateOfProduction
Invalid field value for field "products[0].dateOfProduction
而无法转到下一页面,究竟是什么原因,有哪位碰到过这个问题吗?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2007-09-24 15:28 | Jackson
上述问题解决了,原因是我在做前面的例子时把浏览器的默认语言改成了英文,改为中文后就可以了!  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-10-26 20:36 | William_00
遇到跟上面petpig一样的问题,请教如何解决?showProducts为什么接受不到addProducts里面的数据?希望能看见max大师的答复  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-10-28 01:33 | wulong
ni
hao  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-11-13 17:27 | WJJ
msg = LocalizedTextUtil.findDefaultText("HelloWorld",loc);
我在类里面测试msg 的值的时候,发现它的值是null。不知道为什么取不到值,请问是怎么回事?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-11-19 16:24 | 游客
@lsmxcool
xwork-conversion.properties文件中=号前后的空格全部去掉就不会出现
java.lang.ClassNotFoundException: tutorial.LocaleConverterat 错误  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-12-05 11:22 | 刘文涛
我按照你的例子做成功了,后来发现删除 :
ProductConfirm-conversion.properties

文件还是能正常工作,很困惑。 为什么删除这个文件还能正常呢?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-12-10 20:55 | hgskj
dhliqw7ei owia  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-12-14 22:57 | jaja
@WJJ
我的也是这情况,不知道如何  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-12-28 16:49 | ElgooG
我在做helloworld时候遇到了这样的问题:第一次能够显示“Hello
World”,但是在textfield中输入“zh_CN‘,后,点击提交之后,页面还是跳转回了”en_US“的页面,这是为什么呢?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-12-28 16:56 | ElgooG
@bruy
兄弟,你的问题解决了吗  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2007-12-31 11:55 | zhjp
java.lang.ClassCastException :com.test.bean.Product cannot be cast to ognl.TypeConverter 请教MAX大哥为什么我的出现这样的错误...  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-01-02 11:37 | javer
不错,好好学习.  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-01-04 00:22 | slyOS
严重: Conversion registration error
java.lang.NullPointerException
at com.opensymphony.xwork2.conversion.impl.XWorkConverter.createTypeConverter(XWorkConverter.java:729)

我在做第一个例子时启动tomcat出现上面错误,是什么原因呢。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-01-04 17:21 | 蒋林
hehe  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-01-04 21:48 | 55
555  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-01-09 13:21 | : 转换器(Converter)——Struts 2.0中的魔术师
微任何金黄人猝然感豆腐花个
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-01-13 12:43 | 小拨
很好
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-01-13 12:44 | 小拨
很好用  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2008-01-15 18:39 | 陈鑫
我回让你很幸福..
不回在让你伤心  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-01-20 12:29 | CLD
刚开始接触STRUTS2.0 怎么第一个就出错了呢,提示:
Invalid field value for field "loc".  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2008-01-28 11:36 | java爱好者
讲得一般!  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-02-14 17:48 | xry
@bruy
我也遇到了相同的问题,不知您是否已经解决,我在页面添加错误显示后,提交显示:Invalid field value for field "loc". 请赐教,谢谢!  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-03-01 13:40 | ttt
uegvf  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-03-05 14:36 | v
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-03-14 17:15 | wjk
我是个初学者,在实现第二个例子的时候出问题了:
Invalid field value for field "products[0].dateOfProduction".
我填的日期是 2007-12-11
怎么解决?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-03-19 20:25 | BruceLee
楼主把STRUTS2的批量保存基本讲清楚了,但我有一个问题就是,如果在刚才那个批量保存里加一个添加新行,应该怎样坐,这在现实开始中是常有的能,我试过用MAKENEW[].VALUE的形式,如果是单纯的添加OK可以通过,如果在编辑部分新加行的话就不能保存,因为编辑部分的名字是"%{'products['+#stat.index+'].name'}"这样的形式,造成同一列却有两个不同的名字,此问题困扰了我很久,希望楼主解答,我邮箱:brucelee365@qq.com谢谢!  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-04-08 19:13 | zdy
你好!

为什么我的时间在英文系统下得不到呢!仍然是字符串,没有自动转换成Date


中文下可以得到!一切正常!

希望得到您的回复!

  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-04-22 16:58 | yiying
您好,我想问一下,在第一个例子中,我只有首次打开页面的时候才可以显示信息,此后不管我选择en_US还是zh_CN,都是显示
No result defined for action tutorial.HelloWorld and result input
如果这样写
private Locale loc = Locale.US;
那样首次打开页面的时候就是英文的
如果
private Locale loc = Locale.CHINA;
那样首次打开页面的时候就是中文的,但是之后我那怕只要点击一下提交,也会显示上面的信息,到底是怎么回事那.

非常感谢


  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-04-23 08:45 | yiying
嘿嘿,问题解决了,xwork-conversion.properties这个文件必须要放在WEB-INF/classes中  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-06-04 11:26 | hover
@Spring
@ElgooG
你们的问题解决了吗?我也是同样的问题  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-07-29 11:18 | tinsoldier
楼主,你在不同的环境下编译过你的代码没有。
你这一节的product对象的例子和之前有一个user对象验证的例子,都会报空指针错误。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-08-19 16:34 | goldgood
我只有一个问题,就是在提交日期字符串时(格式:2005-3-2),传入的是一个空字符。这是怎么回事?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-08-21 01:40 | 繁荣
其实最近真的很开心,但是我没有想到也会有不开心的事发生  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-10-20 10:42 | 似懂非懂
空指针异常:先检查标签是否用错,再检查action中是否有set/get方法,最后是否定义list类型变量的元素类型。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2008-11-03 17:58 | 李言
幸福LOVE玮手语——
真的感觉我们走的越来越远了,好想回到从前,回到拥有他的日子,尽管是那么简单可是心中充满了说不清的爱。因为有爱所以快乐!不知道什么时候才能让心里的爱去放纵,不知道心中的他有没有一丝的感动。
一切都是那么茫然……我不知道该如何面对以后的日子,没有他的日子我该怎么继续,我不敢再去过多的想象,因为我怕,有时候觉得自己好胆小心中的爱都不敢说出口,谁能给我勇气……
想你,爱你,直至老死……   回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2009-01-18 20:44 | shuzigui
java.lang.ClassNotFoundException: tutorial.LocaleConverter ,我运行你的第一个例子的时候出现这个错误,而且不管我选择en_US还是zh_CN,都是显示
No result defined for action tutorial.HelloWorld and result input ,请问一下这是什么原因
  回复  更多评论
  
# 第一个例子的第二种实现方法:应用于某个特定类的类型转换器 2009-02-27 12:01 | chjiangsh
需要修改LocaleConverter.java类的代码:代码片段如下:
else if ( toType == String.class) {
if (value == null) {return null;}
Locale locale = (Locale) value;
return locale.toString();
}  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2009-03-10 15:01 | liu
Conversion registration error
这个错误大家碰到没?
我的配置件都是对的。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2009-08-26 18:02 | david hu
@WJJ

我也是一样,msg为空,取不到值
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2009-10-03 12:04 |
播客不错,非常感谢  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2010-03-08 16:57 |
要想在第一个例子中出字,必须配置国际化资源文件@lxf
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2010-03-09 10:17 |
我觉得这个文件多余,根本不用指定products的元素类型,因为在java文件中已经知道这一点了@刘文涛
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2010-07-28 10:14 | du
网友你好,你这套代码不错,但是那个属性文件,我也加上了,为什么仍然不行啊。
那个属性文件需要别的配置,在那个地文加裁的啊?
我的邮箱:wowgenit@gmail.com
非常期待您的帮助。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2010-07-28 10:18 | du
网友你好,批量封装set集合的时候,怎么老是为空。在jsp里面我用的是makeNew,例:<s:textfield name="fmatInIs.makeNew[1].FdStatus" value="2" />

在网上查的帖子里面都有一个属性文件,要定义一个属性KeyProperty_**=**
这个我也定义了,但在调用action的时候仍然为空。

其它的代码与网上的帖子相同,
批量封装set集合,还有其它的需要注意的地方吗?

我的邮箱:wowgenit@gmail.com
非常期待您的帮助。  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2010-08-20 10:48 | zjnh
对于那些msg为空的同学,我这里有一个解决方法,第一看你的资源文件配置好没有,第二就是看你的msg = LocalizedTextUtil.findDefaultText("HelloWorld",loc)中的那个HelloWorld和你的配置文件中的key一样不一样,只要解决这两个应该就没问题了  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2011-01-17 16:45 |
按上述配置了实例二,可是日期类型无法显示,为什么呢?写一个转换的话,应该怎么写  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2011-03-23 16:07 | zhang
MAX先生能不能解惑下下面这个方法的作用,特别是
“ return new Locale(locale.substring( 0 , 2 ), locale.substring( 3 ));
”句看不大明白,刚学习struts2没几天,希望你能答疑解惑,谢谢
@Override
public Object convertValue(Map context, Object value, Class toType) {
if (toType == Locale. class ) {
String locale = ((String[]) value)[ 0 ];
return new Locale(locale.substring( 0 , 2 ), locale.substring( 3 ));
} else if (toType == String. class ) {
Locale locale = (Locale) value;
return locale.toString();
}
return null ;
}
  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2012-02-15 20:03 | LaozhonG
下面那個例子,也就是一個表單提交多個對象,寫得很好啊!值得借鑒參考!謝謝!  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2013-04-09 10:20 | tang
为什么我怎么改都报错啊  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2013-04-09 10:20 | tang
报这个错:
Error setting expression 'loc1' with value '[Ljava.lang.String;@1b35853'
ognl.MethodFailedException: Method "setLoc1" failed for object com.converter.HelloWorld@839139  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2013-04-09 10:24 | tang
我感觉是因为没有用自定义的转换类转换,因为我在那个转换类中打了个断点,没执行到那  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2013-04-09 16:06 | tang
楼主,你啥时候能回答我啊,我等的好急  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2013-04-09 16:08 | tang
qq:569942960,今天晚上你加我啊  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2013-04-10 10:44 | tang
@yiying
你怎么解决的?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师[未登录] 2013-04-17 14:36 | tang
为啥没人回答了?  回复  更多评论
  
# re: 转换器(Converter)——Struts 2.0中的魔术师 2015-10-09 14:51 | 侯永涛
@lxf
楼主写的不全,他是个SB,  回复  更多评论
  

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


网站导航: