`
jakoes
  • 浏览: 68058 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

struts1.x源码赏析-action是线程安全性讨论 

阅读更多
经过对struts1.x源码的研读发现:
struts1.2获取action的方式是单例的,所有的action都被维护在一个hashMap里,当有请求到达时,先根据action的名称去hashMap里查找要请求的Action是否已经存在,如果存在,则直接返回hashMap里的action。如果不存在,则创建一个新的Action实例。


下面我们来分析一下源码:

请求到达ActionServlet时,首先会到达doGet()或doPost()方法,而ActionServlet转给了process()方法进行统一处理


    public void doPost(HttpServletRequest request,
               HttpServletResponse response)
        throws IOException, ServletException {

        process(request, response);

    }





而process()方法又会转给processor的process()方法进行处理

    protected void process(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {

        ...
        processor.process(request, response);

    }




processor的process()方法里经过一系列处理后,最后通过processActionCreate方法来返回一个具体的action实例


public void process(HttpServletRequest request,
                        HttpServletResponse response)
        throws IOException, ServletException {

        ...

        // Create or acquire the Action instance to process this request
        Action action = processActionCreate(request, response, mapping);
        if (action == null) {
            return;
        }

     ...

    }




那我们就到processActionCreate这个方法里去一窥究竟吧:
1、先获取类名
2、根据类名去一个名为actions的map里查寻实例是否已经存在
3、如果存在,则直接返回
4、如果不存在,则创建一个新实例
5、把创建好的action放到map里备用

  
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();//1、先获取类名 
        ...
        Action instance = null;
        synchronized (actions) {

            // Return any existing Action instance of this class
            instance = (Action) actions.get(className);//2、根据类名去map里查寻实例是否已经存在
            if (instance != null) {
                return (instance); //3、如果存在,则直接返回
            }

            // Create and return a new Action instance
            //4、如果不存在,则创建一个新实例
            instance = (Action) RequestUtils.applicationInstance(className)

            instance.setServlet(this.servlet);
            actions.put(className, instance);//5、把创建好的action放到map里
        }
        ...
        return (instance);

    }



我们再来看看actions的定义:

    /**
     * The set of Action instances that have been created and
     * initialized, keyed by the fully qualified Java class name of the
     * Action class.
     */
    protected HashMap actions = new HashMap();


结论:
struts1.x里的action是单例模式的,供多个请求共享。所以不是线程安全的。
其数据都通过actionForm进行传递。
因此,action实例里面不应该声明带有状态的实例变量
分享到:
评论
8 楼 theoffspring 2012-05-20  
谢谢分享,看来说Action Servlet这个不是线程安全的不准确,应是action是线程不安全的
7 楼 askyuan 2010-07-11  
什么Struts2这些,哎,新事物不一定就好啊。。。Servlet成就了Java web,而Struts1把Java web燃烧起来了,Struts2就是给Struts1擦屁股。。。大项目还是用类似于Struts1这样的基于Servlet封装的框架
6 楼 steafler 2010-07-11  
唉,过时东西了,老夫一开始就知道他是不安全,结果你却偏要弄个标题是安全的,还以为老夫这么多年都犯错了
5 楼 beijing2009 2010-07-11  
protected transient ActionServlet servlet
The servlet to which we are attached.
struts文档中这样说,有一个属性字段,这个actionservlet将附加给这个action
4 楼 murainwood 2010-07-11  
楼主,你穿越了?
3 楼 skydream 2010-07-11  
晕倒,还以为时空倒流了。

逐个问题03,04年的时候就讨论过很多的,struts1的基本常识。
2 楼 chrisx 2010-07-11  
就是说action里只能有方法不能有属性,因为是单利模式
所以说struts2与spring集成时,action必须定义成非单利模式的bean,因为form都是在action里的
1 楼 beijing2009 2010-07-11  
action实例里面不应该声明带有状态的实例变量。
能举个例子么?

相关推荐

Global site tag (gtag.js) - Google Analytics