Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 470|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-9-2 09:49:56 | 显示全部楼层 |阅读模式

    使用 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

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-16 01:58 , Processed in 0.064677 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表