错误讯息处理
在使用标准转换器或验证器时,当发生错误时,会有一些预设的错误讯息显示,这些讯息可以使用<h:messages>或<h:message>卷标来显示出来,而这些预设的错误讯息也是可以修改的,您所要作的是提供一个讯息资源文件,例如:
messages.properties
javax.faces.component.UIInput.CONVERSION=Format Error. javax.faces.component.UIInput.REQUIRED=Please input your data.
javax.faces.component.UIInput.CONVERSION是用来设定当转换器发现错误时显示的讯息,而javax.faces.component.UIInput.REQUIRED是在标签设定了required为true,而使用者没有在字段输入时显示的错误讯息。
您要在faces-config.xml中告诉JSF您使用的讯息文件名称,例如:
faces-config.xml
<?xml version="1.0"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_0.dtd"> <faces-config> <application> <local-config> <default-locale>en</default-locale> <supported-locale>zh_cn</supported-locale> </local-config> <message-bundle>messages</message-bundle> </application> ..... </faces-config>
在这边我们设定了讯息档案的名称为messages_xx_YY.properties,其中xx_YY是根据您的Locale来决定,转换器或验证器的错误讯息如果有设定的话,就使用设定值,如果没有设定的话,就使用默认值。验证器错误讯息,除了上面的javax.faces.component.UIInput.REQUIRED之外,还有以下的几个:
javax.faces.validator.NOT_IN_RANGE
javax.faces.validator.DoubleRangeValidator.MAXIMUM
javax.faces.validator.LongRangeValidator.MAXIMUM
javax.faces.validator.DoubleRangeValidator.MINIMUM
javax.faces.validator.LongRangeValidator.MINIMUM
javax.faces.validator.DoubleRangeValidator.TYPE、
javax.faces.validator.LongRangeValidator.TYPE
javax.faces.validator.LengthValidator.MAXIMUM
javax.faces.validator.LengthValidator.MINIMUM
讯息的显示有概述讯息与详述讯息,如果是详述讯息,则在识别上加上 "_detail",例如:
javax.faces.component.UIInput.CONVERSION=Error. javax.faces.component.UIInput.CONVERSION_detail= Detail Error.
除了在讯息资源文件中提供讯息,您也可以在程序中使用FacesMessage来提供讯息,例如在自订验证器中我们就这么用过:
.... if(password.length() < 6) { FacesMessage message = new FacesMessage( FacesMessage.SEVERITY_ERROR, "字符长度小于6", "字符长度不得小于6"); throw new ValidatorException(message); } ....
最好的方法是在讯息资源文件中提供讯息,这么一来如果我们要修改讯息,就只要修改讯息资源文件的内容,而不用修改程序,来看一个简单的例子,假设我们的讯息资源文件中有以下的内容:
javax.faces.component.UIInput.REQUIRED=\u8BF7\u8F93\u5165\u6570\u636E wsz.ncepu.password_all_number_errorMessage=\u5BC6\u7801\u5FC5\u987B\u5305\u542B\u5B57\u6BCD wsz.ncepu.password_length_errorMessage=\u5BC6\u7801\u7684\u957F\u5EA6\u5728{0}\u548C{1}\u4E4B\u95F4
则我们可以在程序中取得讯息资源文件的内容,例如:
import java.util.Locale; import java.util.ResourceBundle; import javax.faces.context.FacesContext; improt javax.faces.component.UIComponent; import javax.faces.application.Application; import javax.faces.application.FacesMessage; .... public void xxxMethod(FacesContext context, UIComponent component, Object obj) { // 取得应用程序代表对象 Application application = context.getApplication(); // 取得讯息档案主名称 String messageFileName = application.getMessageBundle(); // 取得当前 Locale 对象 Locale locale = context.getViewRoot().getLocale(); // 取得讯息绑定 ResourceBundle 对象 ResourceBundle rsBundle = ResourceBundle.getBundle(messageFileName, locale); String message = rsBundle.getString("wsz.ncepu.password_length_errorMessage"); FacesMessage facesMessage = new FacesMessage( FacesMessage.SEVERITY_FATAL, message, message); .... } .... ....
接下来您可以将FacesMessage对象填入ValidatorException或ConverterException后再丢出,FacesMessage建构时所使用的三个参数是严重程度、概述讯息与详述讯息,严重程度有SEVERITY_FATAL、SEVERITY_ERROR、SEVERITY_WARN与SEVERITY_INFO四种。
如果需要在讯息资源文件中设定{0}、{1}等参数,则可以如下:
.... String message = rsBundle.getString( "wsz.ncepu.password_length_errorMessage"); Object[] params = {"param1", "param2"}; message = java.text.MessageFormat.format(message, params); FacesMessage facesMessage = new FacesMessage( FacesMessage.SEVERITY_FATAL, message, message);
如此一来,在显示讯息时,wsz.ncepu.password_length_errorMessage的{0}与{1}的位置就被"param1"与"param2"所取代。
完整代码如下:
UserBean.java
package wsz.ncepu; import java.util.Locale; import java.util.ResourceBundle; import javax.faces.application.Application; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.validator.ValidatorException; public class UserBean { private String name; private String password; private String errMessage; public void setName(String name) { this.name = name; } public String getName() { return name; } public void setPassword(String password) { this.password = password; } public String getPassword() { return password; } public void setErrMessage(String errMessage) { this.errMessage = errMessage; } public String getErrMessage() { return errMessage; } public String verify() { if (!name.equals("justin") || !password.equals("123456")) { errMessage = "名称或密码错误"; return "failure"; } else { return "success"; } } public void validate(FacesContext context, UIComponent component, Object obj) throws ValidatorException { String password = (String) obj; // 取得应用程序代表对象 Application application = context.getApplication(); // 取得资源文件主名称 String messageFileName = application.getMessageBundle(); // 取得当前 Locale 对象 Locale local = context.getViewRoot().getLocale(); // 取得ResourceBundle 对象 ResourceBundle rsBundle = ResourceBundle.getBundle(messageFileName, local); // 取得资源文件中字符串 String password_length_message = rsBundle .getString("wsz.ncepu.password_length_errorMessage"); String password_all_number_errorMessage = rsBundle .getString("wsz.ncepu.password_all_number_errorMessage"); Object[] params = { "6", "12" }; password_length_message = java.text.MessageFormat.format( password_length_message, params); if (password.length() < 6 || password.length() > 12) { FacesMessage message = new FacesMessage( FacesMessage.SEVERITY_ERROR, password_length_message, password_length_message); throw new ValidatorException(message); } if (password.matches(".+[0-9]+")) { FacesMessage message = new FacesMessage( FacesMessage.SEVERITY_ERROR, password_all_number_errorMessage, password_all_number_errorMessage); throw new ValidatorException(message); } } }
index.jsp
<%@taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <%@page contentType="text/html;charset=utf-8"%> <html> <head> <title>第一个JSF程序</title> </head> <body> <f:view> <h:form> <h3> 请输入您的名称 </h3> <h:messages> </h:messages> <p> 名称: <h:inputText value="#{user.name}" /> <p> 密码: <h:inputSecret value="#{user.password}" required="true" validator="#{user.validate}"> </h:inputSecret> <p> <h:commandButton value="送出" action="#{user.verify}" /> </h:form> </f:view> </body> </html>
效果如下