【问题标题】:execAndWait Interceptor not redirecting to success page after waitingexecAndWait 拦截器在等待后未重定向到成功页面
【发布时间】:2013-05-22 13:09:05
【问题描述】:

我有一个登录屏幕,其中会发生一些用户输入验证,用户将通过身份验证并最终重定向到欢迎屏幕。

下面是LoginAction的拦截器定义:

<package name="default" extends="struts-default" namespace="/">
    <interceptors>  
        <interceptor name="myInterceptor" 
            class="com.interceptor.MyInterceptor"></interceptor>

        <interceptor-stack name="newStack">
            <interceptor-ref name="myInterceptor"/>             
            <interceptor-ref name="defaultStack" />
            <interceptor-ref name="execAndWait">
                <param name="delay">100</param>
                <param name="delaySleepInterval">500</param>
            </interceptor-ref>              
         </interceptor-stack> 
    </interceptors>

    <action name="login"
        class="com.action.LoginAction"> 
        <interceptor-ref name="newStack"/>
        <result name="success">common/Welcome.jsp</result>
        <result name="wait">common/wait.jsp</result>
        <result name="error">Login.jsp</result>
        <result name="input">Login.jsp</result>
    </action>
</package>

下面是LoginAction的执行方法:

   if (isUserAuthenticated) {
        // Some background processing for logging purpose           
        return "success";
    } else {            
        addActionError(getText("error.login"));
        return "error";
    }

这段代码有几个问题:

1) 对于经过身份验证的用户,会显示 wait.jsp 页面,但不会重定向到 Welcome.jsp

2) 对于未经身份验证的用户,我收到以下异常:

java.lang.NullPointerException
at com.opensymphony.xwork2.util.LocalizedTextUtil.findText(LocalizedTextUtil.java:361)
at com.opensymphony.xwork2.TextProviderSupport.getText(TextProviderSupport.java:208)
at com.opensymphony.xwork2.TextProviderSupport.getText(TextProviderSupport.java:123)
at com.opensymphony.xwork2.ActionSupport.getText(ActionSupport.java:103)
at com.infy.action.LoginAction.execute(LoginAction.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:450)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:289)
at org.apache.struts2.interceptor.BackgroundProcess$1.run(BackgroundProcess.java:57)
at java.lang.Thread.run(Thread.java:662)

【问题讨论】:

  • 您在刷新等待页面吗?

标签: struts2 struts-validation struts2-interceptors


【解决方案1】:
  1. execAndWait 使操作在新线程中执行。
  2. 由于ActionContextThreadLocal,新线程将不会获取存储在ActionContext 的父线程版本中的值。每个线程都有一个唯一版本的ActionContext
  3. getText() 在尝试在新线程中执行时会抛出 NPE,因为它依赖于 ActionContext

要解决此问题,您需要将父线程 ActionContext 复制到 execAndWait 线程中。您可以通过扩展BackgroundProcess 类,实现beforeInvocation()afterInvocation() 方法,并扩展ExecuteAndWaitInterceptor,实现getNewBackgroundProcess() 方法来做到这一点。

示例

public class YourExecAndWaitInterceptor extends ExecuteAndWaitInterceptor {

    private static final long serialVersionUID = 1L;


    /**
     * {@inheritDoc}
     */
    @Override
    protected BackgroundProcess getNewBackgroundProcess(String arg0, ActionInvocation arg1, int arg2) {
        return new YourBackgroundProcess(arg0, arg1, arg2, ActionContext.getContext());
    }

}



public class YourBackgroundProcess extends BackgroundProcess {

    private final ActionContext context;

    public YourBackgroundProcess(String threadName, ActionInvocation invocation, int threadPriority, ActionContext context) {
        super(threadName, invocation, threadPriority);
        this.context = context;
     }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void beforeInvocation() {
        ActionContext.setContext(context);
    }

    /**
     * {@inheritDoc}
     */
   @Override
    protected void afterInvocation() {
        ActionContext.setContext(null);
    }

}

【讨论】:

  • 这个解决方案在 Struts2.3.24 中不起作用...有什么新的解决方法吗?
  • ActionInvocation 已经拥有对ActionContext 的引用,因此您可以直接在YourBackgroundProcess 中使用它
  • @IlGala 怎么了?你看到有什么例外吗?请在此处发布任何 cmets issues.apache.org/jira/browse/WW-3161
【解决方案2】:

NPE 发生是因为带有execAndWait 拦截器的操作在单独的线程中运行,并且您正在调用使用ActionContextgetText 方法。 ActionContext 是线程本地的,这意味着存储在 ActionContext 中的值对于每个线程都是唯一的。

为了在流程结束后显示成功页面,您需要不时刷新页面。在examples 中使用meta http-equiv="refresh" 完成。

<meta http-equiv="refresh" content="5;url=<s:url includeParams="all" />"/> 

【讨论】:

  • @user182944:您正在刷新等待页面吗?
  • @user182944:您必须轮询相同的操作才能在作业完成后显示成功页面。
  • 感谢您的解释。页面刷新工作正常。但我无法删除 NPE :( 我在 struts.xml 中添加了一个全局属性文件,如下所示:&lt;constant name="struts.custom.i18n.resources" value="ApplicationResources,LoginAction" /&gt; 文件具有条目:error.login = Error login 请让我知道如何解决此问题NPE .
  • @user182944:不要使用getText 方法。如果您需要本地化文本,您可以自己加载资源。
【解决方案3】:

在您的操作或应用程序提供的资源中找不到密钥 "error.login",或者您使用了错误的语言环境。这意味着您没有配置i18n 资源。要解决您的问题,您需要创建LoginAction.properties 文件并将密钥放入其中

error.login = Error login

如果您正在使用从您的帖子中看不到的全局属性文件,请在此处添加此键。

【讨论】:

  • 你怎么知道用户已经通过身份验证?
  • 我在我的 struts.xml 中添加了这个但没有工作:&lt;constant name="struts.custom.i18n.resources" value="ApplicationResources,LoginAction" /&gt; 仍然得到 NPE :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-24
  • 2016-05-28
  • 2022-01-17
  • 1970-01-01
  • 2015-04-24
  • 2019-07-24
相关资源
最近更新 更多