前面已经介绍了Struts的基本原理和控制器ActionServlet,按照一个请求的流程经过了ActionServlet之后就要到达Action类中做具体的处理了。ActionServlet通过ActionMapping获取映射的Action对象,通过Action来完成请求的处理,最后Action返回一个ActionForward对象。
Action的创建
当请求经过ActionServlet时,ActionServlet会根据请求中截取的地址搜索对应名字的ActionMapping,即Struts-config.xml中对应标签的配置信息。然后根据ActionMapping查找对应的Action,如果存在则直接使用,否则就创建一个并放置到HashMap充当的缓存中。也就是说Struts1中的Action是单例的。
线程安全问题
上面提到了,Action是单例的。也就是说所有的请求都使用同一个Action类。这在一定条件下就会导致线程安全问题。这里的一定条件指的是:在Action类中定义了实例变量。提一句所谓的实例变量是指在类中定义的但在所有方法之外的变量。线程安全就不细说了。
解决方法:①尽量不要使用静态变量和实例变量②使用synchronized进行同步③采用ThreadLocal,将定义的成员变量放入ThreadLocal中,一般定义成private static的:
private static ThreadLocal<Integer> local = new ThreadLocal<Integer>();
用的时候,当需要获得成员变量的时候,先使用local对象的get方法Integer inte = local.get(),如果得到的是不是null,那么就返回get的值,如果是null,那么new一个成员变量,然后调用local的set方法,当前线程以后再get的时候就不再是null了。
特殊的Action
看名称就知道它和ActionForward是亲戚。它们俩的功能是非常相似的,都是页面跳转。假设这样一种情况:你单击了某个超链接只是想要一个页面跳转到另一个页面。如果直接跳转的话,该请求将处于Struts的管理之外,而如果你请求到一个Action又很浪费。这时就是使用ForwardAction的时候了。
该类提供了包含其他web组件的能力,我们知道在JSP网页中我们可以通过<include>来做这个功能。但是Struts框架提倡的是管理所有的请求,也就是说包含其他web组件的请求也要纳入到控制中心的管理中来。那么这时候就可以使用IncludeAction了。
通常在一个Action中只完成一种业务逻辑的操作,那么如果需要很多类似的操作就需要建立其他不同的Action类。这样的结果就是Action类的过多。针对这种情况就可以通过DispatchAction类把相似的业务逻辑纳入到一个Action类中来以减少Action的数量。
这个目前没有使用过呢,说是用于模块与模块间的切换。没有用过体会不是很清晰,暂时先放下了。
总结:Action是Struts的实际执行者,它是单例的因此在某些情况下会有线程安全问题。这个需要注意,另外四个特俗用途的Action也需要了解,以便于不会遗漏请求在struts的管理之外。 SSH—Struts(三)—执行器(Action)
原文:http://blog.csdn.net/zhuojiajin/article/details/40662297