Struts2系列:(20)ValidationAware

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Struts2系列:(20)ValidationAware相关的知识,希望对你有一定的参考价值。

本文主要介绍ValidationAware、ValidationAwareSupport和ActionSupport(因为ActionSupport类也实现了ValidationAware接口)。


1、ValidationAware

ValidationAware接口,能够记录Action级别和Field级别的错误。

package com.opensymphony.xwork2;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * ValidationAware classes can accept Action (class level) or field level error messages. 
 * Action level messages are kept in a Collection. 
 * Field level error messages are kept in a Map from String field name to a List of field error msgs.
 *
 * @author plightbo 
 */
public interface ValidationAware {

    /**1、ActionError相关
     * Set the Collection of Action-level String error messages.
     */
    void setActionErrors(Collection<String> errorMessages);

    /**
     * Get the Collection of Action-level error messages for this action. Error messages should not
     * be added directly here, as implementations are free to return a new Collection or an
     * Unmodifiable Collection.
     */
    Collection<String> getActionErrors();

    /**
     * Add an Action-level error message to this Action.
     */
    void addActionError(String anErrorMessage);

    /**
     * Check whether there are any Action-level error messages.
     *
     * @return true if any Action-level error messages have been registered
     */
    boolean hasActionErrors();

    /**2、ActionMessage相关
     * Set the Collection of Action-level String messages (not errors).
     *
     */
    void setActionMessages(Collection<String> messages);

    /**
     * Get the Collection of Action-level messages for this action. Messages should not be added
     * directly here, as implementations are free to return a new Collection or an Unmodifiable
     * Collection.
     *
     */
    Collection<String> getActionMessages();

    /**
     * Add an Action-level message to this Action.
     *
     */
    void addActionMessage(String aMessage);

    /**
     * Checks whether there are any Action-level messages.
     *
     * @return true if any Action-level messages have been registered
     */
    boolean hasActionMessages();

    /**3、FieldError相关
     * Set the field error map of fieldname (String) to Collection of String error messages.
     */
    void setFieldErrors(Map<String, List<String>> errorMap);

    /**
     * Get the field specific errors associated with this action. Error messages should not be added
     * directly here, as implementations are free to return a new Collection or an Unmodifiable
     * Collection.
     */
    Map<String, List<String>> getFieldErrors();

    /**
     * Add an error message for a given field.
     *
     */
    void addFieldError(String fieldName, String errorMessage);

    /**
     * Check whether there are any field errors associated with this action.
     *
     * @return whether there are any field errors
     */
    boolean hasFieldErrors();


    /**4、判断是否包含任何的action errors或field errors
     * Checks whether there are any action errors or field errors.
     * <p/>
     * <b>Note</b>: that this does not have the same meaning as in WW 1.x.
     *
     * @return <code>(hasActionErrors() || hasFieldErrors())</code>
     */
    boolean hasErrors();
}



2、ValidationAwareSupport

ValidationAwareSupport类是对ValidationAware的默认实现

package com.opensymphony.xwork2;

import java.io.Serializable;
import java.util.*;

/**
 * Provides a default implementation of ValidationAware. Returns new collections for
 * errors and messages (defensive copy).
 *
 */
public class ValidationAwareSupport implements ValidationAware, Serializable {

    private Collection<String> actionErrors;
    private Collection<String> actionMessages;
    private Map<String, List<String>> fieldErrors;

	//1、ActionErrors相关
    public synchronized void setActionErrors(Collection<String> errorMessages) {
        this.actionErrors = errorMessages;
    }

    public synchronized Collection<String> getActionErrors() {
        return new LinkedList<String>(internalGetActionErrors());
    }

    public synchronized void addActionError(String anErrorMessage) {
        internalGetActionErrors().add(anErrorMessage);
    }

    public synchronized boolean hasActionErrors() {
        return (actionErrors != null) && !actionErrors.isEmpty();
    }

    private Collection<String> internalGetActionErrors() {
        if (actionErrors == null) {
            actionErrors = new ArrayList<String>();
        }

        return actionErrors;
    }

	//2、ActionMessages相关
    public synchronized void setActionMessages(Collection<String> messages) {
        this.actionMessages = messages;
    }

    public synchronized Collection<String> getActionMessages() {
        return new LinkedList<String>(internalGetActionMessages());
    }

    public synchronized void addActionMessage(String aMessage) {
        internalGetActionMessages().add(aMessage);
    }

    public synchronized boolean hasActionMessages() {
        return (actionMessages != null) && !actionMessages.isEmpty();
    }

    /**
     * Clears action errors list.
     * <p/>
     * Will clear the list that contains action errors.
     */
    public synchronized void clearActionErrors() {
        internalGetActionErrors().clear();
    }

    /**
     * Clears messages list.
     * <p/>
     * Will clear the list that contains action messages.
     */
    public synchronized void clearMessages() {
        internalGetActionMessages().clear();
    }

