我目前正在设置一个使用hibernate bean验证的Stuts2应用程序来验证登录页面上的表单字段。我添加了所有必需的插件和依赖项,并配置了struts.xml以包含一个调用beanValidation拦截器的自定义堆栈。 / logon路径从 authInterceptor 中排除。不幸的是,即使填充了电子邮件和密码的表单字段,返回消息也是空白。我可以在调试器中看到电子邮件和密码是在LoginAction类中设置的,但它好像 beanValidation 没有这个信息。如果我最后将拦截器的顺序切换为 beanValidation ,则永远不会调用它。
Extension
HTML
<?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>
行动类
<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;
}
先行,因为我的理解是它负责填充defaultStack
中的bean。现在,验证正在进行中。但是,如果我将任何字段留空,则会返回正确的错误消息,但仍会调用ActionClass方法 ActionClass
。我现在想弄清楚如何让doLogon
短路,以便不调用beanValidation
。
答案 0 :(得分:1)
所以看来 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方法返回&#34; input&#34;如果有错误。
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";
}