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

All*_*lly 7 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?

干杯

盟友

更新:

代码如下,但我只是想描述一下我想要快速实现的目标:实际上我正在尝试使用来自我的支持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));
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
            })()
        }]
    });        
}); 
Run Code Online (Sandbox Code Playgroud)

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

这有效:

 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
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试传递我的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
}
Run Code Online (Sandbox Code Playgroud)

那不起作用......

此外,我一直在尝试使用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>
Run Code Online (Sandbox Code Playgroud)

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

干杯

盟友

Bhe*_*ung 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>
Run Code Online (Sandbox Code Playgroud)

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

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

在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
}
Run Code Online (Sandbox Code Playgroud)

并定期更新图表只使用JavaScript setIntervalsetTimeout并传递nameremoteCommand实际上是一个JavaScript函数.

setInterval("fetchChartData()", 5000);
Run Code Online (Sandbox Code Playgroud)

我就是这样做的.

PF还有另一个组件p:poll,可以更容易地实现实时图表.

更新:

你理解错了.上

您需要做的是先准备好文档渲染图表,然后开始轮询.

$(document).ready(function() {
    chart = new Highcharts.Chart({
        //....
    });
    // start your poll here
});
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

当你使用民意调查时,你不需要setTimeoutsetInterval.

更新2:

首先,在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);
}
Run Code Online (Sandbox Code Playgroud)

接下来updateChartData是回调函数,所以不要自己调用它,每次请求完成时由remote-command调用它.

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

<h:form>
    <p:remoteCommand name="fetchChartData"
                     action="#{testBean.prepareChartDate()}"
                     oncomplete="updateChartData(xhr, status, args);"/>
</h:form>
Run Code Online (Sandbox Code Playgroud)

请注意,oncomplete="updateChartTest(xhr, status, args);"在代码中应该使用回调函数updateChartTest而不是updateChartTest.

加载图表后触发ajaxical轮询:

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

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

public void prepareChartDate() {
    // Produce you JSON string (I use Gson here)
    RequestContext reqCtx = RequestContext.getCurrentInstance();
    reqCtx.addCallbackParam("chartData", new Random().nextInt(500));
}
Run Code Online (Sandbox Code Playgroud)