Action类是用户请求和业务逻辑之间的桥梁,每个Action充当客户的业务代理,在RequestPorcess类预处理请求时,创建了Action的实例后,就调用自身的processActionPerform()方法,该方法再调用Action类的execute()方法。
1. Action类缓存
为了确保线程安全(thread-safe),在一个应用的生命周期中,Struts框架只会为每个Action类创建一个Action实例,所有的客户请求共享同一个Action实例,并且所有请求的线程可以同时执行它的execute()方法。
RequestProcess类包含了一个HashMap,作为存放所有Action实例的缓存,每个Action实例在缓存中存放的属性key为Action类名。在RequestProcess类的proceeActionCreate()方法中,首先检查在HashMap中是否存在Action实例,如存在,就返回这个实例,否则,就创建一个新的实例。创建Action实例的代码位于同步代码块中,以保证只有一个线程创建Action实例。一旦线程创建了Action实例并把它存放到HashMap中,以后所有的线程都会直接使用这个缓存中的实例。
在Java API中,java.util.Vector和java.util.ArrayList都是集合类,java.util.Hashtable和java.util.HashMap都是Map类,其中,Vector和Hashtable的存取元素的方法采用了Java的同步机制,而另两者没有使用。同步机制可以有效地避免共享资源的竞争,但是滥用会对应用的性能造成影响。 |
2. ActionForward类
Action类的execute()方法返回一个ActionForward对象,它代表了Web资源的逻辑抽象,可以是JSP页面,JavaServlet或者Action,返回ActionForward有两种方法:
l 在execute()方法中动态地创建一个ActionForward实例:
return new ActionForward(“Failure”, “/security/signin.jsp”, true);
“Failure”:代表ActionForward实例的逻辑名;
“/security/signin.jsp”:指定转发路径;
true:表示重定向,false表示请求转发。
l 在Struts配置文件的<action>中配置<forward>子元素或全局<global-forward>
return mapping.findForward(“Failure”);
findForward()方法先调用findForwardConfig()方法,在Action级别(即<action>元素内的<forward>子元素)寻找配置的ActionForward对象,如果没有,再到全局<global-forward>中寻找。如果没有找到,返回null,用户看到的是空白页。
3. 创建支持多线程的Action类
保证线程安全的重要原则是在Action类中仅仅使用局部变量,谨慎地使用实例变量。如果在Action的execute()方法中定义了局部变量,对于每个调用execute()方法的线程,Java虚拟机会在每个线程的堆栈中创建局部变量,因此每个线程拥有独立的局部变量,不会被其他线程共享。当线程执行完execute()方法时,它的局部变量就会被销毁。
因为在Struts应用的生命周期中,只会为每个Action类创建一个实例,所有的客户请求共享这个实例。如果在Action类中定义了实例变量,那么在Action实例的整个生命周期中,这个实例变量被所有的请求线程共享,因此不能在Action类中定义代表特定客户状态的实例变量,比如购物车实例变量。
在Action类中定义的实例变量代表了可以被所有请求线程访问的共享资源,为了避免共享资源的竞争,在必要的情况下,需要采用Java同步机制对访问共享资源共的代码块进行同步。
4. Action类的安全
在某些情况下,如果Action类执行的功能非常重要,则只允许具有特定权限的用户才能访问该Action,为了防止未授权的用户来访问Action,可以在配置Action时指定安全角色:
<action path=”/sample” type=”SampleAction” roles=”manager,admin” /> |
roles属性指定访问这个Action的用户必须具备的安全角色,RequestProcess类在预处理请求时会调用自身的processRoles()方法,检查在配置文件中是否为Action配置了安全角色,如果配置了,就调用HttpServletRequest的isUserInRole()方法,来判断用户是否具备必要的安全角色,不具备返回用户错误。
安全角色和Web容器的应用配置安全域相关,即配置用户和安全角色的映射关系,如果Tomcat,可以参考<CATALINA_HOME>/webapps/tomcat-docs/realm-howto.html