论坛首页 Java企业应用论坛

struts不好吗,为什么总有人骂她.

浏览 39153 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-04-27  
zhanggok 写道
struts是免费,开源的总比自己编一个框架要容易,如果认为有不好可以自己改,开源就是为了让大家发现错误,好变得更完整.

你这种想法太幼稚了。如果是因为这个框架本身存在着设计上缺陷,那就不是改一两段代码能解决问题的了。
0 请登录后投票
   发表时间:2004-04-28  
sunheat 写道
这是你自己的问题好伐?request里当然能放对象,你要自己进行同步访问控制呀!


这怎么是我的问题呢? 我当然知道request能放对象
但我为什么要自己进行同步? 这应该是框架替你完成的事情。

sunheat 写道
这不是Struts发明的问题,Servlet模型就是这样的!


我也没说这是struts发明的,你自己也说这是问题嘛~

sunheat 写道
这是为了提高性能。


为了提高性能,就应该把每次都不同的request,response,mapping,form给共享的action, 因此在action中所有的方法带有request才能保证不会出现同步问题吗?

我不需要struts帮我提高这一点点性能,
我可以优化业务逻辑的性能,比action这一点点性能有效的多
effective java中说,性能优化的诀窍是:不优化。

不要总拿性能来说话。 我认为代码的复用,可读性,简单性等,比性能更重要

我们比较一下:
webwork,String execute()方法,多简单。
struts,ActionFoward execute(ActionForm form, ActionMapping mapping, ServletRequest  request, ServletResponse response)

看多了不头疼吗。

sunheat 写道
每个request都新建一个实例,那不是历史到退回到CGI了!


新建一个Action,不过就是新建了一个对象而以。 你在业务逻辑里面建立了多少个对象? 每次select 一些数据,不是每条记录对应的建立一个对象么?

CGI也不是没有可取之处,不是历史倒退,而是从历史中吸取经验。

我现在仍然在项目中用struts,使用的原因不是因为它好,而是因为它泛滥。
文档多,使用的人多,因此今后想要找人继续开发或维护我这个项目的话更容易找。
0 请登录后投票
   发表时间:2004-04-28  
我没用过,
看到学的人还挺多,
拿不准,该怎么学,得有人带吗,


从何入手呢
0 请登录后投票
   发表时间:2004-04-29  
冰云 写道
现在有深切体会!!

struts,嘿,好死不死的偏要学servlet的初始化方法。
一个Action只有一个实例。

这下可好,由于所有的线程共享一个Action,所有的与请求有关的参数,都要通过execute(xxxxx)传递到方法中。

以前还好,凑合用。可现在用IOC了,还怎么继续用这样的烂接口?

为了保证不会在多线程情况下处问题,你不能保存request,response实例,需要用的话就得一个个传递到别的函数中,造成了函数签名污染

而webwork不是这样。它是对每一个Thread创建一个Action(应该是)

tapestry和jsf等,和action更是不同,根本就没有了显式的request,COP~~虽说问题也是多多。

不过,总的比较起来,我还是倾向于webwork而不是struts。 至于tapestry,嘿嘿,希望等下一版本呢


如果你不喜欢Struts的传统处理模式,希望每个请求用一个独立的action对象来处理的话,可以这样:
public abstract class BaseAction extends Action
{
       public ActionForward execute(......);
       {
             BaseAction action = (BaseAction);this.getClass();.newInstance();;
             return action.doExecute(......);;
       }
       
       protected abstract ActionForward doExecute();;
}

public class ActionA extends BaseAction
{
     .....

     public ActionForward doExecute(....);
     {
              ............
              return mapping.findForward(.....);;
     }
}


这样线程间就不会相互干扰。

同理,如果想像WW2那样通过ActionContext得到request,而不用老是要通过传参的方法得到request,也只要在BaseAction里把Action放到ThreadLocal里,然后写一个类似ActionContext的辅助类就可以实现了。

当然这只是为了弥补Struts的缺陷而已,我自己也是偏向使用WW2的。
0 请登录后投票
   发表时间:2004-04-29  
楼上的说得好~ 这点我没想过~ GOOD
我试试看 呵呵~
0 请登录后投票
   发表时间:2004-05-01  
好多的时候,打火机不行的时候用用火柴也不错.
0 请登录后投票
   发表时间:2004-05-03  
使用struts开发项目的一点体验:
struts是一个框架,顾名思义就是一个架子(容器),需要我们往里填充东西,可以加入很多现成组件、标签库以及一些新技术,可以大大加快开发进度和保证软件质量。它的清晰的框架结构和mvc设计模式使程序结构非常清晰,更易于理解和学习。当然它把mvc的各个层次分的非常清楚可能会使以前一直使用jsp开发的初学者感觉繁琐,同时它的FormBean和Model部分可能会增加代码量,但是正是这些使程序更易于理解,同时在开发过程中根据实际需要开发一些辅助开发工具使很多固定模式的代码根据配置自动生成将可大大减少代码的编写量,并可减少出错。当然我们学习它,不仅要会用它,更重要的是要理解它的设计思想和实现思想,我们更重要的是要得到“渔”,通过掌握它,学别的框架就会更快,也更容易理解。
0 请登录后投票
   发表时间:2004-07-17  
sunheat 写道
冰云 写道
现在有深切体会!!

struts,嘿,好死不死的偏要学servlet的初始化方法。
一个Action只有一个实例。

这下可好,由于所有的线程共享一个Action,所有的与请求有关的参数,都要通过execute(xxxxx)传递到方法中。

以前还好,凑合用。可现在用IOC了,还怎么继续用这样的烂接口?

为了保证不会在多线程情况下处问题,你不能保存request,response实例,需要用的话就得一个个传递到别的函数中,造成了函数签名污染

