2012-01-09 15 views
0

在我當前的Spring/JSF項目中,我需要集成一種方法來將服務器端更新(最好是在發生時)推送到基於Web的GUI以顯示給客戶端。使用Spring/DWR反向Ajax功能來顯示錶數據的動態更改

所以要開始使用這些東西,我正在研究這個小應用程序,以瞭解DWR的工作原理。基本上,我已經開發了兩種變體來實現服務器端推送。

在第一種方法中,當按下「查找按鈕」時,正確顯示後端更新。這會在InstrumentManager中調用findInstrumentSymbols()方法,並通過DWR將輸出作爲List對象返回。

在第二種方法我試圖實現在DWR網網站建議反向Ajax方法。(http://directwebremoting.org/dwr-demo/reverseajax/peopleTable.html

如何使該功能可以作爲默認功能每次頁面加載,而無需專門激活它通過一個按鈕?

在此實現中,我無法像第一種方法那樣通過DWR將輸出作爲List對象返回,並且必須以字符串數組形式發送。我發現新的結果沒有像第一種方法那樣正確地填充,並且當按下「禁用按鈕」時它傾向於丟失新的數據。如何使用DWR正確實現反向服務器推送功能?

我已經列出了下面的代碼片段。我真的很感謝任何獲得反向Ajax功能的指針。

我已經使用了輪詢,如前面DWR版本中所述。如果切換到DWR3是前進的方向,那麼實現反向Ajax功能最理想的方法是什麼?

Web.xml中

<?xml version="1.0" encoding="UTF-8"?> 
<web-app id="WebApp_ID" version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 

    <display-name>AdminConsole</display-name> 
    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/application-context.xml 
     /WEB-INF/application-security-context.xml</param-value> 
    </context-param> 
    <context-param> 
     <param-name>javax.faces.DEFAULT_SUFFIX</param-name> 
     <param-value>.xhtml</param-value> 
    </context-param> 
    <context-param> 
     <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description> 
     <param-name>javax.faces.STATE_SAVING_METHOD</param-name> 
     <param-value>server</param-value> 
    </context-param> 
    <context-param> 
     <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name> 
     <param-value>resources.application</param-value> 
    </context-param> 
    <filter> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <url-pattern>/*</url-pattern> 
     <dispatcher>FORWARD</dispatcher> 
     <dispatcher>REQUEST</dispatcher> 
    </filter-mapping> 
    <listener> 
     <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> 
    </listener> 
    <listener> 
     <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> 
    </listener> 
    <listener> 
     <listener-class>com.sun.faces.config.ConfigureListener</listener-class> 
    </listener> 
    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
    <listener> 
     <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> 
    </listener> 
    <servlet> 
     <servlet-name>Faces Servlet</servlet-name> 
     <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>Faces Servlet</servlet-name> 
     <url-pattern>/faces/*</url-pattern> 
    </servlet-mapping> 
    <servlet> 
     <display-name>DWR Servlet</display-name> 
     <servlet-name>dwr-invoker</servlet-name> 
     <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> 
     <init-param> 
      <param-name>debug</param-name> 
      <param-value>true</param-value> 
     </init-param> 
     <init-param> 
      <param-name>activeReverseAjaxEnabled</param-name> 
      <param-value>true</param-value> 
     </init-param> 
     <init-param> 
      <param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name> 
      <param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value> 
     </init-param> 
     <init-param> 
      <param-name>timeToNextPoll</param-name> 
      <param-value>5000</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>dwr-invoker</servlet-name> 
     <url-pattern>/dwr/*</url-pattern> 
    </servlet-mapping> 
    <session-config> 
     <session-timeout>30</session-timeout> 
    </session-config> 
    <welcome-file-list> 
     <welcome-file>faces/index.xhtml</welcome-file> 
    </welcome-file-list> 
    <error-page> 
     <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
     <location>/login.xhtml</location> 
    </error-page> 
    ....... 
</web-app> 

的dwr.xml

<?xml version="1.0" encoding="UTF-8"?> 
<DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://directwebremoting.org/schema/dwr30.dtd"> 

<dwr> 
    <allow> 
    <convert converter="bean" match="com.stocktrade.admin.entity.*"/> 
    <create creator="spring" javascript="InstrumentManager"> 
     <param name="beanName" value="instrumentManager"/> 
    </create> 
    </allow> 
</dwr> 

應用的context.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring- context.xsd      
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
     http://www.springframework.org/schema/jee 
     http://www.springframework.org/schema/jee/spring-jee.xsd 
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
     http://www.directwebremoting.org/schema/spring-dwr 
     http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"> 

     ..... 

    <!-- bean for Instrument class --> 
    <bean id="instrumentManager" class="com.stocktrade.admin.instrument.InstrumentManagerImpl"> 
     <property name="instrumentDAO" ref="instrumentDAO"></property> 
     <property name="userManager" ref="userManager"></property> 
     <property name="accountManager" ref="accountManager"></property> 
     <property name="portfolioManager" ref="portfolioManager"></property> 
    </bean> 

     ...... 
</beans> 

儀器類

package com.xxxxx.admin.entity; 

import java.io.Serializable; 
import java.math.BigDecimal; 
import java.util.List; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.OneToMany; 
import javax.persistence.Table; 

@Entity 
@Table(name = "instrument") 
public class Instrument implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @Column(name="symbolName") 
    private String SymbolName; 

    @Column(name="name") 
    private String Name; 

    @Column(name="quantity") 
    private long Quantity; 

    @Column(name="price") 
    private BigDecimal Price; 

    @Column(name="Limit") 
    private int Limit; 

    public String getSymbolName() { 
     return SymbolName; 
    } 
    public void setSymbolName(String symbolName) { 
     SymbolName = symbolName; 
    } 
    public String getName() { 
     return Name; 
    } 
    public void setName(String name) { 
     Name = name; 
    } 
    public long getQuantity() { 
     return Quantity; 
    } 
    public void setQuantity(long quantity) { 
     Quantity = quantity; 
    } 
    public BigDecimal getPrice() { 
     return Price; 
    } 
    public void setPrice(BigDecimal price) { 
     Price = price; 
    } 
    public int getLimit() { 
     return Limit; 
    } 
    public void setLimit(int Limit) { 
     Limit = Limit; 
    } 
} 

InstrumentManager類

package com.xxxxx.admin.instrument; 

import java.math.BigDecimal; 
import java.util.List; 
import com. xxxxx.admin.entity.Instrument; 
import com. xxxxx.admin.entity.Portfolio; 
import com. xxxxx.admin.entity.Account; 
import com. xxxxx.admin.entity.Users; 

public interface InstrumentManager {  
     ……… 
     /*used to implement the find() functionality*/ 
    public List<Instrument> findInstrumentSymbols(); 
     /*used to implement the reverse ajax functionality*/ 
    public void SendInstrumentSymbols(); 
    public void addAttributeToScriptSession(); 
    public void removeAttributeToScriptSession(); 
    public void run(); 
} 

InstrumentManagerImpl類

​​

updateMMStatus.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:ui="http://java.sun.com/jsf/facelets" 
     xmlns:h="http://java.sun.com/jsf/html" 
     xmlns:f="http://java.sun.com/jsf/core"> 
     <h:head> 
     <title>Reverse Ajax Table Update</title> 
     <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" /> 
     <script type='text/javascript' src='/AdminConsole/dwr/engine.js'></script> 
     <script type='text/javascript' src='/AdminConsole/dwr/util.js'></script> 
     <script type='text/javascript' src='/AdminConsole/dwr/interface/InstrumentManager.js'></script> 

     <script type="text/javascript"> 
      window.onload=function() 
      { 
          // Initiate reverse ajax polling 
       dwr.engine.setActiveReverseAjax(true); 
          // Called when a call and all retry attempts fail 
       dwr.engine.setErrorHandler(errorHandler); 
          // Optional function to call when the reverse ajax status changes (e.g. online to offline) 
       dwr.engine.setPollStatusHandler(updatePollStatus); 
          // Optional - We are online right now! Until DWR determines we are not! 
       updatePollStatus(true); 
          //Optional - When the page is unloaded, remove this ScriptSession. 
       dwr.engine.setNotifyServerOnPageUnload(true); 
          // Initialize the tabs for this display   
       Tabs.init('tabList', 'tabContents'); 
          // Make a call to the server to begin updating the table! 
       InstrumentManager.SendInstrumentSymbols(); 
          //Make a remote call to the server to add an attribute onto the ScriptSession 
          //which will be used in determining what pages receive updates! 
       addAttributeToScriptSession(); 
      } 
       function errorHandler(message, ex) { 
        dwr.util.setValue("error", "Cannot connect to server. Initializing retry logic.", {escapeHtml:false}); 
        setTimeout(function() { dwr.util.setValue("error", ""); }, 5000) 
       } 

       function updatePollStatus(pollStatus) { 
        dwr.util.setValue("pollStatus", pollStatus ? "Online" : "Offline", {escapeHtml:false}); 
       } 

       // Make a remote call to add an attribute on the ScriptSession. 
       // Only clients that have this attribute set will receive updates.  
       function addAttributeToScriptSession() { 
        InstrumentManager.addAttributeToScriptSession(); 
       } 

       // Make a remote call to remove an attribute from the ScriptSession. 
       // Clients that call this will no longer receive updates (unless addAttributeToScriptSession is called again).   
       function removeAttributeToScriptSession() { 
        InstrumentManager.removeAttributeToScriptSession(); 
       } 
     </script> 
    /*Java script to updated instrument table related changes when the "find" Button is pressed */ 
    function find() { 
     <script type="text/javascript"> 
     function find() { 
     InstrumentManager.findInstrumentSymbols(); 
     } 
    </script> 
    </h:head> 
    <h:body onload="dwr.engine.setActiveReverseAjax(true);"> 

    <input type="button" value="Enable page updates" onclick="addAttributeToScriptSession();"/> 
    <input type="button" value="Disable page updates" onclick="removeAttributeToScriptSession();"/> 

     <h:messages styleClass="error" /> 
     <div class="data_header">Current Symbols in the System</div> 
     <h:dataTable rowClasses="odd,even" id="MMTable" 
      value="#{updateMMStausBean.instrumentsList}" var="insList" 
      rendered="#{updateMMStausBean.instrumentsList != null}" 
      headerClass="tableHeader" styleClass="table"> 
      <h:column> 
       <f:facet name="header"> 
        <h:outputText value="Symbol" /> 
       </f:facet> 
       <div align="left"> 
        <h:outputText value="#{insList.symbolName}" /> 
       </div> 
      </h:column> 
      <h:column> 
       <f:facet name="header"> 
        <h:outputText value="Name" /> 
       </f:facet> 
       <div align="left"> 
        <h:outputText value="#{insList.name}" /> 
       </div> 
      </h:column> 
      <h:column> 
       <f:facet name="header"> 
        <h:outputText value="Quantity" /> 
       </f:facet> 
       <div align="center"> 
        <h:outputText value="#{insList.quantity}" /> 
       </div> 
      </h:column> 
      <h:column> 
       <f:facet name="header"> 
        <h:outputText value="Price($)" /> 
       </f:facet> 
       <div align="right"> 
        <h:outputText value="#{insList.price}" /> 
       </div> 
      </h:column> 
      <h:column> 
       <f:facet name="header"> 
        <h:outputText value="Limit" /> 
       </f:facet> 
       <div align="right"> 
        <h:outputText value="#{insList.mMLimit}" /> 
       </div> 
      </h:column> 
     </h:dataTable> 

     <div id="container">  
    <h:panelGrid columns="2" cellpadding="6"> 
    <h:form id="authenticate1"> 
    <h:commandButton action="#{updateMMStausBean.ActivateAllMMOrdrerOn()}" value="Activate all Orders"> 
    </h:commandButton> 
    </h:form> 

    <h:form id="authenticate2"> 
    <h:commandButton action="#{updateMMStausBean.DeactivateAllMMOrdrerOn()}" value="Deactivate all Orders"> 
    </h:commandButton> 
    </h:form> 

     /* Java script to updated instrument table related changes when the "find" Button is pressed */ 
    <h:form id="authenticate3"> 
    <h:commandButton value="Find" onclick="find()"> 
    </h:commandButton> 
    </h:form> 
    </h:panelGrid> 
</div> 

     </h:body> 

</html> 

回答

0

排序出問題的一部分,但我沒有運氣與使用服務器端推送java列表尚未。

我一直在研究peopleTable demo application和基於網絡的類似應用程序,爲我的問題提出了一個解決方案。大多數這些應用程序傳遞String或String數組。

* >>> *這會調用InstrumentManager中的findInstrumentSymbols()方法,並通過DWR將對象的輸出作爲Object返回。

有一件事我在DWR注意到的是,當DWR Java腳本被稱爲連接到一個GUI操作如onclick(Egfind按鈕),可以通過smoothly.I對象或集合類型的數據相信會返回一個JSON對象在這個例子中。

該程序中顯示的findInstuments methods JSON output可以很容易地集成到網頁中。

>>> * 但是當你嘗試使用服務器推送操作將數據傳遞到網頁,我無法通過DWR在第一approach.It像以前那樣返回輸出必須被作爲一個字符串數組(基於我遇到的信息*:|)。

我基於服務器推送樣本代碼上的人員演示demo.It似乎DWR提供一點功能發送集合或對象到GUI,雖然它很容易可用時鏈接到用戶操作JSON對象傳遞(這似乎提供了支持字符串/字符串數組和基於字符串的集合或者說是我收集:|

與此相關的描述相關的代碼示例如下(爲完整的代碼參照的。原帖)

public void SendInstrumentSymbols() { 
     // Get the current page. 
     String page = ServerContextFactory.get().getContextPath() + "/faces/Instruments.xhtml"; 
     // Create a new AttributeScriptSessionFilter which will look for an attribute on the ScriptSession 
     ScriptSessionFilter attributeFilter = new AttributeScriptSessionFilter(SCRIPT_SESSION_ATTR); 
     // Update the page, filters ScriptSessions using attributeFilter. If the SCRIPT_SESSION_ATTR 
     // has not been set on the ScriptSession the page in question will not receive updates. 
     Collection sessions = ServerContextFactory.get().getScriptSessionsByPage(page); 
     Browser.withPageFiltered(page, attributeFilter, new Runnable() 
     { 
      <b>@Override 
      public void run() 
      { 
       // Creates a new Person bean. 
       List<Instrument> InstrumentList = new ArrayList<Instrument>(); 
       InstrumentList = findInstrumentSymbols() ; 

     /*This seems to be the tricky part - Sending the List<Instrument> to the server end.*/ 

       // Creates a multi-dimensional array, containing a row and the rows column data. 
       String[][] data = { 
        {InstrumentList.get(0).getSymbolName().toString(), InstrumentList.get(0).getName().toString(), String.valueOf(InstrumentList.get(0).getQuantity()), InstrumentList.get(0).getPrice().toString(), String.valueOf(InstrumentList.get(0).getMarketMakingLimit()),String.valueOf(InstrumentList.get(0).isBuyOrderMarketMakingOn()),String.valueOf(InstrumentList.get(0).isSellOrderMarketMakingOn())}}; 
       // Call DWR's util which adds rows into a table. instrumentTable is the id of the tbody and 
       // data contains the row/column data. 
       Util.addRows("instrumentTable", data); 
      } 
     }</b>); 
    } 

當y你可以嘗試改變這個功能來支持其他數據類型,比如在第一個Json對象被傳遞的情況下,我無法找到一個Clean方法 - 這很容易(我希望我沒有遺漏一些明顯的東西:| )

有沒有更好的方法可以設計爲使用此方法使用服務器推送時傳輸對象?(訴諸字符串轉換似乎該方法在大多數的Web例子建議。)

能數據交換時沒有GUI觸發來滿足同樣的要求,執行服務器側推以JSON對象? * 是否需要額外的配置更改和更新? *

如果基於JSON數據傳輸是可能的服務器端推送,你可以請給一些擡頭的一些文檔,網站或示例代碼,可以是任何assistance.Any這樣的鉛會非常讚賞的我在這個主題上沒有找到具體的東西

先謝謝你