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

你可能感兴趣的:(Struts2中使用execAndWait后,在 Action中调用getXXX()方法报告java.lang.NullPointerException异常的原因和解决方法)