【问题标题】:How to pass an action name using hyperlink in Struts 2?如何在 Struts 2 中使用超链接传递动作名称?
【发布时间】:2013-08-18 14:11:14
【问题描述】:

我有一个名为"Click for new User" 的超链接。单击链接后,我得到了NullPointerException 而不是打开RegisterPage.jsp 页面。

我在这里发布我的代码,我找不到我的错误

index.jsp:

<s:form action="verify">
<s:textfield name="username" key="label.uname"  required="true"/>
<s:password name="password" key="label.pass" required="true"/>
<s:submit value="Login" align="center"/> 
</s:form>
<a href="<s:url action='register'/>">Click for New User</a>

struts.xml:

<struts>
<package name="a" extends="struts-default">
<action name="verify" class="java4s.Login"  method="execute">
<result name="success">loginsuccess.jsp</result>
<result name="error">error.jsp</result>
<result name="input">index.jsp</result>
</action>
<action name="register" class="java4s.Login" method="register">
<result name="success">RegisterPage.jsp</result>
</action>
</package>
</struts>

Login.java(动作类):

package java4s;

import com.opensymphony.xwork2.ActionSupport;

public class Login extends ActionSupport {

private static final long serialVersionUID = 1L;
private String username,password;
public String getUsername() {
    return username;
}
public void setUsername(String username) {
    this.username = username;
}
public String getPassword() {
    return password;
}
public void setPassword(String password) {
    this.password = password;
}
public String register(){
    System.out.println("register ()");
    return SUCCESS;
}
public String execute(){
    if (getUsername().equals("java4s")&&getPassword().equals("java4s")) {
        return SUCCESS;
    } else {
        this.addActionError(getText("u.p.wrong"));
        return ERROR;
    }   
}
@Override
public void validate() {
        if (getUsername().equals("")||getUsername().length()==0)
        this.addFieldError("username",getText("error.uname"));
        if(getPassword().equals("")||getPassword().length()==0) 
        this.addFieldError("password", getText("error.pass"));

}
}

例外:

 javax.servlet.ServletException: java.lang.NullPointerException
 org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:515)
 org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:4‌​19)
 java.lang.NullPointerException
java4s.Login.validate(Login.java:38)
com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:200)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:86)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:150)
org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:48)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:86)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:123)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:167)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:86)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:105)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:83)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:207)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:74)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:127)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
org.apache.struts2.interceptor.ProfilingActivationInterceptor.intercept(ProfilingActivationInterceptor.java:107)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:206)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:115)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:143)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:121)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:86)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:170)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:123)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176) 
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:50)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:504)
org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:419)

【问题讨论】:

  • 我已将您的例外添加到您的帖子中。将来请在您的问题中添加所有相关详细信息,而不是未格式化的 cmets。此外,未缩进的 XML 是怎么回事?这并不容易阅读。最后,这不是完整的堆栈跟踪。请发布完整堆栈跟踪。
  • 当您通过链接调用您的操作时,没有用户名和密码字段,您正在通过检查导致此问题的长度和空值对它们进行验证,因为您的验证方法正在由于 S2 配置的拦截器堆栈而被调用
  • 我建议您对所有此类情况使用 Apache 通用库,它的 String Util 方法 StringUtils.isBlank() 是空安全检查,它将能够解决您的问题,而且更多的通用性确实是一个有用的 API多方面
  • 我不确定您为什么要使用 validate 方法,而您可以使用更灵活并提供更多详细信息的内置验证框架,而且建议的验证方法将在您每次操作的方法时触发由于配置了默认堆栈而被调用,因此您可以创建单独的注册操作,或者您可以检查操作类中的空值
  • 当您的用户名未设置时将引发空指针异常,因为在这种情况下它将为空,并且对空值执行任何操作都会引发 NPE。我说StringUtils.isBlank() 是空安全的,这意味着它将首先检查给定值是否不为空,然后才检查字符串是否为空。

标签: java jquery jsp validation struts2


【解决方案1】:

当您单击超链接时,您没有提供带有参数usernamepassword 的请求URL(这些参数不是由params 拦截器设置的),因此该属性的值是null但是validate() 方法在执行操作之前被调用,因为您的操作扩展了ActionSupport,它实现了ValidateableValidationAware,它允许validation 拦截器(它是defaultStack 的一部分)执行@987654333 @ 方法,您可以在其中执行手动检查并提供 ActionErrorsFieldErrorsActionMessages。但是,如果您不提供属性的值,则没有理由这样做。您应该提交表单或在 url 中设置参数,例如

<a id="myLink" href="#">Click for New User</a>
<script type="text/javascript>
$(document).ready(function(){
  $('#myLink').click(function(e) {
    window.location="<s:url action='register'/>"+"?username="+$('username').val()+"&password="+$('password').val();
    return false;
  });
});
</script>

但问题是参数值(用户名和密码)是敏感信息,不应在 URL 中传递。您应该使用 Ajax post 或使用 POST 请求提交表单,例如 this 示例。

当使用手动验证时,Apache commons validator 非常有用

if (GenericValidator.isBlankOrNull(value))
  addFieldError("FieldLabel", MessageFormat.format(getText("ErrorKey"),
    getText("FieldLabel"), new Object {}));

可以为ActionErrors 和/或ActionMessages 完成类似的代码。其他验证器在 commons-validator 包中可用,或者您可以使用不属于这个问题的 Struts2 验证器。

【讨论】:

  • 我很抱歉不接受你的回答,问题是我的工作区,在我的工作区有 12 个项目,所以它不能正常工作,在重新启动时只有你的代码可以工作,谢谢你的回复我的帖子。
猜你喜欢
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-29
  • 2016-01-19
  • 2014-01-05
  • 2013-09-20
  • 2013-10-17
相关资源
最近更新 更多