分类: Struts2

  • 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

    package byrs.rms.interceptors;
    
    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.ActionEventListener;
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.ActionProxy;
    import com.opensymphony.xwork2.Result;
    import com.opensymphony.xwork2.interceptor.PreResultListener;
    import com.opensymphony.xwork2.util.ValueStack;
    
    public class ActionInvocationEx implements ActionInvocation {
    
        /**
         * 
         */
        private static final long serialVersionUID = 2434502343414625665L;
    
        private final ActionInvocation mActionInvocation;
    
        private final ActionContext context;
    
        public ActionInvocationEx(ActionInvocation aActionInvocation,ActionContext aContext)
        {
            mActionInvocation = aActionInvocation;
            context = aContext;
        }
    
        public Object getAction() {
            return mActionInvocation.getAction();
        }
    
        public boolean isExecuted() {
            return mActionInvocation.isExecuted();
        }
    
        public ActionContext getInvocationContext() {
            return mActionInvocation.getInvocationContext();
        }
    
        public ActionProxy getProxy() {
            return mActionInvocation.getProxy();
        }
    
        public Result getResult() throws Exception {
            return mActionInvocation.getResult();
        }
    
        public String getResultCode() {
            return mActionInvocation.getResultCode();
        }
    
        public void setResultCode(String resultCode) {
            mActionInvocation.setResultCode(resultCode);
        }
    
        public ValueStack getStack() {
            return mActionInvocation.getStack();
        }
    
        public void addPreResultListener(PreResultListener listener) {
            mActionInvocation.addPreResultListener(listener);
        }
    
        public String invoke() throws Exception {
            return mActionInvocation.invoke();
        }
    
        public String invokeActionOnly() throws Exception {
            return mActionInvocation.invokeActionOnly();
        }
    
        public void setActionEventListener(ActionEventListener listener) {
            mActionInvocation.setActionEventListener(listener);
        }
    
        public void init(ActionProxy proxy) {
            mActionInvocation.init(proxy);
        }
    
        public ActionInvocation serialize() {
            return mActionInvocation.serialize();
        }
    
        public ActionInvocation deserialize(ActionContext actionContext) {
            return mActionInvocation.deserialize(actionContext);
        }
    
        /**
         * @return the context
         */
        public ActionContext getContext() {
            return context;
        }
    
    }

     

    ExecAndWaitInterceptorEx.java

    package byrs.rms.interceptors;
    
    import org.apache.struts2.interceptor.BackgroundProcess;
    import org.apache.struts2.interceptor.ExecuteAndWaitInterceptor;
    
    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.ActionInvocation;
    
    public class ExecAndWaitInterceptorEx extends ExecuteAndWaitInterceptor {
    
        /**
         * 
         */
        private static final long serialVersionUID = 8829373762598564300L;
        
        /**
         * {@inheritDoc}
         */
        @Override
        protected BackgroundProcess getNewBackgroundProcess(String arg0, ActionInvocation arg1, int arg2) {
            ActionInvocationEx aActionInvocationEx = new ActionInvocationEx(arg1,ActionContext.getContext());
            return new BackgroundProcessEx(arg0, aActionInvocationEx, arg2);
        }
    
        private class BackgroundProcessEx extends BackgroundProcess {
            public BackgroundProcessEx(String threadName,
                    ActionInvocation invocation, int threadPriority) {
                super(threadName, invocation, threadPriority);
            }
    
            private static final long serialVersionUID = -9069896828432838638L;
            /**
             * {@inheritDoc}
             * @throws InterruptedException 
             */
            @Override
            protected void beforeInvocation() throws InterruptedException {
                ActionInvocationEx aActionInvocationEx = (ActionInvocationEx)this.invocation;
                ActionContext context = aActionInvocationEx.getContext();
                ActionContext.setContext(context);
            }
    
            /**
             * {@inheritDoc}
             */
           @Override
            protected void afterInvocation() {
                ActionContext.setContext(null);
            }
    
        }
    
    }

     

    然后在struts.xml中覆盖默认拦截器即可

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

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

  • 在struts2上获取包含参数的完整的url

    Map map = request.getParameterMap();
    Iterator it = map.keySet().iterator();
    String paramStr = "";
    while(it.hasNext()){
    	String key = it.next().toString();
    	String value = request.getParameter(key);
    	paramStr += key + "=" + value + "&";
    }
    //完整的请求
    System.out.println(request.getRequestURL()+"?"+paramStr);

     

  • 解决struts2中首页默认调用index的问题

    在struts 2中,通过在web-xml中配置welcome-file欢迎页面来调用action是无效的。

    以前是直接在index.jsp中加上这个标签 <s:action name=”index” namespace=”/”/>, 但是这样做的话, 对应index的action中result处理就不起作用了。

    经过资料整理后, 最终得出我们可以在struts-xml中的action配置中加入来实现你预期的效果。

    我们可以在默认的package中加上<default-action-ref name=”action名称”/>, 如:

    <package name="default" namespace="/" extends="struts-default">
        <default-action-ref name="index"/>
        <action name="index" class="web.action.IndexAction" method="index">
            <result name="success">index.jsp</result>
        </action>
    </package>

    还有一点不要漏掉,记得清空web.xml中的welcome-file,不然默认是会被调用index.jsp的,对于某些人来说可能会造成错误:

    <welcome-file-list>
        <welcome-file></welcome-file>
    </welcome-file-list>

    这样即可解决这个问题。

  • struts2自定义404错误页面

    最近服务器后台出现一些异常,问题是客户访问一个该网站下不存在的action,为了给客户一个友好的界面提示以及减小服务器端日志文件的内容。就在struts2下进行了如下配置:
    在struts.xml里的package下添加:

    <default-action-ref name="pagenotfound"></default-action-ref>  
    <action name="pagenotfound">  
        <result>/404.jsp</result>  
    </action>

     

    当然struts2只会处理用户访问不存在的action,当用户访问jsp或者html时,是不会处理的。
    这样还要在项目的web.xml下添加:

    <package name="404" extends="struts-default">
    	<default-action-ref name="notFound" />
    	<action name="notFound">
    		<result>/404.jsp</result>
    	</action>
    </package>