在JSF JavaEE应用程序中执行简单验证的正确方法是什么?

时间:2014-04-03 17:18:33

标签: validation jsf java-ee

例如,from和to date(从应该在before之前),整数范围(int a应该总是小于int b),如果选中某个复选框,则应在文本框等中输入一些值等。在我们的应用程序中有许多形式需要这种输入。在做任何事情之前,在何处以及如何正确验证它们并显示适当的错误消息而不关心简单的验证?

使用javascript在客户端验证所有这些内容?提交表单时,立即验证控制器上的每个字段?使用ajax + controller方法验证?实现一些自定义注释来标记具有各种限制的字段?

经过几天的努力,当你的测试者朋友以某种形式告诉你"来自" "到"之后的日期可以输入日期,这让开发人员伤心......

PS:具体来说,你将如何以及在哪里制作一个"从...到#34;日期验证?

2 个答案:

答案 0 :(得分:1)

除了简单的仅一个字段的bean验证之外,恕我直言只有两种情况:

  1. 验证类型仅针对一种情况:使用backing bean方法验证
  2. 验证类型是通用的或频繁的情况:构建您自己的验证器标签
  3. 我从不使用客户端验证,因为它不可靠。

    对于第2点,这是我的交叉日期验证器:

    @FacesValidator(DateValidator.VALIDATOR_ID)
    public class DateValidator implements Validator, PartialStateHolder
    {
        public static final String VALIDATOR_ID = "it.shape.DateValidator";
        public static final String BEFORE_MESSAGE_ID = VALIDATOR_ID + ".BEFORE";
        public static final String AFTER_MESSAGE_ID = VALIDATOR_ID + ".AFTER";
    
        private boolean transientValue = false;
        private boolean initialState;
    
        private String beforeId;
        private String afterId;
    
        public DateValidator()
        {
            super();
        }
    
        public DateValidator(String beforeId)
        {
            super();
            setBeforeId(beforeId);
        }
    
        public DateValidator(String beforeId, String afterId)
        {
            super();
            setBeforeId(beforeId);
            setAfterId(afterId);
        }
    
        public String getBeforeId()
        {
            return beforeId;
        }
    
        public void setBeforeId(String beforeId)
        {
    
            clearInitialState();
            this.beforeId = beforeId;
    
        }
    
        public String getAfterId()
        {
            return afterId;
        }
    
        public void setAfterId(String afterId)
        {
            clearInitialState();
            this.afterId = afterId;
        }
    
        @Override
        public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException
        {
            if((context == null) || (component == null))
            {
                throw new NullPointerException();
            }
    
            if(value != null)
            {
                if(!(value instanceof Date))
                {
                    throw new FaceletException("component [" + component.getClientId() + "] must have a Date value");
                }
    
                Date currentDate = (Date) value;
    
                if(beforeId != null)
                {
                    UIComponent target = component.findComponent(beforeId);
    
                    if(target == null)
                    {
                        throw new FaceletException("component [" + beforeId + "] not found!");
                    }
    
                    if(!(target instanceof ValueHolder))
                    {
                        throw new FaceletException("component [" + beforeId + "] must be a ValueHolder");
                    }
    
                    Object targetValue = ((ValueHolder) target).getValue();
    
                    if(targetValue != null)
                    {
                        if(!(targetValue instanceof Date))
                        {
                            throw new FaceletException("component [" + beforeId + "] must have a Date value");
                        }
    
                        Date targetDate = (Date) targetValue;
    
                        if(!currentDate.before(targetDate))
                        {
                            throw new ValidatorException(MessageUtils.getErrorMessage(BEFORE_MESSAGE_ID, MessageFactory.getLabel(context, target), DateFormat.getInstance().format(targetDate)));
                        }
                    }
    
                }
    
                if(afterId != null)
                {
                    UIComponent target = component.findComponent(afterId);
    
                    if(target == null)
                    {
                        throw new FaceletException("component [" + afterId + "] not found!");
                    }
    
                    if(!(target instanceof ValueHolder))
                    {
                        throw new FaceletException("component [" + afterId + "] must be a ValueHolder");
                    }
    
                    Object targetValue = ((ValueHolder) target).getValue();
    
                    if(targetValue != null)
                    {
                        if(!(targetValue instanceof Date))
                        {
                            throw new FaceletException("component [" + afterId + "] must have a Date value");
                        }
    
                        Date targetDate = (Date) targetValue;
    
                        if(!currentDate.after(targetDate))
                        {
                            throw new ValidatorException(MessageUtils.getErrorMessage(AFTER_MESSAGE_ID, MessageFactory.getLabel(context, target), DateFormat.getInstance().format(targetDate)));
                        }
                    }
    
                }
            }
        }
    
        @Override
        public Object saveState(FacesContext context)
        {
            if(context == null)
            {
                throw new NullPointerException();
            }
    
            if(!initialStateMarked())
            {
                Object values[] = new Object[2];
                values[0] = beforeId;
                values[1] = afterId;
                return(values);
            }
    
            return null;
        }
    
        @Override
        public void restoreState(FacesContext context, Object state)
        {
            if(context == null)
            {
                throw new NullPointerException();
            }
    
            if(state != null)
            {
                Object values[] = (Object[]) state;
                beforeId = (String) values[0];
                afterId = (String) values[1];
            }
        }
    
        @Override
        public boolean isTransient()
        {
            return(transientValue);
        }
    
        @Override
        public void setTransient(boolean transientValue)
        {
            this.transientValue = transientValue;
        }
    
        @Override
        public void markInitialState()
        {
            initialState = true;
        }
    
        @Override
        public boolean initialStateMarked()
        {
            return initialState;
        }
    
        @Override
        public void clearInitialState()
        {
            initialState = false;
        }
    }
    

    在taglib中注册:

    <tag>
        <description><![CDATA[cross field date validator]]></description>
        <tag-name>validateDate</tag-name>
        <validator>
            <validator-id>it.shape.DateValidator</validator-id>
        </validator>
        <attribute>
            <description>
                <![CDATA[The component identifier for 'before' testing]]>
            </description>
            <name>beforeId</name>
            <required>false</required>
        </attribute>
        <attribute>
            <description>
                <![CDATA[The component identifier for 'after' testing]]>
            </description>
            <name>afterId</name>
            <required>false</required>
        </attribute>
    </tag>
    

    享受:

    <h:outputLabel value="#{bundle.startDate}" />
    <h:panelGroup>
        <p:calendar id="startDate" value="#{page.entity.startDate}"
            label="#{bundle.startDate}" />
        <p:message for="startDate" />
    </h:panelGroup>
    
    <h:outputLabel value="#{bundle.endDate}" />
    <h:panelGroup>
        <p:calendar id="endDate" value="#{page.entity.endDate}">
            <s:validateDate afterId="startDate" />
        </p:calendar>
        <p:message for="endDate" />
    </h:panelGroup>
    

答案 1 :(得分:0)

可以使用firebug禁用Javascript。 Jsf有验证器,并且有用于bean验证的jsr。某些验证很复杂,需要其他对象的上下文,通常在业务层中执行。我不认为有一种标准的方式,而是许多方法的组合。