你说的control主要是指Action吧。关于多control的问题,一个JSP页面或页面中的其中一个user-case,不一定要对应一个自己独有的Action(即不一定要一一对应),在许多场合是可以共用一个Action,是否共用主要是看所需要实现的功能是否相近以及设计者所规划的系统结构。关于代码的共用问题,上面说的共用一个Action可以实现部分代码的共用。另外,通过扩展自己的Action基类,是一种代码共用实现方式;把共用代码封装在一个独立的类中也是一种代码共用实现方式;采用插件也是一种代码共用实现方式。具体采用什么方式,不同情况采用不同方法,但一定要规划好。关于是否复合MVC或Struts规范的问题,可以根据项目的需要,结合标准的MVC和Struts规范,在前期工作中制定项目自己的规范。规范是人制订的,规范也是一样,没有创新就不会有进步。
关于是否复合MVC或Struts规范的问题,可以根据项目的需要,结合标准的MVC或Struts规范,在前期工作中制定项目自己的规范。规范是人制定的,规范也是一样,没有创新就不会有进步。

解决方案 »

  1.   

    省是可以省一些啊那些和structs没有关系了,看你个人代码的功底了
      

  2.   

    kui的 “另外,通过扩展自己的Action基类,是一种代码共用实现方式;把共用代码封装在一个独立的类中也是一种代码共用实现方式。”-----------------------------------------这种方法不错,在许多项目实践中也确实是这么做的,俺们公司一些大项目基本上都是在原有的框架上再抽象封装一层,这样一来Action多了不要紧,但是只要分好包,例如每一个case单元一个包,也是很容易管理的,而且框架建起来之后,代码量就非常小了。像俺们公司的一些大项目,直接使用ant根据框架的要求生成一堆基础代码,然后剩下的工作就是填充业务逻辑了,说白了就是SQL和变量常量声明、getAttribute和setAttribute。Struts是一个非常灵活的框架,不需要受太多条条框框的束缚,其实Struts本身是否严格遵循了MVC的概念,还是一个有争议的问题。
      

  3.   

    一个action里面只有一句话
    这种情况为什么还要写一个action,麻烦。看情况而定,所有东西都不是宝典,万能药,要看项目情况,要灵活
      

  4.   

    一个action里面只有一句话
    这种情况为什么还要写一个action,麻烦。==============================================================================
    举个例子,比如
    Order order=orderService.findById(id);
    return mapping.findForward("success");这里只有一句调用查找order的service,但是不能不写。
    也不能不在control里面写,因为我要处理异常的。那么这种一句话的control可能大量存在。这里是order,那里就是item,还可能有user...
    而且这种连复用都困难。当然这种查找在实体少的时候可能不多,那么这种情况就多了:
    Order order=orderService.findById(id);
    someMethod();
    return mapping.findForward("success");下一次可能是:
    Order order=orderService.findById(id);
    otherMethod();
    return mapping.findForward("success");
    再下一次是another...各位认为这种有办法复用吗?提取函数?我这里是两句话而已,你提取函数还不如直接写。这种太简单了,如果光写几个函数当然不麻烦。
    但是struts要写配置文件的,control自然就多了。可能各位认为把这些control合并一下能够ok。比如引进一个参数就可以根据参数来判断。
    比如
    Order order=orderService.findById(id);
    if(param=="a")
       someMethod();
    else
       otherMethod();看起来很美,那么如果这些还加上安全控制呢?
    比如someMethod和otherMethod是不同权限用户的呢?
    要么就加上权限控制。
    如果是分离的control我可以写filter,可以控制一群control的权限。
    而这种,我要把权限代码嵌入到someMethod和otherMethod的前面。
    我认为control的复用太困难了。而且各位提到的方法,我也试过,但是一旦出现control改变的情况,可能你辛苦建立的复用机制一下就瓦解了。
    打个比方:
    管理员修改用户信息和用户修改自己的信息,在代码上是差不多的。只是权限验证不同。
    我们可以复用修改代码,甚至是修改页面的代码。但是管理员由于业务变化可能要修改以前不需要修改的信息,这样管理员的代码就要变化了,得重新写。后来用户又需要修改另一个以前不需要改的信息。这样两边的代码都发生了变化,甚至完全不相关了。
    那么建立起来的重用机制不是没用了吗?在实际系统中由于可能是在不同的角色之间的control进行复用,那么这种复用可能相当不稳定。因为无法预期哪个角色会改变。A角色和B角色可能现在用例90%相似,我们复用这90%,后来可能业务改变只有50%,最后下去可能1%都没有了。
      

  5.   

    这是程序设计中的“鱼和熊掌”的问题。通常是采取了折衷的方案,以“一个页面对应一个Action,如果同一个页面内有多个事件,同页面不同事件共用一个Action”为基础,当不同的Action中的相近代码或功能确实较多的情况下,通过扩展自己的Action基类,或把共用代码封装在一个独立的类中,以实现代码的共用。采用“一个页面对应一个Action”为基础,主要是考虑到一是加强程序的可读性和可维护性;二是考虑到方便于在可视化设计系统中(例如JavaWebstudio等)采用文件向导自动生成代码以及方便实现可视化设计。不同的程序员采用的方式都会有些差别,上述问题不会有统一的答案。
      

  6.   

    那么是否可以认为control这一层和业务的耦合是非常紧密的。
    我个人认为,一旦业务发生改变,比如流程改变,那么control很可能改动是非常大的。我们分离view和control更多的是为了将view独立的进行设计,而实际上一旦表示层要变化,
    control很可能要变化,一旦control要变化,表示层也可能要变化。
      

  7.   

    业务逻辑应该封装到业务逻辑层,而绝非Action,这是很浅显的道理。
      

  8.   

    不要被具体的技术牵着走, 在Action中做业务是Struts设计的初衷, 也可以在此基础上做你自己的封装.业务逻辑复杂后, 造成业务不能使用只能说是设计不够周全, 设计师不是特别精通业务造成的, 即时不是Struts估计改动也是很大的.精通业务才是可复用设计的关键.
      

  9.   

    在JSP版发的一篇东东,使用1个control的一点小技巧^_^今天无意中看了一点JPetStore的源代码,发觉他的一些
    用法很值得讨论。。
    JPetStore是1个完全的使用OpenSource的demo,
    使用了Struts+IBATiS,IBATiS也是1个持久层框架。嘿嘿,以前不是有
    j2ee版本的PetStore的demo吗?^_^JPetStore的设计令我眼前一亮的居然只使用了1个Action,注意不是ActionServlet,当然
    Struts当然只使用1个前置控制器关键代码
    if (form != null) {        // Explicit Method Mapping
            Method method = null;
            String methodName = mapping.getParameter();
            if (methodName != null && !"*".equals(methodName)) {
              try {
                method = form.getClass().getMethod(methodName, null);
                forward = (String) method.invoke(form, null);
              } catch (Exception e) {
                throw new BeanActionException("Error dispatching bean action via method parameter ('" + methodName + "').  Cause: " + e, e);
              }
            }        // Path Based Method Mapping
            if (method == null && !"*".equals(methodName)) {
              methodName = mapping.getPath();
              if (methodName.length() > 1) {
                int slash = methodName.lastIndexOf("/") + 1;
                methodName = methodName.substring(slash);
                if (methodName.length() > 0) {
                  try {
                    method = form.getClass().getMethod(methodName, null);
                    forward = (String) method.invoke(form, null);
                  } catch (Exception e) {
                    throw new BeanActionException("Error dispatching bean action via URL pattern ('" + methodName + "').  Cause: " + e, e);
                  }
                }
          
    这是这个BeanAction的关键代码,当然这个BeanAction是继承Action的,和普通的Action没什么2样
    这也是所有的请求所调用的Action....Cool....这时要先说说JPetStore里的ActionForm的设计,在JPetStore里Form取名为XXXBean,咋1看很令人奇怪..
    仔细看,每个具体的XXXBean都继承了一个BaseBean,而这个BaseBean则继承了ActionForm,而这个
    XXXBean引用了domain域对象(与数据库字段是对应的),同时,在XXXBean里添加了调用DAO的方法,例如
    Insert,update等操作,成了1个名副其实的BO,同时,这些方法都是无参的,因为使用的参数都可以从
    Bean自生的字段取得,同是这也是关键的部分^_^来看一段Struts-config.xml里配置
    <action path="/shop/viewItem" type="com.ibatis.struts.BeanAction"
          name="catalogBean" scope="session"
          validate="false" input="/catalog/Product.jsp">
          <forward name="success" path="/catalog/Item.jsp"/>
    </action>奇妙的地方在于,这个path的viewItem这部分是catalogBean里的一个方法名,这时你可以回头去看
    这个BeanAction,他使用反射的原理,通过Form(其实成了1个BO)和 URL来定位调用的方法。写了1大段,^_^,感觉到灵活运用框架是多么重要,不要拘泥与某些固定的用法....DEMO的主页,有兴趣的朋友可以去看看
    http://www.ibatis.com/jpetstore/jpetstore.html
      

  10.   

    fantasyCoder(JC★牛仔) :
    我看过jpetstore的代码,我不欣赏这种写法。准确来说,这种设计是基于petStore本事业务简单的情况。更复杂的情况呢?
    这种写法是无法通用的,也就是说如果petStore可以这么写,其他的应用呢?
    如果不能通用的解决,那么这种解决方案是没有多少实际意义的。并且我认为jpetstroe的这种结果是重构的结果,而不是事先设计的结果。
    另外我感觉jpetstore的control和service紧耦合的。我需要一种比较通用的方案,至少是能够大多数情况下使用的方案。
    比如设计模式就是大多数情况下可以使用的方案,而jpetstore的方案是不行的。即使是可以,那么将已经存在的项目重写成这个模式需要非常大的耗费。
      

  11.   

    EN...
    同意你的想法....
    JPetStore只是为了回击dot net版的petstore的
    简单应用,说白了是1个HelloWorld的web应用...
    他的ActionForm积聚膨胀为一个行数据入口(在Matin Fowler的企业应用架构模式中
    提到过)并且调用了DAO层的接口...确实在业务复杂的情况下是不能取用的....
    他只是一个较为灵活的设计(至少我这么认为),在设计Struts的Action时又给了我们1个
    想法..你也可以保留ActionForm的简单性,独立出原来膨胀的ActionForm为1个domain object
    就是一个ActionForm 对应一个 domain object
    那么使用这个[单Action]模式是能分离control和service偶合的....
      

  12.   

    同时jpetstore的这个实现方式,并没有解决我所提到的问题。
    它简化了control的设计,但是这只是在struts1.2没有出现之前。struts1.2要实现同样的能力不用费那么多劲的。
      

  13.   

    重复是比较罪恶的,我也比较痛恨。对于,多个Action 99%相同的..
    我会先 absloute class MyAction extends Action(){}  ,然后再 让具体的Action extends MyAction()......
      

  14.   

    ^_^ to totodo:
    Action一般不会有多大的相似之处吧。。?
    一般抽象出MyAction是做权限处理的比较
      

  15.   

    抽象出来的Action能做好多事情. ,不过具体也是要看系统要求了..象 liujiboy(liujiboy) 那么多故事的,就应该这样子了.  
      我一般会把control 中每次都要记录的Session的User信息, 操作日志记录,用户认证, actionError(这里是.GLOBAL_ERROR),还有linsence 的验证等等啦..
     这些在每个Action里都要写得,于是抽象之. 也不单可以抽象一两层,可以好多多的..看系统了.