    private Collection<String> internalGetActionMessages() {
        if (actionMessages == null) {
            actionMessages = new ArrayList<String>();
        }

        return actionMessages;
    }

	//3、FieldErrors相关
    public synchronized void setFieldErrors(Map<String, List<String>> errorMap) {
        this.fieldErrors = errorMap;
    }

    public synchronized Map<String, List<String>> getFieldErrors() {
        return new LinkedHashMap<String, List<String>>(internalGetFieldErrors());
    }

    public synchronized void addFieldError(String fieldName, String errorMessage) {
        final Map<String, List<String>> errors = internalGetFieldErrors();
        List<String> thisFieldErrors = errors.get(fieldName);

        if (thisFieldErrors == null) {
            thisFieldErrors = new ArrayList<String>();
            errors.put(fieldName, thisFieldErrors);
        }

        thisFieldErrors.add(errorMessage);
    }

    public synchronized boolean hasFieldErrors() {
        return (fieldErrors != null) && !fieldErrors.isEmpty();
    }

    /**
     * Clears field errors map.
     * <p/>
     * Will clear the map that contains field errors.
     */
    public synchronized void clearFieldErrors() {
        internalGetFieldErrors().clear();
    }

    private Map<String, List<String>> internalGetFieldErrors() {
        if (fieldErrors == null) {
            fieldErrors = new LinkedHashMap<String, List<String>>();
        }

        return fieldErrors;
    }

	//4、通用的功能
    public synchronized boolean hasErrors() {
        return (hasActionErrors() || hasFieldErrors());
    }

    /**
     * Clears all error list/maps.
     * <p/>
     * Will clear the map and list that contain
     * field errors and action errors.
     */
    public synchronized void clearErrors() {
        internalGetFieldErrors().clear();
        internalGetActionErrors().clear();
    }

    /**
     * Clears all error and messages list/maps.
     * <p/>
     * Will clear the maps/lists that contain
     * field errors, action errors and action messages.
     */
    public synchronized void clearErrorsAndMessages() {
        internalGetFieldErrors().clear();
        internalGetActionErrors().clear();
        internalGetActionMessages().clear();
    }

}






3、ActionSupport

ActionSupport类也实现了ValidationAware接口

public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {

	//1、定义ValidationAwareSupport类型成员变量
	private final ValidationAwareSupport validationAware = new ValidationAwareSupport();

	//2、ActionErrors相关
    public void setActionErrors(Collection<String> errorMessages) {
        validationAware.setActionErrors(errorMessages);
    }

    public Collection<String> getActionErrors() {
        return validationAware.getActionErrors();
    }

    public void addActionError(String anErrorMessage) {
        validationAware.addActionError(anErrorMessage);
    }

    public boolean hasActionErrors() {
        return validationAware.hasActionErrors();
    }

    /**
     * Clears action errors. Useful for Continuations and other situations
     * where you might want to clear parts of the state on the same action.
     */
    public void clearActionErrors() {
        validationAware.clearActionErrors();
    }

	//3、ActionMessages相关
    public void setActionMessages(Collection<String> messages) {
        validationAware.setActionMessages(messages);
    }

    public Collection<String> getActionMessages() {
        return validationAware.getActionMessages();
    }

    public void addActionMessage(String aMessage) {
        validationAware.addActionMessage(aMessage);
    }

    public boolean hasActionMessages() {
        return validationAware.hasActionMessages();
    }

    /**
     * Clears messages. Useful for Continuations and other situations
     * where you might want to clear parts of the state on the same action.
     */
    public void clearMessages() {
        validationAware.clearMessages();
    }

	//4、FieldErrors相关
    public void setFieldErrors(Map<String, List<String>> errorMap) {
        validationAware.setFieldErrors(errorMap);
    }

    public Map<String, List<String>> getFieldErrors() {
        return validationAware.getFieldErrors();
    }

    public void addFieldError(String fieldName, String errorMessage) {
        validationAware.addFieldError(fieldName, errorMessage);
    }

    public boolean hasFieldErrors() {
        return validationAware.hasFieldErrors();
    }

    /**
     * Clears field errors. Useful for Continuations and other situations
     * where you might want to clear parts of the state on the same action.
     */
    public void clearFieldErrors() {
        validationAware.clearFieldErrors();
    }




	//5、通用功能
    public boolean hasErrors() {
        return validationAware.hasErrors();
    }

    /**
     * Clears all errors. Useful for Continuations and other situations
     * where you might want to clear parts of the state on the same action.
     */
    public void clearErrors() {
        validationAware.clearErrors();
    }

    /**
     * Clears all errors and messages. Useful for Continuations and other situations
     * where you might want to clear parts of the state on the same action.
     */
    public void clearErrorsAndMessages() {
        validationAware.clearErrorsAndMessages();
    }


	//其它代码。。。

}


