随笔 - 63  文章 - 0  trackbacks - 0
<2009年4月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

常用链接

留言簿(2)

随笔分类

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

       Action类是用户请求和业务逻辑之间的桥梁,每个Action充当客户的一项业务代理。在RequestProcessor类预处理请求时,在创建了Action的实例后,就调用自身的processActionPerform()方法,该方法再调用Action类的execute()。
Action的excute()方法调用模型的业务方法,完成用户请求,然后根据执行结果把请求转发给其他合适的WEB组件。

一、Action类缓存

      struts应用的生命周期中RequestProcessor只保证一个Action实例,所有的客户请求都共享这个实例.所有请求可以同时执行它的excute()方法。RequestProcessor类包含一个HashMap,作为存放所有Action实例的缓存。每个Action实例在缓存中存放的key为Action类名。在RequestProcessor类的processActionCreate()方法中,首先检查在HashMap中是否存在Action实例,如果有直接使用,否则创建一个新的。创建Action实力的代码位于同步代码块中,以保证只有一个线程创建Action实例,然后放在HashMap中。供其他线程使用。
如下代码
  • 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);   
  •       }   
  •   
  •       // :TODO: If there were a mapping property indicating whether   
  •       // an Action were a singleton or not ([true]),   
  •       // could we just instantiate and return a new instance here?   
  •   
  •       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);   
  •   
  •   }  

     

    二.创建支持多线程的Action
    1.什么是线程安全的代码
    在多线程环境下能正确执行的代码就是线程安全的。
    安全的意思是能正确执行,否则后果是程序执行错误,可能出现各种异常情况。

    2.如何编写线程安全的代码
    很多书籍里都详细讲解了如何这方面的问题,他们主要讲解的是如何同步线程对共享资源的使用的问题。主要是对synchronized关键字的各种用法,以及锁的概念。
    Java1.5中也提供了如读写锁这类的工具类。这些都需要较高的技巧,而且相对难于调试。

    但是,线程同步是不得以的方法,是比较复杂的,而且会带来性能的损失。等效的代码中,不需要同步在编写容易度和性能上会更好些。
    我这里强调的是什么代码是始终为线程安全的、是不需要同步的。如下:
    1)常量始终是线程安全的,因为只存在读操作。
    2)对构造器的访问(new 操作)是线程安全的,因为每次都新建一个实例,不会访问共享的资源。
    3)最重要的是:局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量。

    Servlet是在多线程环境下的。即可能有多个请求发给一个servelt实例,每个请求是一个线程。 struts下的action也类似,同样在多线程环境下,你也必须编写线程安全的Action类。
    保证线程安全的原则就是仅仅使用局部变量,谨慎使用实例变量(拥有状态的实例,尤其是拥有业务对象状态的实例). 如果要用到那些有状态的实例,唯一和最好的办法是在Action类中,仅仅在Action类的execute()方法中使用局部变量,对于每个调用execute()方法的线程,JVM会在每个线程的堆栈中创建局部变量,因此每个线程拥有独立的局部变量,不会被其他线程共享.当线程执行完execute()方法后,它的局部变量就会被销毁.
    如果Action类的实例变量是必须的话,需要采用JAVA同步机制(synchronized)对访问共享资源的代码块进行同步


    三、Struts的几种Action
    Struts提供了一些现成的Action类,直接使用可以大大节省时间,如下
    ForwardAction
    可以转发到其他web组件,仅仅提供一个转发功能,不作处理。
    IncludeAction
    包含其他web组件。
    DiapatchAction
    通常一个Action只完成一个操作,用这个Action可以完成一组相关的操作。
    LookupDispatchAction
    他是DiapatchAction的子类,也可以定义多个方法,但主要用于一个表单里有多个按钮,而这些按钮又有一个共同的名字的场合。
    SwitchAction
    用于子模块之间的切换。


    四.ActionForward类
    Action类的excute()方法返回一个ActionForward对象,它代表了web资源的逻辑抽象,这里的web资源可以是jsp页面、Java servlet、或Action
    从excute返回ActionForward可以有两种方法。
    1) 动态创建一个ActionForward实例
    return new ActionForward(”Failure”,”login.jsp”,true);
    2) 调用ActionMappin实例的findForward方法
    这个方法先从action级别找,然后在<global-forwards />级别找
    return mapping.findForward(“Failure”);

  • posted on 2009-04-05 11:19 lanxin1020 阅读(180) 评论(0)  编辑  收藏 所属分类: struts1

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


    网站导航: