Struts2 Bean验证

克莱顿罗杰斯

我目前正在设置一个Stuts2应用程序,该应用程序使用休眠bean验证来验证登录页面上的表单字段。我已经添加了所有必需的插件和依赖项,并将struts.xml配置为包括一个调用beanValidation拦截器的自定义堆栈。/ logon路径从authInterceptor中排除不幸的是,即使填充了电子邮件和密码的表单字段,返回消息仍然是空白。我可以在调试器中看到已在LoginAction类中设置了电子邮件和密码,但是好像beanValidation没有此信息。如果我将拦截器的顺序切换到最后beanValidation,则永远不会调用它。

  <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <constant name="struts.devMode" value="false" />
    <constant name="struts.action.extension" value="," />
    <constant name="struts.custom.i18n.resources" value="login,signup" />
    <constant name="struts.mapper.alwaysSelectFullNamespace"
        value="false" />
    <constant name="struts.beanValidation.providerClass" value="org.hibernate.validator.HibernateValidator" />
    <constant name="struts.beanValidation.ignoreXMLConfiguration"
        value="false" />
    <constant name="struts.beanValidation.convertMessageToUtf"
        value="false" />
    <constant name="struts.beanValidation.convertMessageFromEncoding"
        value="ISO-8859-1" />
    <constant name="struts.enable.SlashesInActionNames" value="true" />
    <package name="defaultPackage" namespace="/" extends="struts-default">
        <interceptors>
            <interceptor name="authInterceptor"
                class="com.mypackage.interceptor.AuthenticationInterceptor">
            </interceptor>
            <interceptor name="beanValidation"
                class="org.apache.struts.beanvalidation.validation.interceptor.BeanValidationInterceptor" />
            <interceptor-stack name="authStack">
                <interceptor-ref name="defaultStack" />
                <interceptor-ref name="beanValidation">
                    <param name="validateAnnotatedMethodOnly">true</param>
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="authInterceptor" />
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="authStack"></default-interceptor-ref>
        <global-results>
            <result name="login">/jsp/login.jsp</result>
        </global-results>
        <action name="login" class="com.mypackage.action.LoginAction"
            method="login">
            <interceptor-ref name="authStack">
                <param name="excludeMethods">login</param>
            </interceptor-ref>
            <result name="login">/jsp/login.jsp</result>
            <result name="input">/jsp/login.jsp</result>
        </action>
        <action name="logon" class="com.mypackage.action.LoginAction"
            method="doLogon">
            <interceptor-ref name="authStack">
                <param name="authInterceptor.excludeMethods">doLogon</param>
            </interceptor-ref>
            <result name="input">/jsp/login.jsp</result>
            <result name="success">/jsp/login.jsp</result>
        </action>
        <action name="password/reset" class="com.mypackage.action.PasswordResetAction"
            method="resetPassword">
            <interceptor-ref name="authInterceptor">
                <param name="excludeMethods">resetPassword</param>
            </interceptor-ref>
            <result name="reset-password">/jsp/password_reset_html.jsp</result>
        </action>
        <action name="register" class="com.mypackage.action.RegisterAction"
            method="register">
            <interceptor-ref name="authInterceptor">
                <param name="excludeMethods">register</param>
            </interceptor-ref>
            <result name="register">/jsp/register_html.jsp</result>
        </action>
        <action name="doRegistration" class="com.mypackage.action.RegisterAction">
            <interceptor-ref name="authInterceptor">
                <param name="excludeMethods">resetPassword</param>
            </interceptor-ref>
        </action>
    </package>
</struts>

的HTML

         <div class="fields-container">
            <div class="field-div">
                <div>
                    <span><s:text name="login.email" /></span>
                </div>
                <label class="form-label"> <input type="text" name="email"
                    value="" />
                </label>
            </div>
            <div class="field-div">
                <div>
                    <span><s:text name="login.password" /></span>
                </div>
                <label class="form-label"> <input type="text"
                    name="password" value="" />
                </label>
            </div>
        </div>

动作课

public class LoginAction extends BaseAction {

/**
 * 
 */
private static final long serialVersionUID = 1L;

private static final Logger log = LoggerFactory.getLogger(LoginAction.class);

@NotNull(message = "{login.error.email.empty}")
private String email;

@NotNull(message = "{login.error.password.empty}")
private String password;

public String login() {
    return ActionConstants.LOGIN;
}

/**
 * Perform the authentication of the user.
 * 
 * @return The result string which maps to a jsp page.
 */
public String doLogon() {
    String result = null;
    return result;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

编辑16/10/6

我更改了拦截器的执行顺序,以便首先执行,defaultStack因为我的理解是它负责填充中的bean ActionClass现在,验证正在按需进行。但是,如果我将任何字段保留为空白,则会返回正确的错误消息,但doLogon仍在调用ActionClass方法我现在试图找出如何使beanValidation短路,以便ActionClass不被调用。

克莱顿罗杰斯

因此,似乎是org.apache.struts.beanvalidation.validation.interceptor。BeanValidationInterceptor并非旨在缩短其他拦截器的执行。在struts bean验证插件的2.5版中,doIntercept方法仅返回invocation.invoke(),这将指示即使有错误,执行也会继续。

    protected String doIntercept(ActionInvocation invocation)
    throws Exception
  {
    Validator validator = this.beanValidationManager.getValidator();
    if (validator == null)
    {
      LOG.debug("There is no Bean Validator configured in class path. Skipping Bean validation..");
      return invocation.invoke();
    }
    LOG.debug("Starting bean validation using validator: {}", new Object[] { validator.getClass() });

    Object action = invocation.getAction();
    ActionProxy actionProxy = invocation.getProxy();
    String methodName = actionProxy.getMethod();
    if (LOG.isDebugEnabled()) {
      LOG.debug("Validating [{}/{}] with method [{}]", new Object[] { invocation.getProxy().getNamespace(), invocation.getProxy().getActionName(), methodName });
    }
    Collection<Method> annotatedMethods = AnnotationUtils.getAnnotatedMethods(action.getClass(), new Class[] { SkipValidation.class });
    if (!annotatedMethods.contains(getActionMethod(action.getClass(), methodName))) {
      performBeanValidation(action, validator);
    }
    return invocation.invoke();
  }

因为我不希望在发生错误时调用ActionClass方法,所以我创建了BeanValidationInterceptor.class的副本并将其添加到struts.xml中。新类具有用于存储ConstraintViolations的实例变量,并且如果有错误,则doIntercept方法将返回“ input”。

private Set<ConstraintViolation<Object>> constraintViolations;

protected String doIntercept(ActionInvocation invocation) throws Exception {
    Validator validator = this.beanValidationManager.getValidator();
    if (validator == null) {
        LOG.debug("There is no Bean Validator configured in class path. Skipping Bean validation..");
        return invocation.invoke();
    }
    LOG.debug("Starting bean validation using validator: {}", new Object[] { validator.getClass() });

    Object action = invocation.getAction();
    ActionProxy actionProxy = invocation.getProxy();
    String methodName = actionProxy.getMethod();
    if (LOG.isDebugEnabled()) {
        LOG.debug("Validating [{}/{}] with method [{}]", new Object[] { invocation.getProxy().getNamespace(),
                invocation.getProxy().getActionName(), methodName });
    }
    Collection<Method> annotatedMethods = AnnotationUtils.getAnnotatedMethods(action.getClass(),
            new Class[] { SkipValidation.class });
    if (!annotatedMethods.contains(getActionMethod(action.getClass(), methodName))) {
        performBeanValidation(action, validator);
    }
    return this.constraintViolations.isEmpty() ? invocation.invoke() : "input";
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章