appfuse学习笔记(四)struts2的表单校验

(1) 添加校验项
修改文件
src/main/resources/com/mycompany/app/model/Person-validation.xml
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
	<field name="person.firstname">
        <field-validator type="requiredstring">
            <message key="errors.required"/>
        </field-validator>
    </field>
    <field name="person.lastname">
        <field-validator type="requiredstring">
            <message key="errors.required"/>
        </field-validator>
    </field>
</validators>

重新编译,重新访问添加人员的页面,姓、名设置为空直接保存,报错
校验起了作用
(2) struts.xml文件的配置说明
......
<!-- Constants -->
    <!-- 常量设置 -->
    <!-- 
    	是否处于开发模式下
    	设置为true则表示处在开发模式下,应用出现异常和错误时将给开发人员提供更有益于调试的错误信息
    	设置为false则表示不处在开发模式下,一般应用在应用发布之后
     -->
    <constant name="struts.devMode" value="false"/>
    <!-- 指定应用的默认编码 -->
    <constant name="struts.i18n.encoding" value="UTF-8"/>
    <!-- 指定符合哪种后缀格式的请求由struts来处理 -->
    <constant name="struts.action.extension" value="html"/>
    <!-- 指定默认的ObjectFactory,设置值为spring后将由spring管理bean -->
    <constant name="struts.objectFactory" value="spring"/>
    <!-- 指定应用国际化需要的资源文件,多种时以逗号分隔 -->
    <constant name="struts.custom.i18n.resources" value="ApplicationResources,errors"/>
    <!-- 指定struts2的上传组件请求内容的最大字节数 -->
    <constant name="struts.multipart.maxSize" value="2097152"/>
    <!-- 指定模板主题,其它的还有simple,xhtml -->
    <constant name="struts.ui.theme" value="css_xhtml"/>
    <!-- 指定应用jsp文件的根路径 -->
    <constant name="struts.codebehind.pathPrefix" value="/WEB-INF/pages/"/>
    <!-- 是否允许在Action名中使用斜线 -->
<constant name="struts.enable.SlashesInActionNames" value="true"/>
。。。。。。

(3) 校验流程分析
struts.xml中定义默认包时
<!-- 定义default包,继承自struts-default包,将自动拥有struts-default包的所有配置 -->
<package name="default" extends="struts-default">

而在struts-default.xml中,配置了如下的拦截器
<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
<interceptor-stack name="paramsPrepareParamsStack">
<interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel</param>
                </interceptor-ref>
	</interceptor-stack>

当执行添加操作时会被validation拦截器拦截
AnnotationValidationInterceptor中的doIntercept方法
protected String doIntercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();
        if (action != null) {
            Method method = getActionMethod(action.getClass(), invocation.getProxy().getMethod());
            SkipValidation skip = (SkipValidation) method.getAnnotation(SkipValidation.class);
            if (skip != null) {
                return invocation.invoke();
            }
        }
        return super.doIntercept(invocation);
}

再看父类的doIntercept方法
protected String doIntercept(ActionInvocation invocation) throws Exception {
doBeforeInvocation(invocation);
    return invocation.invoke();
}

再看触发前要执行的方法doBeforeInvocation(invocation)
protected void doBeforeInvocation(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();
        String context = invocation.getProxy().getActionName();
        String method = invocation.getProxy().getMethod();
        if (log.isDebugEnabled()) {
            log.debug("Validating "
                    + invocation.getProxy().getNamespace() + "/" + invocation.getProxy().getActionName() + " with method "+ method +".");
        }
        if (validateAnnotatedMethodOnly) {
           ActionValidatorManagerFactory.getInstance().validate(action, context, method);
        } else {
            ActionValidatorManagerFactory.getInstance().validate(action, context);
        }
}

