《J2EE设计开发编程指南》(及spring)作者Rod Jhnson也说过类似的话,《J2EE设计开发编程指南》第394页倒数第三行写“这就意味着它们不能被传递给业务对象”,认为这是Struts的ActionForm方法很差(第396页)。我相信,Struts的设计者们也一定面对过这个问题,最后还是保留了现在的做法。所以,关键看开发者如何考虑和处理,而不在于Struts。也就是说开发者可采用现在Struts的折衷办法,因为它带来了许多优点;也可以自己修改一下Struts,使Bean与Struts无关,但同时也失去了Struts数据验证等优点。实际上,ActionForm并不复杂,开发者想修改它或扩展它还是不难的,不用我多说,看看ActionForm源代码就知道了:
package org.apache.struts.action;
import java.io.Serializable;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.upload.MultipartRequestHandler;public abstract class ActionForm implements Serializable {
    protected transient ActionServlet servlet = null;
    protected transient MultipartRequestHandler multipartRequestHandler;
    protected ActionServlet getServlet() {
        return (this.servlet);
    }
       public ActionServletWrapper getServletWrapper() {
           return new ActionServletWrapper(getServlet());
    }
       public MultipartRequestHandler getMultipartRequestHandler() {
        return multipartRequestHandler;
    }
    public void setServlet(ActionServlet servlet) {
        this.servlet = servlet;
    }
      public void setMultipartRequestHandler(MultipartRequestHandler multipartRequestHandler) {
        this.multipartRequestHandler = multipartRequestHandler;
    }
    public void reset(ActionMapping mapping, ServletRequest request) {
        try {
            reset(mapping, (HttpServletRequest) request);
        } catch (ClassCastException e) {
            ;
        }
    }
    public void reset(ActionMapping mapping, HttpServletRequest request) {
        ;       // Default implementation does nothing
    }
    public ActionErrors validate(ActionMapping mapping,
                                ServletRequest request) {
        try {
            return (validate(mapping, (HttpServletRequest) request));
        } catch (ClassCastException e) {
            return (null);
        }
    }
    public ActionErrors validate(ActionMapping mapping,
                                 HttpServletRequest request) {
        return (null);
    }
}

解决方案 »

  1.   

    使用引用嵌套类呀
    public class Contact{
    private String name;
    private String address;
    ......
    }
    对于
    ContactForm
    类,可以这么来写:
    public class ContactForm extern ActionForm{
         Contact  contact = new Contact();
    }那么在页面上:可以这么写:
    <input type="text" name="contactForm.name" value="">contactForm 为你在struct-config.xml文件中,
    action 指写的formBean的name.
      

  2.   

    to liaowufeng:
    我现在的做法和你提的是一样的,但问题是ContactForm还要写一堆的getter,setter.
    to kui:
    我觉得改写struts的实现代码不是个好的方案,这样你的代码就难兼容了.
      

  3.   

    关键是View层的数据并不一定是和业务层数据对应的,所以Contract和ContractForm实际上是没有任何关系的两个类,让它们之间用用继承关系是一个非常糟糕的设计!至于认为setter和getter麻烦完全可以使用代码生成技术来做。
      

  4.   

    尝试一下动态form 在Action中:DynaValidatorActionForm form = (DynaValidatorActionForm) actionForm;得到动态表单,这样就不用写你的ContactForm了
      

  5.   

    DynaActionForm和request中的键值对的方式有什么区别吗?
      

  6.   

    ActionForm的优劣是仁者见仁,智者见智了...
    一般来说ActionForm起了1到防火墙的作用...
    使web层的数据经过过滤传到Action
    一般ActionForm也可以当作一个VO来使用
    我的做法是
    jsp-->ActionForm-->vo2po工具(自己写)--->domain object-->pesistent layer
    反向
    pesistent layer -->domain object -->BeanUtils工具-->ActionForm-->jsp(配合标签库)
      

  7.   

    你的那个Contact我想应该是个po吧。而struts中的actionform其实是个dto也就是个vo。它应该只道业务层(biz)。你可以在bissiness层吧vo转成po,千万不要怕麻烦。vo和po是在概念上完全不同的东西,也许有时候vo其实和po在结构上是相同的,但是请不要为了简单把po直接传到view层了,那样就破坏了分层的架构,在后期维护的时候会很麻烦。
      

  8.   

    core j2ee patterns中不是提出了一个解决方式吗
    就是把你的contact实现为接口,然后ActionForm继承这个接口
    这样虽然getter、setter免不了还要重复写(就是接口中的无需实现罢了),但程序结构上好一些
      

  9.   

    我的想法是,
    Contact未必就是PO,Contact可以认为是M层提供给C层和V层的业务接口(虽然它的表示是个bean).所以我认为让Contact来直接作为ActionForm未必就是不好的设计,这样相当于我在V层使用了M层的Contact接口.当然,Polarislee(北极星)说的也有道理
    另,谢谢大家的热情参与
      

  10.   

    晕,你干脆把Contact去掉直接都用ContactForm或者,让Contact继承ContactForm不就结了,虽然逻辑上有点不通,但还是可以在Struts下解决问题的
      

  11.   

    我觉得还是现有的structs结构好,本来两个类完成的是不同的工作,非要搞在一起干什么。
    用户界面上显示的数据项和数据库中保存的数据结构有时会差得很多,放在一起只会增加代码的复杂性,增加维护的难度。即便是今天你看到的是一样数据结构的,但你的用户对界面会提出很多修改意见,form中的数据项可能要经常调整,如果按你的想法设计,有些调整会对你的model带来很大的影响。
      

  12.   

    to javacomte(基督山伯爵) 
    这样虽然可以解决问题,但是却破坏了软件层次,最后搞的层次不清
      

  13.   

    这个问题还用说么!po和vo 不要混着用 。大不了做一个互相转化的工具就行了被。不要宁要代码的简化 而破坏软件的层次和结构!
      

  14.   

    这些赋值动作,完全可以使用commons-beanutils来简化。可以节省不少工作量
      

  15.   

    支持 liaowufeng(liaowufeng) 的用法,我也这样用过.
      

  16.   

    1.用动态form,直接把action form 省掉,非数据库字段的在action请求多一次
    2.liaowufeng(liaowufeng)的用法,也是非数据库字段的在action请求多一次,对应get,set方法.
    加上Contact对象 这两种方式我都用过,觉得思路还算清析,也不会态多重复代码啊!!