2

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

下面是拦截器的定义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)
4

3 回答 3

4
  1. execAndWait导致动作在新线程中执行。
  2. 既然ActionContextThreadLocal这样,新线程将不会获得存储在父线程版本中的值ActionContext。每个线程都有一个独特的版本ActionContext
  3. getText()当它试图在新线程中执行时会抛出一个 NPE,因为它依赖于ActionContext

要解决此问题,您需要将父线程复制ActionContextexecAndWait线程中。您可以通过扩展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);
    }

}
于 2013-11-13T21:37:09.547 回答
3

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

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

<meta http-equiv="refresh" content="5;url=<s:url includeParams="all" />"/> 
于 2013-05-23T08:46:06.660 回答
1

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

error.login = Error login

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

于 2013-05-22T15:33:15.403 回答