4、DefaultWorkflowInterceptor


上面谈到ValidationAware,以及实现ValidatorAware接口了类(ValidatorAwareSupport类和ActionSupport类)。

ValidationAware接口能够添加Action级别和Field级别的错误,但是使用这些错误,是由DefaultWorkflowInterceptor完成。


先来看一下DefaultWorkflowInterceptor类的继承结构:

技术分享

public interface Interceptor extends Serializable {
    //...
}
public abstract class AbstractInterceptor implements Interceptor {
    //...
}
public abstract class MethodFilterInterceptor extends AbstractInterceptor {
    //...
}
public class DefaultWorkflowInterceptor extends MethodFilterInterceptor {
    //...
}


Interceptor接口定义了一些方法。

技术分享

AbstractInterceptor抽象类对Interceptor进行了“空实现”。

技术分享

在MethodFilterInterceptor抽象类中,覆写intercept方法,在itercept方法的内部,又调用了doIntercept方法。doIntercept方法是MethodFilterInterceptor抽象类的一个抽象方法。



/*
*Method是方法,Filter是过滤,MethodFilterInterceptor是对方法名进行过滤的拦截器。
*对方法名进行过滤的依据就是两个参数:excludeMethods和includeMethods。includeMethods的优先级比较高。
*MethodFilterInterceptor is an abstract Interceptor used as a base class for interceptors
*that will filter execution based on method names according to specified included/excluded method lists.
*
*当前拦截器可设置的参数
*Settable parameters are as follows:
*
*excludeMethods - method names to be excluded from interceptor processing
*includeMethods - method names to be included in interceptor processing
*NOTE: If method name are available in both includeMethods and excludeMethods,
*it will be considered as an included method: includeMethods takes precedence over excludeMethods.
*
*哪些拦截器继承了当前拦截器
*Interceptors that extends this capability include:
*
*TokenInterceptor
*TokenSessionStoreInterceptor
*DefaultWorkflowInterceptor
*ValidationInterceptor
*/
public abstract class MethodFilterInterceptor extends AbstractInterceptor {
    protected Set<String> excludeMethods = Collections.emptySet();
    protected Set<String> includeMethods = Collections.emptySet();

    public void setExcludeMethods(String excludeMethods) {
        this.excludeMethods = TextParseUtil.commaDelimitedStringToSet(excludeMethods);
    }

    public Set<String> getExcludeMethodsSet() {
    	return excludeMethods;
    }

    public void setIncludeMethods(String includeMethods) {
        this.includeMethods = TextParseUtil.commaDelimitedStringToSet(includeMethods);
    }

    public Set<String> getIncludeMethodsSet() {
    	return includeMethods;
    }

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        if (applyInterceptor(invocation)) {
            return doIntercept(invocation);
        }
        return invocation.invoke();
    }

    protected boolean applyInterceptor(ActionInvocation invocation) {
        String method = invocation.getProxy().getMethod();
        //Static method to decide if the specified method should be apply 
	//depending on the set of excludeMethods and includeMethods. 
        boolean applyMethod = MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, method);
        return applyMethod;
    }

    /**
     * Subclasses must override to implement the interceptor logic.
     *
     * @param invocation the action invocation
     * @return the result of invocation
     * @throws Exception
     */
    protected abstract String doIntercept(ActionInvocation invocation) throws Exception;

}


在DefaultWorkflowInterceptor类中覆写父类的doIntercept方法。在doIntercept方法内,实现对ValidationAware对象的操作。

public class DefaultWorkflowInterceptor extends MethodFilterInterceptor {

    private String inputResultName = Action.INPUT;

    /**
     * Intercept {@link ActionInvocation} and returns a <code>inputResultName</code>
     * when action / field errors is found registered.
     *
     * @return String result name
     */
    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();
		//判断当前action是否实现了ValidationAware接口
        if (action instanceof ValidationAware) {
            ValidationAware validationAwareAction = (ValidationAware) action;
			//判断当前ValidationAware类型的对象中,是否包含错误
            if (validationAwareAction.hasErrors()) {
                String resultName = inputResultName;//inputResultName是成员变量,它的值是Action.INPUT
                return resultName;//发现错误,返回Action.INPUT,不再执行后续的Action的业务逻辑
            }
        }
		
        return invocation.invoke();
    }

}















以上是关于Struts2系列:(20)ValidationAware的主要内容,如果未能解决你的问题,请参考以下文章

Struts2系列:Struts2配置文件

struts2系列:struts2参数传递错误struts2的输入错误验证

struts2系列:struts2入门(struts2的产生struts2的工作流程搭建struts2开发环境)

Struts2系列——struts2的result

Struts2系列:(14)Struts2验证

Struts2系列第一篇 快速了解Struts2