再看ActionValidatorManagerFactory.getInstance()
public class ActionValidatorManagerFactory {
    private static final Log LOG = LogFactory.getLog(ActionValidatorManagerFactory.class);
    private static ActionValidatorManager instance = new DefaultActionValidatorManager();
    static {
        try {
            Class c = ClassLoaderUtil.loadClass("com.opensymphony.xwork2.validator.AnnotationActionValidatorManager", ActionValidatorManagerFactory.class);
            LOG.info("Detected AnnotationActionValidatorManager, initializing it...");
            instance = (ActionValidatorManager) c.newInstance();
        } catch (ClassNotFoundException e) {
            // this is fine, just fall back to the default object type determiner
        } catch (Exception e) {
            throw new XWorkException(e);
        }
    }
    public static void setInstance(ActionValidatorManager instance) {
        ActionValidatorManagerFactory.instance = instance;
    }
    public static ActionValidatorManager getInstance() {
        return instance;
    }
}

再看com.opensymphony.xwork2.validator.AnnotationActionValidatorManager中的validate(Object object, String context, ValidatorContext validatorContext, String method)方法
public void validate(Object object, String context, ValidatorContext validatorContext, String method) throws ValidationException {
        List<Validator> validators = getValidators(object.getClass(), context, method);
        Set<String> shortcircuitedFields = null;

        for (final Validator validator: validators) {
            try {
                validator.setValidatorContext(validatorContext);

                if (LOG.isDebugEnabled()) {
                    LOG.debug("Running validator: " + validator + " for object " + object + " and method " + method);
                }

                FieldValidator fValidator = null;
                String fullFieldName = null;

                if (validator instanceof FieldValidator) {
                    fValidator = (FieldValidator) validator;
                    fullFieldName = fValidator.getValidatorContext().getFullFieldName(fValidator.getFieldName());

                    if ((shortcircuitedFields != null) && shortcircuitedFields.contains(fullFieldName)) {
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("Short-circuited, skipping");
                        }

                        continue;
                    }
                }

                if (validator instanceof ShortCircuitableValidator && ((ShortCircuitableValidator) validator).isShortCircuit())
                {
                    // get number of existing errors
                    List<String> errs = null;

                    if (fValidator != null) {
                        if (validatorContext.hasFieldErrors()) {
                            Collection<String> fieldErrors = (Collection<String>) validatorContext.getFieldErrors().get(fullFieldName);

                            if (fieldErrors != null) {
                                errs = new ArrayList<String>(fieldErrors);
                            }
                        }
                    } else if (validatorContext.hasActionErrors()) {
                        Collection<String> actionErrors = validatorContext.getActionErrors();

                        if (actionErrors != null) {
                            errs = new ArrayList<String>(actionErrors);
                        }
                    }

                    validator.validate(object);

                    if (fValidator != null) {
                        if (validatorContext.hasFieldErrors()) {
                            Collection<String> errCol = (Collection<String>) validatorContext.getFieldErrors().get(fullFieldName);

                            if ((errCol != null) && !errCol.equals(errs)) {
                                if (LOG.isDebugEnabled()) {
                                    LOG.debug("Short-circuiting on field validation");
                                }

                                if (shortcircuitedFields == null) {
                                    shortcircuitedFields = new TreeSet<String>();
                                }

                                shortcircuitedFields.add(fullFieldName);
                            }
                        }
                    } else if (validatorContext.hasActionErrors()) {
                        Collection<String> errCol = validatorContext.getActionErrors();

                        if ((errCol != null) && !errCol.equals(errs)) {
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("Short-circuiting");
                            }

                            break;
                        }
                    }

                    continue;
                }

                validator.validate(object);
            } finally {
                validator.setValidatorContext( null );
            }

        }
    }

最后看一下校验必填项的实现
 <validator  name="requiredstring" class ="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>

public class RequiredFieldValidator extends FieldValidatorSupport {

    public void validate(Object object) throws ValidationException {
        String fieldName = getFieldName();
        Object value = this.getFieldValue(fieldName, object);

        if (value == null) {
            addFieldError(fieldName, object);
        }
    }
}

到这里,校验表单,出错后将执行addFieldError方法

你可能感兴趣的:(spring,xml,struts,配置管理,Appfuse)