struts1和struts2线程安全对比

①,Struts1通过缓存来管理action对象,并且使用了单例模式,就是一个action只产生一个实例对象,这个实例对象要处理所有对应的request,所以Action类里面不应该有可变的全局变量,我们应该把所有的变量都封装到ActionForm里面。

来看下Struts1的生成action实例对象的源代码:

 1     protected Action processActionCreate(HttpServletRequest request,
 2         HttpServletResponse response, ActionMapping mapping)
 3         throws IOException {
 4         // 获取action类的名字
 5         String className = mapping.getType();
 6 
 7         if (log.isDebugEnabled()) {
 8             log.debug(" Looking for Action instance for class " + className);
 9         }
10 
11         Action instance;
12         
13         // 加锁处理。
14         synchronized (actions) {
15             // 如果此Action已经被创建过对象了,则直接返回已经创建好的对象。
16             instance = (Action) actions.get(className);
17 
18             if (instance != null) {
19                 if (log.isTraceEnabled()) {
20                     log.trace("  Returning existing Action instance");
21                 }
22 
23                 return (instance);
24             }
25 
26             // 如果还没有被创建对象,则创建一个再返回。
27             if (log.isTraceEnabled()) {
28                 log.trace("  Creating new Action instance");
29             }
30 
31             try {
32                 instance = (Action) RequestUtils.applicationInstance(className);
33 
34                 // Maybe we should propagate this exception
35                 // instead of returning null.
36             } catch (Exception e) {
37                 log.error(getInternal().getMessage("actionCreate",
38                         mapping.getPath()), e);
39 
40                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
41                     getInternal().getMessage("actionCreate", mapping.getPath()));
42 
43                 return (null);
44             }
45             
46             // 把新创建好的对象放到缓存中。
47             actions.put(className, instance);
48 
49             if (instance.getServlet() == null) {
50                 instance.setServlet(this.servlet);
51             }
52         }
53 
54         return (instance);
55     }

从代码中我们可以看出,struts1使用了一个actions的缓存来管理所有的action实例对象,当请求一个action对象时,先到actions里面查找对应的action对象,如果存在,则直接返回此对象,如果不存在,则新创建一个action对象,然后加到缓存中,再返回新创建的action实例对象。

②,struts2和struts1不同,struts2会为每个请求都创建一个action对象实例,所以不存在线程安全的问题。

还是看源码:

StrutsPrepareAndExecuteFilter类的doFilter方法:

 1     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
 2 
 3         HttpServletRequest request = (HttpServletRequest) req;
 4         HttpServletResponse response = (HttpServletResponse) res;
 5 
 6         try {
 7             prepare.setEncodingAndLocale(request, response);
 8             prepare.createActionContext(request, response);
 9             // 把dispatcher绑定到当前线程上,作为当前线程的局部变量。
10             prepare.assignDispatcherToThread();
11             if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
12                 chain.doFilter(request, response);
13             } else {
14                 request = prepare.wrapRequest(request);
15                 ActionMapping mapping = prepare.findActionMapping(request, response, true);
16                 if (mapping == null) {
17                     boolean handled = execute.executeStaticResourceRequest(request, response);
18                     if (!handled) {
19                         chain.doFilter(request, response);
20                     }
21                 } else {
22                     execute.executeAction(request, response, mapping);
23                 }
24             }
25         } finally {
26             // 此处清楚线程局部变量。
27             prepare.cleanupRequest(request);
28         }
29     }

从上面的代码中可以看出,struts2把dispatcher作为局部变量绑定到了线程上,而Dispatcher是struts2的核心分发器,所有的action初始化操作都是在它控制之下,所以struts2是线程安全的。

原文地址:https://www.cnblogs.com/huashui/p/3220718.html