经典Java EE企业应用实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.9 利用JSF的消息

对于MVC框架而言,系统处理过程总有一些额外的消息需要传递给浏览者,这些消息当然可以使用托管Bean的属性来维护。但对于JSF框架来说,使用JSF消息机制是更好的解决方法。

在JSF生命周期中,任何组件都可以创建一个JSF消息,JSF消息通常由FacesContext来添加,而且FacesContext会自动维护应用的消息队列。当JSF生命周期结束(进入生成响应阶段)时,视图页面只要使用简单的<h:messages.../>或<h:message.../>即可显示这些消息。

JSF一共支持4种级别的消息:

一般信息:由FacesMessage.SEVERITY_INFO常量代表。

警告消息:由FacesMessage.SEVERITY_WARNING常量代表。

错误消息:由FacesMessage.SEVERITY_ERROR常量代表。

致命错误:由FacesMessage.SEVERITY_FATAL常量代表。

当程序要使用JSF消息时,可以通过构造器创建一个FacesMessage对象,该对象就代表JSF消息。创建该对象时可传入3个参数:

severity:指定消息的严重级别,就是前面介绍的4种级别。

summary:指定消息的摘要信息。

detail:指定消息的详细信息。

一旦得到了FacesMessage对象之后,接下来就可使用FacesContext将该JSF消息添加到消息队列中。添加到消息队列中的消息可使用<h:messages.../>或<h:message.../>在生成响应阶段显示出来。

使用FacesContext添加JSF消息是通过调用FacesContext的如下方法来实现的:

addMessage(String clientId, FacesMessage message):该方法的第一个参数指定该消息关联到哪个页面组件,第二个参数指定添加到消息队列中的FacesMessage对象。

例如,如下简单的用户注册页面。

程序清单:codes\02\2.9\FacesMessage\regist.jsp

      <f:view>
      <html>
          <head>
              <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
              <title>JSF消息测试</title>
          </head>
          <body>
              <h1><h:outputText value="用户注册"/></h1>
              <h:form>
              <!-- 将下面UI组件的值绑定到Bean属性 -->
              用户名:<h:inputText value="#{userBean.name}"/><br/>
              <!-- 将下面UI组件的值绑定到Bean属性 -->
              年龄:<h:inputText id="age" value="#{userBean.age}"/><br/>
              <h:commandButton value="注册" action="#{userBean.regist}"/><br/>
              </h:form>
          </body>
      </html>
      </f:view>

上面页面中有一行粗体字代码,这行粗体字代码将一个单行文本框绑定到userBean的age属性,该userBean是一个非常简单的托管Bean,它会在处理用户注册时对用户的年龄进行提醒:如果用户输入的年龄大于100或小于0,该托管Bean将会使用JSFMessage进行提醒。下面是该托管Bean的类代码。

程序清单:codes\02\2.9\FacesMessage\WEB-INF\src\org\crazyit\jsf\UserBean.java

      public class UserBean
      {
          private String name;
          private int age;
          //无参数的构造器
          public UserBean()
          {
          }
          //初始化全部属性的构造器
          public UserBean(String name, int age)
          {
              this.name = name;
              this.age = age;
          }
          //省略name属性的setter和getter方法
          ...
          //省略age属性的setter和getter方法
          public void setAge(int age)
          {
              if (age > 100 || age < 0)
              {
                  FacesContext.getCurrentInstance()
                      .addMessage("age"
                      , new FacesMessage(FacesMessage.SEVERITY_FATAL
                      , "年龄不对" , "年龄必须小于100,且大于0 "));              }
              this.age = age;
          }
          public int getAge()
          {
              return this.age;
          }
          //简单的处理逻辑,直接返回“success”字符串
          public String regist()
          {
              return "success";
          }
      }

上面程序中的粗体字代码判断当用户输入的age大于100或age小于0时,系统将会自动添加一个FacesMessage消息,该消息的summary为“年龄必须小于100,且大于0”。

在faces-config.xml文件中配置该托管Bean,并为该Bean配置导航规则,指定当该托管Bean返回“success”字符串时,应用将导航到show.jsp页面。show.jsp页面代码如下:

程序清单:codes\02\2.9\FacesMessage\show.jsp

      <f:view>
      <html>
          ...
          <body>
              <h:messages/>
              <h1>注册结果</h1>
              用户名:<h:outputText value="#{userBean.name}"/><br/>
              年龄:<h:outputText value="#{userBean.age}" /><br/>
          </body>
      </html>
      </f:view>

UserBean在setAge()方法中通过FacesContext添加了一条FacesMessage消息,该页面就可通过粗体字代码所示的<h:messages/>标签将它显示出来。关于<h:message.../>和<h:messages.../>标签的用法后面还会有介绍,此处不详述。

如果用户输入的age属性大于100,将可以看到如图2.32所示的页面。

图2.32 JSF的消息

从上面示例可以看出,当使用FacesContext添加JSF消息之后,这些JSF消息并不会改变JSF生命周期的推进。

应用对用户输入的age属性不只是简单地警告,而是强制要求age属性必须在0~100之间,否则系统直接退回regist.jsp,那我们可以在setAge()方法中显式抛出异常。代码如下所示:

程序清单:codes\02\2.9\FacesException\WEB-INF\src\org\crazyit\jsf\UserBean.java

      public class UserBean
      {
          private String name;
          private int age;
          //无参数的构造器
          public UserBean()
          {
          }
          //初始化全部属性的构造器
          public UserBean(String name, int age)
          {
              this.name = name;
              this.age = age;
          }
          //省略name属性的setter和getter方法
          ...
          //age属性的setter和getter方法
          public void setAge(int age)
          {
              if (age > 100 || age < 0)
              {
                  throw new RuntimeException("年龄必须小于100,且大于0!");
              }
              this.age = age;
          }
          public int getAge()
          {
              return this.age;
          }
          //简单的处理逻辑,直接返回“success”字符串
          public String regist()
          {
              return "success";
          }
      }

从上面页面中可以看到,当用户输入的age不在0~100之内时,UserBean的setAge()方法将会抛出一个RuntimeException异常,这个异常信息是“年龄必须小于100,且大于0!”,JSF的<h:messages.../>标签和<h:message.../>标签都可输出这个异常信息。

为了在regist.jsp页面上输出setAge()方法中抛出的异常,可以将该页面代码改为如下形式:

程序清单:codes\02\2.9\FacesException\regist.jsp

      <f:view>
      <html>
          <head>
              <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
              <title>JSF消息测试</title>
          </head>
          <body>
              <h1><h:outputText value="用户注册"/></h1>
              <h:messages/>
              <h:form>
              <!-- 将下面UI组件的值绑定到Bean属性 -->
              用户名:<h:inputText value="#{userBean.name}"/><br/>
              <!-- 将下面UI组件的值绑定到Bean属性 -->
              年龄:<h:inputText id="age" value="#{userBean.age}"/>
              <!-- 输出age字段关联的异常信息 -->
              <h:message for="age"/><br/>
              <h:commandButton value="注册" action="#{userBean.regist}"/><br/>
              </h:form>
          </body>
      </html>
      </f:view>

上面页面代码中同时使用了<h:messages.../>和<h:message.../>两个标签,其中第一个标签可以输出所有组件上的异常信息;第二个标签需要指定一个for属性,for属性值指定输出哪个组件上的异常信息。

如果用户输入的age属性大于100,该应用将不会激发<h:commandButton.../>组件上的action属性绑定#{userBean.regist}方法,系统将退回regist.jsp,浏览者将看到如图2.33所示的页面。

图2.33 输出setAge()方法抛出的异常信息

通过上面两个示例可以看出,JSF提供的消息机制给实际开发带来了很大的便捷,开发者只要通过FacesContext将消息添加到消息队列中,接下来就可在生成响应阶段使用<h:messages.../>标签或<h:message.../>标签来输出消息内容了。

如果结合后面介绍的JSF国际化支持,应用程序还可添加具有国际化支持的消息。