一、Validation in the Action Controller:
1.Create error messages:
With null: store a message for the form as a whole
? context addMessage(null someFacesMessage);
– With component ID: store message specific to element
? context.addMessage("someID", someFacesMessage);
This assumes you used <h:form prependId="false">
FacesMessage message = new FacesMessage();
message.setDetail("error details");
message.setSummary("error summary");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
FacesContext context = FacesContext.getCurrentInstance();
if (getUserID().equals("")) {
context.addMessage(null,
new FacesMessage("UserID required"));
}
if (getKeyword().equals("")) {
context.addMessage(null,
new FacesMessage("Keyword required"));
}
if (context.getMessageList().size() > 0) {
return(null);
//Returning null means to redisplay the form
} else {
doBusinessLogicForValidData();
return("show-bid1");
}
2.Display error messages:
<h:messages/>
<h:message for="userId"/>
<h:message showSummary="true" showDetail="false"
errorClass="error"
id="errors1" for="userNo"/>
二、Validation via Type Conversion:
<h:inputText value="#{bidBean2.keyword}"
required="true"
requiredMessage="You must enter a keyword"
converterMessage="Amount must be a number"
id="keyword"/></td>
<td><h:message for="keyword" styleClass="error"/>
三、Validation using the Validation using the JSF Validator Tags:
f:validateDoubleRange
f:validateLength
f:validateLongRange
f:validateBean
f:validateRegex
f:validateRequired
<h:inputText value="#{bidBean2.userID}"
required="true"
requiredMessage="You must enter a user ID"
validatorMessage="ID must be 5 or 6 chars"
id="userID">
<f:validateLength minimum="5" maximum="6"/>
</h:inputText>
<h:message for="userID" styleClass="error"/>
当需要国际化时:
Message_zh_CN.properties:
例如:不能为空时:<h:inputText value="#{bidBean2.userID}" required="true" />的错误提示:
javax.faces.component.UIInput.REQUIRED=不能为空
四、Validation using Validation using Custom Validator Methods:
<h:inputText value="#{bidBean2.bidAmount}"
required="true"
requiredMessage="You must enter an amount"
converterMessage="Amount must be a number"
validator="#{bidBean2.validateBidAmount}"
id="amount"/>
public void
validateBidAmount(FacesContext context,
UIComponent componentToValidate,
Object value)
throws ValidatorException {
double bidAmount = ((Double)value).doubleValue();
double previousHighestBid = currentHighestBid();
if (bidAmount <= previousHighestBid) {
FacesMessage message =
new FacesMessage("Bid must be higher than current " +
"highest bid ($" +
previousHighestBid + ").");
throw new ValidatorException(message);
}
五、Creating a custom validator(
f:validator
):
@FacesValidator(value = "ipValidator")
public class IpValidator implements Validator {
private static final String IP_REGEX = "^([1-9]|[1-9][0-9]|1[0-
9][0-9]|2[0-4][0-9]|25[0-5])(\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-
4][0-9]|25[0-5])){3}$";
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
String ipAddress = (String) value;
Pattern mask = null;
mask = Pattern.compile(IP_REGEX);
Matcher matcher = mask.matcher(ipAddress);
if (!matcher.matches()) {
FacesMessage message = new FacesMessage();
message.setDetail("IP not valid");
message.setSummary("IP not valid");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
<h:inputText id="ipID" required="true" value="#{ipBean.ipValue}">
<f:validator validatorId="ipValidator"/>
</h:inputText>
六、bean validation:
作为
Java EE 6规范的一部分,JSR 303 -
bean
validation, 提供了一个独立于应用程序层的定义数据验证约束的机制。这个JSR允许我们通过
annotation来指定数据验证约束。当没有使用Java EE 6服务器的时候,我们也可以使用Hibernate Validator(JSR 303的另外一个实现)。
Annotation |
施加的约束 |
@NotNull |
Cannot be null |
@Min |
Must be a number and whose value must higher or equal to the specified number. |
@Max |
Must be a number and whose value must lower or equal to the specified number. |
@Size |
Must be between specified minimum and maximum limits |
@Pattern |
Must match the specified Java regular expression |
ValidationMessages.properties:
javax.validation.constraints.Size.message=size must be betweenss {min} and {max}
javax.validation.constraints.Size为@Size的全路径
ValidationMessages_zh_CN.properties:
javax.validation.constraints.Size.message=必须在{min}与{max}之间
org.hibernate.validator.constraints.NotEmpty.message=不能为空
验证:
@NotNull
@Size(min = 1, message = "{validator.notEmpty}")
public String getEmailAddress() {
return emailAddress;
}
页面验证:
<h:inputText id="age" value="#{myBean.age}">
<f:validateBean disabled="
true" />
</h:inputText>
自定义验证:
Email.java:
@Documented
@Constraint(validatedBy = EmailConstraintValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Email {
// message string should be {constraint.email}
String message() default "{validator.email}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
EmailConstraintValidator.java:
public class EmailConstraintValidator
implements ConstraintValidator<Email, String> {
private Pattern pattern;
public void initialize(Email parameters) {
// credit goes to http://www.regular-expressions.info/email.html
pattern = Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$",
Pattern.CASE_INSENSITIVE);
}
public boolean isValid(String value, ConstraintValidatorContext ctxt) {
if (value == null || value.length() == 0) {
return true;
}
return pattern.matcher(value).matches();
}
}
使用:
@Email
public String getEmailAddress() {
return emailAddress;
}
3.群组:
JSF 2.0还提供了<f:validateBean>标签,这个标签允许我们使用validation组。一个validation组定义了约束条件的一个子集,每个约束条件可以属于一个或多个组。我们可以在验证组件的时候使用validateiongGroups属性指定要验证的组。代码如下:
- <h:inputText value="#{bean.prop1}">
- <f:validateBean validationGroups="com.demo.validation.groups.Group1"/>
- </h:inputText>
我们可以使用如下的代码来定义一个组,如:
- package com.demo.validation.groups;
- public interface Group1{
- }
你没有看错,就是一个空的接口。
一个组可以扩展另外一个组,如
- package com.demo.validation.groups;
- public interface Group2 extends Group1{
- }
每个约束条件的annotation都有一个Group属性,我们可以通过该属性来指定这个约束条件属于那个组。如
@Size(min = 1, message = "Please enter the Email",groups=Group1.class)
如果没有指定groups,缺省的所有的约束都属于javax.validation.groups.Default组。这个组是一个内建的接口。
七、Customizing error messages for validators:
1.default messages from Message.propertie;
2.Even if we are in JSF 2.0, we need to configure this properties file in faces-config.xml.
This can be done as follows:
3.custom
error messages:
<application>
<locale-config>
<default-locale>en</default-locale>
</locale-config>
<message-bundle>users.MyMessages</message-bundle>
</application>
页面中:
<f:loadBundle basename="Messages" var="msg"/>
八、Binding validators to backing bean properties:
<h:inputText id="ageID" required="true"
value="#{userBean.userAge}">
<f:validateLongRange binding="#{userBean.longAge}"/>
</h:inputText>
private LongRangeValidator longAge;
public LongRangeValidator getLongAge(){
return this.longAge;
}
public void setLongAge(LongRangeValidator longAge){
longAge.setMinimum(18);
longAge.setMaximum(90);
this.longAge=longAge;
}
九、转换器:
f:convertDateTime
<h:body>
<b><h:outputText value="-Formatting the current date
and time-"/></b><br />
<h:outputText value="#{datetimeBean.currentdate}">
<f:convertDateTime type="date" dateStyle="medium"/>
</h:outputText>
<br />
<h:outputText value="#{datetimeBean.currentdate}">
<f:convertDateTime type="date" dateStyle="full"/>
</h:outputText>
<br />
<h:outputText value="#{datetimeBean.currentdate}">
<f:convertDateTime type="time" timeStyle="full"/>
</h:outputText>
<br />
<h:outputText value="#{datetimeBean.currentdate}">
<f:convertDateTime type="date" pattern="dd/mm/yyyy"/>
</h:outputText>
<br />
<h:outputText value="#{datetimeBean.currentdate}">
<f:convertDateTime dateStyle="full" pattern="yyyy-mm-dd"/>
</h:outputText>
<br />
<h:outputText value="#{datetimeBean.currentdate}">
<f:convertDateTime dateStyle="full"
pattern="yyyy.MM.dd 'at' HH:mm:ss z"/>
</h:outputText>
<br />
<h:outputText value="#{datetimeBean.currentdate}">
<f:convertDateTime dateStyle="full" pattern="h:mm a"/>
</h:outputText>
<br />
<h:outputText value="#{datetimeBean.currentdate}">
<f:convertDateTime dateStyle="long"
timeZone="EST" type="both" />
</h:outputText>
<br />
<h:outputText value="#{datetimeBean.currentdate}">
<f:convertDateTime locale="ro"
timeStyle="long" type="both"
dateStyle="full" />
</h:outputText>
<br />
<h:outputText value="#{datetimeBean.currentdate}">
<f:convertDateTime locale="de"
timeStyle="short" type="both"
dateStyle="full" />
</h:outputText>
</h:body>
f:convertNumber
<h:body>
<b><h:outputText value="-Formatting the double
value 12345.12345-"/></b><br />
<!-- Format as 00000.00000 -->
<h:outputText value="Format as 00000.00000: "/>
<h:outputText value="#{numbersBean.doubleNumber}">
<f:convertNumber type="number" maxIntegerDigits="5"
maxFractionDigits="5"
groupingUsed="false"/>
</h:outputText>
<br />
<!-- Format as 00000 -->
<h:outputText value="Format as 00000: "/>
<h:outputText value="#{numbersBean.doubleNumber}">
<f:convertNumber type="number" maxIntegerDigits="5"
maxFractionDigits="0"/>
</h:outputText>
<br />
<!-- Format as currency -->
<h:outputText value="Format as currency: "/>
<h:outputText value="#{numbersBean.doubleNumber}">
<f:convertNumber type="currency" currencySymbol="$"
maxIntegerDigits="5"
maxFractionDigits="2"/>
</h:outputText>
<br />
<!-- Format as percent -->
<h:outputText value="Format as percent: "/>
<h:outputText value="#{numbersBean.doubleNumber}">
<f:convertNumber type="percent" maxIntegerDigits="5"
maxFractionDigits="5"/>
</h:outputText>
<br />
<!-- Format as pattern #####,00% -->
<h:outputText value="Format as pattern #####,00%: "/>
<h:outputText value="#{numbersBean.doubleNumber}">
<f:convertNumber pattern="#####,00%"/>
</h:outputText>
</h:body>
Creating and using a custom converter
@FacesConverter(value = "customDateConverterImpl")
public class CustomDateConverterImpl implements Converter {
public String getAsString(FacesContext arg0, UIComponent arg1,
Object arg2) {
if (arg0 == null) {
throw new NullPointerException("context");
}
if (arg1 == null) {
throw new NullPointerException("component");
}
final Date date = (Date) arg2;
String DATE_FORMAT = "yyyy-MM-dd";
SimpleDateFormat sdf =
new SimpleDateFormat(DATE_FORMAT);
Calendar c1 = Calendar.getInstance(); // today
c1.setTime(date);
return sdf.format(c1.getTime());
}
public Object getAsObject(FacesContext arg0, UIComponent arg1,
String arg2) {
if (arg0 == null) {
throw new NullPointerException("context");
}
if (arg1 == null) {
throw new NullPointerException("component");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
Date today = df.parse(arg2);
return today;
} catch (ParseException e) {
FacesMessage message = new FacesMessage(FacesMessage.
SEVERITY_ERROR,
"Parser error!", "Cannot parse this date!");
throw new ConverterException(message);
}
}
}
<h:form id="customDateTimeID">
<h:inputText id="dateID" value="#{datetimeBean.currentdate}"
converter="customDateConverterImpl">
</h:inputText>
<h:message showSummary="true" showDetail="false" for="dateID"
style="color: red; text-decoration:overline"/>
<br />
<h:commandButton value="Submit"
action="selected?faces-redirect=true"/>
</h:form>
其中:@FacesConverter(value = "customDateConverterImpl")也可以在 faces-config.xml中配置
<converter>
<converter-id>CONVERTER_ID</converter-id>
<converter-class>CONVERTER_CLASS_NAME</converter-class>
</converter>
扩充某个转换器:
@FacesConverter(value = "customDateConverterExtend")
public class CustomDateConverterExtend extends DateTimeConverter {
public CustomDateConverterExtend() {
super();
setTimeZone(TimeZone.getDefault());
setPattern("yyyy-MM-dd");
}
}
Binding converters to backing bean properties:
<h:form id="numberFormID">
<h:inputText id="numberID" value="#{numbersBean.numbery}">
<f:convertNumber binding="#{numbersBean.number}" />
</h:inputText>
<h:message showSummary="true" showDetail="false" for="numberID"
style="color: red; text-decoration:overline"/>
<br />
<h:commandButton value="Submit"
action="selected?faces-redirect=true"/>
</h:form>
private NumberConverter number;
public NumberConverter getNumber(){
return this.number;
}
public void setNumber(NumberConverter number){
number.setType("currency");
number.setCurrencySymbol("$");
this.number=number;
}
f:converter
<!-- explicit conversion using the UIComponent converter attribute -->
<h:inputText id="userAgeID" required="true"
value="#{userBean.userAge}"
converter="javax.faces.Integer">
</h:inputText>
<!-- converter tag nested within a UIComponent -->
<h:inputText id="userAgeID" required="true"
value="#{userBean.userAge}">
<f:converter converterId="javax.faces.Integer"/>
</h:inputText>