首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

用动态元素自动更新 Web 页面 -1 简介

用动态元素自动更新 Web 页面 -1 简介

简介有时,您可能需要用动态元素自动更新一个 Web 页面。比如,对于一个投票网站,它需要在数据库接收到新的投票时就立刻更新投票结果,又比如,一个股票网站需要能够定期地更新证券的实时交易数据。投票结果以及实时的交易数据都是动态元素,直到运行时才能知道,但是当服务器端发出信号时,这些元素就应该能被添加或更新。那么,在一个 JSF 应用程序中如何做到这一点呢?
此前的一篇 developerWorks 文章 “” 介绍了如何在刷新 Web 页面的同时隐藏和显示可选的 JSF 组件。但是,这篇文章中所介绍的方法并不能解决上述问题。因为该方法需要您标识出所有的            JSF 组件并将它们写入到您的 JSF 页面。如果这些动态元素直到运行时都无法被识别,该怎么办呢?
直到现在,JSF 对这个问题都没有好的解决办法。虽然,您可能熟悉 Java Swing 应用程序,比如 “clock”,其中数据更改会引起 GUI 更新,或者您可能已经在一些基础的 Swing 开发指南中读到过有关如何实现这类应用程序的详细信息,但是这种方法对于我的场景不会奏效。Swing 已经提供了一种成熟的方式来仅仅基于内部的数据状态自动更新 GUI,但是 JSF 并不支持基于服务器端的请求刷新 GUI。如果研究一下 JSF 的标准生命周期,不难发现用户通常需要在 Web 页面上生成一个事件(比如,通过单击一个按钮)来调用 GUI 刷新。这意味着即使动态元素能在运行时创建并被添加到一个 Web 页面,如果没有来自用户的交互,这个 Web 页面仍不能自动刷新。
那么,该如何用动态元素自动更新一个 Web 页面呢?在本文中,我将探讨如下的解决方案:
  • 清除旧的 UI 组件并将新的组件添加到 Web 页面的适当位置
  • 将不同的事件处理程序绑定到 Web 页面的不同元素
  • 注册一个能侦听服务器端变更的侦听器
  • 使用 Ajax 技术只刷新 Web 页面的动态部分,而不是整个页面
监视服务器端的数据变更为了更好地解释我的解决方案,我将在整篇文章中只采用一个简单的例子。此应用程序是一个进行在线书籍销售的网站。诸如书的类别以及每个类别中的书的数量等库存信息将在这个网站的主页(参见图 1)中显示。
图 1. 在线售书网站的主页为了反映正确的信息,需要实时同步库存信息与数据库端的数据。由于从库存中添加或删除书的操作会导致服务器端数据的变更,所以必须要监视这些动作。监视变更的方法是添加一个侦听器来查询服务器端数据的变更,并让服务器端在变更发生后通知侦听器。清单 1 显示了该如何将侦听器注册到一个类以及如何从一个类中解除侦听器的注册。
清单 1. 向库存添加和删除侦听器
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Inventory{
……
   private Map<String, InventoryListner> listeners =
                    new HashMap<String,InventoryListner>();
……
   public void register(String id, InventoryListner listener){
      listeners.put(id, listener);
   }        
   public void deregister(String id){
      listeners.remove(id);                        
   }
……
}




库存侦听器可以通过两种 Java 方法从清单 1 中所示的 Inventory 类中添加和删除。假设所有的库存更改都是添加或删除书籍这类动作的结果,那么可以在每次发生这些动作的时候通知所有注册到 Inventory 类的侦听器。清单 2 显示了如何在发生变更时通知侦听器。
清单 2. 发生变更时通知侦听器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Inventory{
……
     public void addBookItem(String bookName,String auther,String price,
                                                                   String category){
         //codes for adding books
        categoryChanged();
     }
        
      public void removeBookItem(String bookName,String auther,
                                          String price,String category){
         //codes for deleting books
         categoryChanged();     
      }

      private synchronized void categoryChanged(){
         for (InventoryListner listener : listeners.values()) {
          listener.categoryChanged();
        }                          
      }
}




接下来,让受管 bean InventoryBean 实现 InventoryListener 并将其注册到库存数据,以便该 bean 可以在库存数据变更时获得通知。清单 3 显示了如何将这个受管 bean 注册到 Inventory 类。
清单 3. 将受管 bean 注册到 Inventory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface InventoryListner {
     public abstract void categoryChanged();
   }

   public class InventoryBean implements InventoryListner{
   ……
          private String m_clientId ;
          private InventoryNotifier m_notifier;
          public InventoryBean(){
            m_notifier = InventoryNotifier.getInstance();
            if(m_clientId == null) {
                m_clientId = "bookstore";
                m_notifier.register(m_clientId, this);
            }      
         }
    public void categoryChanged() {
    refresh();
    //code for refresh dynamic part via ajax
    }   
……
}




使用清单 1 到清单 3 中所列的这些方法,可以建立一个面向受管 bean 的框架来监视服务器端数据的变更。工作流程是:当此受管 bean 获得服务器端数据已经变更的通知后,就会调用 InventoryBean 的 categoryChanged() 方法,数据模型也会被更新。图 2 展示了此框架在数据库和 “Bean 部分” 之间建立了连接。想要在服务器端监视数据变更或从服务器端接收事件的任何应用程序都可以使用这个框架作为模板。
图 2.               业务处理模型
返回列表