java.lang.NullPointerException at com.opensymphony.xwork2.util.LocalizedTextUtil.findText(...

为了防止CSRF攻击,在struts2的form表单中使用<s:token/>,在拦截器里添加了<interceptor-ref name=”token”/>,结果发现抛出下面的异常:

java.lang.NullPointerException

at com.opensymphony.xwork2.util.LocalizedTextUtil.findText(LocalizedTextUtil.java:630)

at com.opensymphony.xwork2.util.LocalizedTextUtil.findText(LocalizedTextUtil.java:606)

at com.opensymphony.xwork2.TextProviderSupport.getText(TextProviderSupport.java:210)

at com.opensymphony.xwork2.TextProviderSupport.getText(TextProviderSupport.java:139)

at org.apache.struts2.interceptor.TokenInterceptor.getErrorMessage(TokenInterceptor.java:182)

at org.apache.struts2.interceptor.TokenInterceptor.handleInvalidToken(TokenInterceptor.java:166)

at org.apache.struts2.interceptor.TokenInterceptor.handleToken(TokenInterceptor.java:151)

at org.apache.struts2.interceptor.TokenInterceptor.doIntercept(TokenInterceptor.java:142)

at com.alibaba.search.scc.web.interceptor.SccTokenInterceptor.intercept(SccTokenInterceptor.java:42)

at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)

at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)

at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:562)

at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)

at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)

我的用法照理讲应该是官方的用法,按照异常堆栈查看struts2源码,发现问题在这里:

TokenInterceptor.java

Java

@Inject
    public void setTextProvider(TextProvider textProvider) {
        this.textProvider = textProvider;
    }

    protected String handleInvalidToken(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();
        String errorMessage = getErrorMessage(invocation);

        if (action instanceof ValidationAware) {
            ((ValidationAware) action).addActionError(errorMessage);
        } else {
            log.warn(errorMessage);
        }

        return INVALID_TOKEN_CODE;
    }

    protected String getErrorMessage(ActionInvocation invocation) {
        Object action = invocation.getAction();
        if (action instanceof TextProvider) {
            return ((TextProvider) action).getText(INVALID_TOKEN_MESSAGE_KEY, DEFAULT_ERROR_MESSAGE);
        }
        return textProvider.getText(INVALID_TOKEN_MESSAGE_KEY, DEFAULT_ERROR_MESSAGE);
    }

@Inject

public void setTextProvider ( TextProvider textProvider ) {

this . textProvider = textProvider ;

}

protected String handleInvalidToken ( ActionInvocation invocation ) throws Exception {

Object action = invocation . getAction ( ) ;

String errorMessage = getErrorMessage ( invocation ) ;

if ( action instanceof ValidationAware ) {

( ( ValidationAware ) action ) . addActionError ( errorMessage ) ;

} else {

log . warn ( errorMessage ) ;

}

return INVALID_TOKEN_CODE ;

}

protected String getErrorMessage ( ActionInvocation invocation ) {

Object action = invocation . getAction ( ) ;

if ( action instanceof TextProvider ) {

return ( ( TextProvider ) action ) . getText ( INVALID_TOKEN_MESSAGE_KEY , DEFAULT_ERROR_MESSAGE ) ;

}

return textProvider . getText ( INVALID_TOKEN_MESSAGE_KEY , DEFAULT_ERROR_MESSAGE ) ;

}

出问题的是textProvider.getText方法,原因是textProvider中的bundle和class是空的,为什么是空的呢?可以看到setTextProvider方法上有一个@Inject注解,这个注解告诉了struts2需要注入一个类型为 com.opensymphony.xwork2.TextProvider 的实例,因为struts jar包里面的 struts-default.xml 中默认的配置是:

Java

<span class="code-tag" style="color: #000091;">&lt;bean type=<span class="code-quote" style="color: #009100;">"com.opensymphony.xwork2.TextProvider"</span> name=<span class="code-quote" style="color: #009100;">"struts"</span> class=<span class="code-quote" style="color: #009100;">"com.opensymphony.xwork2.TextProviderSupport"</span> /&gt;</span>

< span class = "code-tag" style = "color: #000091;" > & lt ; bean type = < span class ="code-quote" style = "color: #009100;" > "com.opensymphony.xwork2.TextProvider" < /span > name = < span class = "code-quote" style = "color: #009100;" > "struts" < / span> class = < span class = "code-quote" style = "color: #009100;" > "com.opensymphony.xwork2.TextProviderSupport" < / span > / & gt ; < / span >

所以默认注入的就是TextProviderSupport实例对象,而这个bean中没有默认指定class和bundle,这就导致了textProvider.getText方法抛出空指针异常。

根据官方文档中的说法,可以自己实现TextProvider,形如:

<bean class=”org.demo.MyTextProvider” name=”myTextProvider” type=”com.opensymphony.xwork2.TextProvider” />

<constant name=”struts.xworkTextProvider” value=”myTextProvider” />

换个方式解决问题:

如果上面的getErrorMessage方法中执行了if语句里面的内容就不会走到textProvider.getText方法那里去,所以可以尝试让action的类型属于TextProvider,在TextProvider上ctrl+T可以看到其实现类上有ActionSupport类,所以这就知道了只需要让action类继承ActionSupport类即可避免抛出上面的空指针异常。

当然,既然进入到handleInvalidToken方法里面来了,那就需要为返回值INVALID_TOKEN_CODE(“invalid.token“)配置出错页面,形如:

XHTML

<global-results>
    <result name="invalid.token" type="dispatcher">
        /templates/error/illegal_operate.jsp
    </result>
</global-results>

<global-results>

<result name = "invalid.token" type = "dispatcher" >

/templates/error/illegal_operate.jsp

</result>

</global-results>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值