Struts2中使用execAndWait后,在 Action中調用getXXX()方法報告java.lang.NullPointerException異常的原因和解決方法


使用 Struts2 編寫頁面,遇到一個要長時間運行的接口,因此增加了一個execAndWait ,結果在 Action 中調用 getContext()的時候報告異常

1 ActionContext context = ActionContext.getContext();
2 ServletContext servletContext = (ServletContext) context.get(ServletActionContext.SERVLET_CONTEXT);  //拋空指針異常
3 String rootPath = servletContext.getRealPath("/");

查詢了很多評論,最終找到原因跟解決方案,具體解釋在 http://stackoverflow.com/questions/16692658/execandwait-interceptor-not-redirecting-to-success-page-after-waiting。大致意思為:execAndWait 會導致執行的Action 在另外一個線程中被執行,而getText 依賴 ActionContext ,他從 ActionContext 中獲得當前的Locale 從而根據語言的不同加載不同的文字,可是,由於ActionContext 是ThreadLocal 的,而execAndWait 新開線程的時候並沒有把父線程的ActionContext 傳遞給子線程 結果導致在新開的子線程中的ActionContext中的數據都是null ,因此出現異常信息就不足為怪了。

解決方法如下:需要重載兩個類,來解決這個問題
ActionInvocationEx.java

 1 package byrs.rms.interceptors;
 2 
 3 import com.opensymphony.xwork2.ActionContext;
 4 import com.opensymphony.xwork2.ActionEventListener;
 5 import com.opensymphony.xwork2.ActionInvocation;
 6 import com.opensymphony.xwork2.ActionProxy;
 7 import com.opensymphony.xwork2.Result;
 8 import com.opensymphony.xwork2.interceptor.PreResultListener;
 9 import com.opensymphony.xwork2.util.ValueStack;
10 
11 public class ActionInvocationEx implements ActionInvocation {
12 
13     /**
14      * 
15      */
16     private static final long serialVersionUID = 2434502343414625665L;
17 
18     private final ActionInvocation mActionInvocation;
19 
20     private final ActionContext context;
21 
22     public ActionInvocationEx(ActionInvocation aActionInvocation,ActionContext aContext)
23     {
24         mActionInvocation = aActionInvocation;
25         context = aContext;
26     }
27 
28     public Object getAction() {
29         return mActionInvocation.getAction();
30     }
31 
32     public boolean isExecuted() {
33         return mActionInvocation.isExecuted();
34     }
35 
36     public ActionContext getInvocationContext() {
37         return mActionInvocation.getInvocationContext();
38     }
39 
40     public ActionProxy getProxy() {
41         return mActionInvocation.getProxy();
42     }
43 
44     public Result getResult() throws Exception {
45         return mActionInvocation.getResult();
46     }
47 
48     public String getResultCode() {
49         return mActionInvocation.getResultCode();
50     }
51 
52     public void setResultCode(String resultCode) {
53         mActionInvocation.setResultCode(resultCode);
54     }
55 
56     public ValueStack getStack() {
57         return mActionInvocation.getStack();
58     }
59 
60     public void addPreResultListener(PreResultListener listener) {
61         mActionInvocation.addPreResultListener(listener);
62     }
63 
64     public String invoke() throws Exception {
65         return mActionInvocation.invoke();
66     }
67 
68     public String invokeActionOnly() throws Exception {
69         return mActionInvocation.invokeActionOnly();
70     }
71 
72     public void setActionEventListener(ActionEventListener listener) {
73         mActionInvocation.setActionEventListener(listener);
74     }
75 
76     public void init(ActionProxy proxy) {
77         mActionInvocation.init(proxy);
78     }
79 
80     public ActionInvocation serialize() {
81         return mActionInvocation.serialize();
82     }
83 
84     public ActionInvocation deserialize(ActionContext actionContext) {
85         return mActionInvocation.deserialize(actionContext);
86     }
87 
88     /**
89      * @return the context
90      */
91     public ActionContext getContext() {
92         return context;
93     }
94 
95 }

ExecAndWaitInterceptorEx.java

 1 package byrs.rms.interceptors;
 2 
 3 import org.apache.struts2.interceptor.BackgroundProcess;
 4 import org.apache.struts2.interceptor.ExecuteAndWaitInterceptor;
 5 
 6 import com.opensymphony.xwork2.ActionContext;
 7 import com.opensymphony.xwork2.ActionInvocation;
 8 
 9 public class ExecAndWaitInterceptorEx extends ExecuteAndWaitInterceptor {
10 
11     /**
12      * 
13      */
14     private static final long serialVersionUID = 8829373762598564300L;
15     
16     /**
17      * {@inheritDoc}
18      */
19     @Override
20     protected BackgroundProcess getNewBackgroundProcess(String arg0, ActionInvocation arg1, int arg2) {
21         ActionInvocationEx aActionInvocationEx = new ActionInvocationEx(arg1,ActionContext.getContext());
22         return new BackgroundProcessEx(arg0, aActionInvocationEx, arg2);
23     }
24 
25     private class BackgroundProcessEx extends BackgroundProcess {
26         public BackgroundProcessEx(String threadName,
27                 ActionInvocation invocation, int threadPriority) {
28             super(threadName, invocation, threadPriority);
29         }
30 
31         private static final long serialVersionUID = -9069896828432838638L;
32         /**
33          * {@inheritDoc}
34          * @throws InterruptedException 
35          */
36         @Override
37         protected void beforeInvocation() throws InterruptedException {
38             ActionInvocationEx aActionInvocationEx = (ActionInvocationEx)this.invocation;
39             ActionContext context = aActionInvocationEx.getContext();
40             ActionContext.setContext(context);
41         }
42 
43         /**
44          * {@inheritDoc}
45          */
46        @Override
47         protected void afterInvocation() {
48             ActionContext.setContext(null);
49         }
50 
51     }
52 
53 }

然后在struts.xml中覆蓋默認攔截器即可

1 <interceptors > 
2             <interceptor name="execAndWait" class="byrs.rms.interceptors.ExecAndWaitInterceptorEx"/> 
3         </interceptors >

參考自:http://www.mobibrw.com/?p=1046


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM