该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-07-06
最后修改:2010-07-10
struts2在这一点上做了改进,每个action都是一个singleton,所有的请求都是请求同一个action实例。这样在一定程度上能节约资源,但又有安全问题。最常见的就是在action中声明有块状的实例变量,因为这一点是不被提倡的。如果一定要声明,那一定要加上同步块。 那么在spring mvc中的controller是不是线程安全的呢?答案是否定的。controller在默认情况下也是非线程安全的,我们来看看源码: * @author John A. Lewis * @author Juergen Hoeller * @since 2.0 * @see ResourceAwareController * @see EventAwareController */ public abstract class AbstractController extends PortletContentGenerator implements Controller { [color=red]private boolean synchronizeOnSession = false;[/color] 由上面源码可知,controller默认是非安全的。 public void handleActionRequest(ActionRequest request, ActionResponse response) throws Exception { // Delegate to PortletContentGenerator for checking and preparing. check(request, response); // Execute in synchronized block if required. //只有synchronizeOnSession设置为true,才会同步处理请求 if (this.synchronizeOnSession) { PortletSession session = request.getPortletSession(false); if (session != null) { synchronized (session) { handleActionRequestInternal(request, response); return; } } } handleActionRequestInternal(request, response); } 只有手工设置controller的synchronizeOnSession值为true,才会被同步处理。 因此,我们在使用spring mvc 的contrller时,应避免在controller中定义实例变量。 ##### 更正 #################################### 由于在下对struts1.x的理解也来自网络,给大家带来不便,还请见谅。 经过对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、根据类名去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.2获取action的方式是单例的,所有的action都被维护在一个hashMap里,当有请求到达时,先根据action的名称去hashMap里查找要请求的Action是否已经存在,如果存在,则直接返回hashMap里的action。如果不存在,则创建一个新的Action实例。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-07-06
引用 大家都知道,struts1.2由于是线程安全的,每一个请求都去实例化一个action,造成大量并发时的资源浪费。
struts2在这一点上做了改进,每个action都是一个singleton,所有的请求都是请求同一个action实例。 struts1.2不了解 struts2怎么会是所有的请求都是请求同一个action实例 |
|
返回顶楼 | |
发表时间:2010-07-06
struts1 貌似是单实例的 所以会有线程安全问题
struts2 貌似是每个请求都有一个实例 所以不会有线程安全的问题 |
|
返回顶楼 | |
发表时间:2010-07-06
最后修改:2010-07-06
LZ搞反了吧
struts1是单例提供服务,请求数据绑定在actionform里,form当做参数传入调用方法,不用实例变量就不会出现并发问题---spring mvc的contrller也是这样的模式 struts2是每次创建新的实例,其请求变量是绑定在action的实例变量里面,用spring管理S2的action时,因为spring的bean默认是只创建一个实例,所以必须设定作用域为prototype才行 |
|
返回顶楼 | |
发表时间:2010-07-06
楼主反了额
|
|
返回顶楼 | |
发表时间:2010-07-07
果然是反了
|
|
返回顶楼 | |
发表时间:2010-07-07
aws 写道 LZ搞反了吧
struts1是单例提供服务,请求数据绑定在actionform里,form当做参数传入调用方法,不用实例变量就不会出现并发问题---spring mvc的contrller也是这样的模式 struts2是每次创建新的实例,其请求变量是绑定在action的实例变量里面,用spring管理S2的action时,因为spring的bean默认是只创建一个实例,所以必须设定作用域为prototype才行 我说也是LZ搞反了 |
|
返回顶楼 | |
发表时间:2010-07-07
我就说怎么一看感觉变扭。。
|
|
返回顶楼 | |
发表时间:2010-07-07
struts1来一个请求,通过key(action)到actionMap里找,找到null就添加一个创建,否则直接使用。
|
|
返回顶楼 | |
发表时间:2010-07-07
lz误人子弟啊,我这种菜鸟就是被这么误掉的,哈哈
|
|
返回顶楼 | |