将数据从Java / JSF2 bean传递到Javascript / jQuery组件作为返回值的最佳方法

时间:2011-10-28 13:40:26

标签: javascript jquery jsf-2

我无法确定将数据从Java支持/托管bean传递到jQuery / Javascript组件(如Highcharts)的最佳方法,以便我的Web应用程序以动态,实时的方式生成/显示数据。我在Java方面的表现非常扎实,但我对JavaScript / jQuery的了解非常有限,这显然是我倒下的地方。到目前为止,我已经阅读过,最好的方法是在我的Web应用程序上Ajax化一个隐藏字段并传递一个JSON对象或字符串?在它中,然后将该值传递给我的JS组件。

首先,这似乎有点费力,因为我会更新JSON数据进行Ajax调用,然后调用setInterval来重新读取JS组件中的数据?我希望我可以直接将数据传递给JS组件......

无论哪种方式,有人可以坚定我的知识,并告诉我一个良好的经过试验和测试的方法,如果不同于上面...指南/演示也将受到大力赞赏!!

如果这会影响建议的方法,我也使用Primeface的2.2.1?

干杯

Ally

更新:

代码如下,但我只是想描述一下我想要快速实现的目标:实际上我正在尝试使用我的支持bean中的简单count ++函数来实现动态Highcharts图表。显然,我将使用实时源提供此数据,但目前我只是想根据我的JSF支持bean更改信息来使Highcharts工作。

这是我的简单计数函数和转换为JSON(我不确定JSON方法是否真的有必要,因为只传递了1个值(int),但我想保留这个方法,因为我相信我会在网络应用程序的其他部分更广泛地使用):

public class TestBean {

    private int output;

    public TestBean() {
        output = 1;
    }

    public int getOutput() {
        return output;
    }

    public void setOutput(int output) {
        this.output = output;
    }

    public void update() {
        setOutput(getOutput() + 1);
    }

    public void prepareChartDate() {
        // Produce you JSON string (I use Gson here)
        RequestContext reqCtx = RequestContext.getCurrentInstance();
        reqCtx.addCallbackParam("chartData", new Gson().toJson(output));
    }
}

Highcharts外部JS文件,值得注意的是我在图表底部维护了系列函数,以便在我开始附加从JSF Beans获得的值之前构建/填充图形:

Highcharts.setOptions({
    global: {
        useUTC: false
    }
});

var chart;
$(document).ready(function() {
    chart = new Highcharts.Chart({
        chart: {
            backgroundColor: "#F8F0DB",
            renderTo: 'containerHigh',
            defaultSeriesType: 'area',
            margin: 10,
            marginLeft:30,
            marginBottom:17,
            zoomType: 'y',
            events: {
                load: updateChartData
            }
        },
        title: {
            text: 'Feed Flow Rate '

        },
        xAxis: {
            type: 'datetime',
            tickPixelInterval: 150
        },
        yAxis: {
            title: {
                text: ''
            },
            plotLines: [{
                value: 0,
                width: 1,
                color: '#808080'
            }]
        },
        tooltip: {
            formatter: function() {
                return '<b>'+ this.series.name +'</b><br/>'+
                Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) +'<br/>'+ 
                Highcharts.numberFormat(this.y, 2);
            }
        },
        legend: {
            enabled: false
        },
        exporting: {
            enabled: false
        },
        plotOptions: {
            area: {
                fillColor: {
                    linearGradient: [0, 0, 0, 100],
                    stops: [
                    [0, Highcharts.getOptions().colors[0]],
                    [1, 'rgba(2,0,0,0)']
                    ]
                },
                lineWidth: 1,
                marker: {
                    enabled: false,
                    states: {
                        hover: {
                            enabled: true,
                            radius: 5
                        }
                    }
                },
                shadow: false,
                states: {
                    hover: {
                        lineWidth: 1                        
                    }
                }
            }
        },
        series: [{
            name: 'Random data',
            data: (function() {
                // generate an array of random data
                var data = [],
                time = (new Date()).getTime(),
                i;

                for (i = -19; i <= 0; i++) {
                    data.push({
                        x: time + i * 10000,
                        y: 50 * Math.random()
                    });
                }
                return data;
            })()
        }]
    });        
}); 

内联JS函数保存在我的XHTML页面上:

这有效:

 function updateChartData(xhr, status, args) { 
    var series = this.series[0];
    setInterval(function() {            
        var x = (new Date()).getTime()
        y = 50 * Math.random();
        series.addPoint([x, y], true, true);   

    }, 1000)       
//parse it, process it and load it into the chart
}

但是当我尝试传递我的bean值时:

 function updateChartData(xhr, status, args) { 
    var jsonString = args.chartData
    var series = this.series[0];

    setInterval(function() {            
        var x = (new Date()).getTime()
        y = jsonString 
        series.addPoint([x, y], true, true);   

    }, 1000)       
//parse it, process it and load it into the chart
}

那不起作用......

此外,我一直在尝试使用remoteCommand和Poll来使图表工作,我都没有成功:

 <h:form>                       
                    <p:commandButton value="update" action="#{testBean.update}" update="beanvalue"/> 

                    <h:outputText value="#{testBean.output}" id="beanvalue"/> <br />
                    <h:outputText value="#{testBean.output}" id="chartValue"/> <br />

                    <p:commandButton value="Load" type="button" onclick="fetchChartData();"/>
                    <p:remoteCommand name="fetchChartData"
                                     action="#{testBean.prepareChartDate()}"
                                     oncomplete="updateChartTest(xhr, status, args);"/>            
                </h:form>

正如我在Bhesh之前所说的那样,你的帮助非常受欢迎,而且会更好!

干杯

Ally

1 个答案:

答案 0 :(得分:16)

如果您使用的是 PrimeFaces 2.2.1 ,则应该很容易实现您的目标。

PF有一个组件p:remoteCommand,您可以使用Ajaxicaly调用托管bean方法。

<h:form id="frmIrsChartData">
    <p:remoteCommand name="fetchChartData"
                     action="#{chartManagedBean.prepareChartData()}"
                     oncomplete="updateChartData(xhr, status, args);"/>
</h:form>

在方法prepareChartData()中,您生成JSON字符串并使用PF提供的RequestContext将其发送回客户端:

public void prepareChartDate() {
    // Produce you JSON string (I use Gson here)
    RequestContext reqCtx = RequestContext.getCurrentInstance();        
    reqCtx.addCallbackParam("chartData", jsonString);
}

在Javascript回调函数updateChartData(xhr, status, args)中,您可以处理JSON响应并加载到图表中:

function updateChartData(xhr, status, args) {
    var jsonResponse = args.chartData;
    //parse it, process it and load it into the chart
}

要定期更新图表,只需使用Javascript setIntervalsetTimeout,然后传递name的{​​{1}},这实际上是一个Javascript函数。

remoteCommand

我就是这样做的。

PF还有另一个组件setInterval("fetchChartData()", 5000); ,可以更轻松地实现实时图表。

<强>更新

你弄错了。在

您需要做的是先准备文档,然后开始轮询。

p:poll

$(document).ready(function() { chart = new Highcharts.Chart({ //.... }); // start your poll here }); 回调函数p:poll需要是全局的,以便民意调查可以在updateChartData(xhr, status, args)事件中调用它。

oncomplete

当您使用民意调查时,您不需要function updateChartData(xhr, status, args) { var jsonResponse = args.chartData; //parse it, process it and load it into the chart //you will load data into the same chart created in document-ready } setTimeout

更新2:

首先,在setInterval函数中,您应该更新您创建的updateChartData

chart

接下来,function updateChartData(xhr, status, args) { var series = chart.series[0]; // <--- no more this instead global variable "chart" var newData = args.chartData; var x = (new Date()).getTime() var y = eval('(' + newData + ')'); series.addPoint([x, y], true, true); } 是回调函数,所以不要自己调用它,每次请求完成时都会被remote-command调用。

并且,给remote-command一个单独的形式:

updateChartData

请注意,代码中<h:form> <p:remoteCommand name="fetchChartData" action="#{testBean.prepareChartDate()}" oncomplete="updateChartData(xhr, status, args);"/> </h:form> 的回调函数应为oncomplete="updateChartTest(xhr, status, args);"而不是updateChartTest

在图表加载完成后触发ajaxical轮询:

updateChartTest

仅用于测试,尝试从managed-bean返回一个随机值:

events: {
       load: function() {
           setInterval("fetchChartData()", 5000); //update the chart every 5 seconds               
       }
}