而webwork不是这样。它是对每一个Thread创建一个Action(应该是)

tapestry和jsf等,和action更是不同,根本就没有了显式的request,COP~~虽说问题也是多多。

不过,总的比较起来,我还是倾向于webwork而不是struts。 至于tapestry,嘿嘿,希望等下一版本呢


这是你自己的问题好伐?request里当然能放对象,你要自己进行同步访问控制呀!这不是Struts发明的问题,Servlet模型就是这样的!这是为了提高性能。每个request都新建一个实例,那不是历史到退回到CGI了!


对不起。我是偶尔翻看Javaeye的论坛,发现这个贴子的。
我并不是好为人师,只是恰好知道这方面的一些东西。希望能够对大家有所帮助。

我要说明的是,其实,这个贴子里讨论的问题(关于action,request,thread)其实根本不存在。这也意味这个贴子里后面的很多问答都不成立。
所有的争论其实都是基于一些误解的基础上。
我希望能够帮助澄清这些误解。

1. 关于Struts Action的误解
Struts Action是为每一个Request对应一个Action实例的。并没有共享同一个Action实例。只是使用了pooling技术,可以回收用完的Action实例,以备为下一个Request使用。

Struts源代码
org.apache.struts.action包,RequestProcessor类。

    /**
     * Return an <code>Action</code> instance that will be used to process
     * the current request, creating a new one if necessary.
     *
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     * @param mapping The mapping we are using
     *
     * @exception IOException if an input/output error occurs
     */
    protected Action processActionCreate(HttpServletRequest request,
                                         HttpServletResponse response,
                                         ActionMapping mapping);
        throws IOException {

        // Acquire the Action instance we will be using (if there is one);
        String className = mapping.getType();;
        if (log.isDebugEnabled();); {
            log.debug(" Looking for Action instance for class " + className);;
        }
        
        Action instance = null;
        synchronized (actions); {

            // Return any existing Action instance of this class
            instance = (Action); actions.get(className);;
            if (instance != null); {
                if (log.isTraceEnabled();); {
                    log.trace("  Returning existing Action instance");;
                }
                return (instance);;
            }

            // Create and return a new Action instance
            if (log.isTraceEnabled();); {
                log.trace("  Creating new Action instance");;
            }
            
            try {
                instance = (Action); RequestUtils.applicationInstance(className);;
                // TODO Maybe we should propagate this exception instead of returning
                // null.
            } catch (Exception e); {
                log.error(
                    getInternal();.getMessage("actionCreate", mapping.getPath(););,
                    e);;
                    
                response.sendError(
                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                    getInternal();.getMessage("actionCreate", mapping.getPath();););;
                    
                return (null);;
            }
            
            instance.setServlet(this.servlet);;
            actions.put(className, instance);;
        }

        return (instance);;

    }


2. 关于Thread的误解

这个误解相当常见。
我们说一个方法是否是线程安全的,判断的标准只有一个,
这个方法是否访问了 可以写的“成员变量”。(所谓的state)
注意,只有两个条件:
  (1)可以改变的  (2)成员变量
如果访问了可以写的“成员变量”,那么这个方法不是 线程安全的。
如果没有访问 可以写的“成员变量”,那么这个方法是 线程安全的。

方法的线程安全特性和传进来的参数毫无关系。
举个例子说明,为什么和参数毫无关系。

public class A {
   // 这个方法没有访问任何成员变量,本身是线程安全的。
   public void changeBuf(StringBuffer buf);{
      buf.append("aaa");;
   }
};

公用变量
public class Common{
   public static StringBuffer buf = new StringBuffer();;
}

Thread 1的代码:
A a1 = new A();;
a1.changeBuf(Common.buf);;

Thread 2的代码:
A a2 = new A();;
a2.changeBuf(Common.buf);;



我们看到,这个Common.buf还是存在共享冲突。
但这个不是A.changeBuf()方法的问题,而是调用这个方法的问题。
而且,我们看到,这里的线程安全和是否共享实例根本就没有关系。
你就是创建1000个线程,分别调用1000个不同的实例,这种调用方法还是线程不安全。
结果和这1000个线程,都调用同一个共享实例的结果,没有任何区别。

这就是说,只要你不在Action类里面声明可写的成员变量,那么多个Request使用一个共享Action,还是分别使用不同的Action,结果完全一样。
(这种情况基本没有,因为Servlet,Action就是Stateless的,没有理由声明 可写的成员变量)

类和Object实例的基本概念:
同一个类的每个Object Instance都有自己的"成员变量备份",但是所有的Object Instance都共享同一份Java代码,不管这个方法是static method还是instance method.

线程的基本概念:
每个线程有自己的运行栈。线程只在自己的运行栈上运行方法。线程只和类的方法(method)有关。线程并不和任何具体Object实例有直接关系。

由于这个问题涉及的概念比较复杂,如果有疑问,
我可以举更多详细的例子,一步一步地说明所有问题。
因为这个误解太普遍了。不解决这个误解,很多问题的讨论都是南辕北辙,根本不成立的。

(3)关于Request的误解。
我想,这个Request应该是说HttpRequest这个参数。
我想要说明的是,根据基本常识,这个HttpRequest这个参数绝不可能被共享。

我查阅了好久Tomcat的源代码,但没有找到相关的从Socket连接生成Request的代码。所以,不能提供有力的证据。只能根据常识下这个判断。

希望有了解Tomcat源代码的高手,能够指教。
0 请登录后投票
   发表时间:2004-07-22  
buaawhl果然渊博,不过我想冰云只是想说:他的pico不好用了
0 请登录后投票
   发表时间:2004-07-27  
我还是坚持我的观点。不用的框架没有优略只分。只是更使用于某个应用领域罢了。何必要找到一个万金油呢。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics