例如,from和to date(从应该在before之前),整数范围(int a应该总是小于int b),如果选中某个复选框,则应在文本框等中输入一些值等。在我们的应用程序中有许多形式需要这种输入。在做任何事情之前,在何处以及如何正确验证它们并显示适当的错误消息而不关心简单的验证?
使用javascript在客户端验证所有这些内容?提交表单时,立即验证控制器上的每个字段?使用ajax + controller方法验证?实现一些自定义注释来标记具有各种限制的字段?
经过几天的努力,当你的测试者朋友以某种形式告诉你"来自" "到"之后的日期可以输入日期,这让开发人员伤心......
PS:具体来说,你将如何以及在哪里制作一个"从...到#34;日期验证?
答案 0 :(得分:1)
除了简单的仅一个字段的bean验证之外,恕我直言只有两种情况:
我从不使用客户端验证,因为它不可靠。
对于第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。某些验证很复杂,需要其他对象的上下文,通常在业务层中执行。我不认为有一种标准的方式,而是许多方法的组合。