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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7930047/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 01:45:49  来源:igfitidea点击:

Best method for passing Data from Java/JSF2 bean to Javascript/jQuery Components as return values

javascriptjqueryjsf-2

提问by Ally

I am having trouble nailing down the best method for passing data from a Java backing/managed bean to a jQuery/Javascript component such as Highcharts, so that my web app produces/displays data in a dynamic, real time way. I am pretty solid on my Java side of things but I have a pretty limited knowledge of JavaScript/jQuery which is obviously where I am falling down. So far as I have read, the best way is to Ajaxify a hidden field on my web app and pass a JSON object or string? in to it and then pass that value into my JS component.

我无法确定将数据从 Java 支持/托管 bean 传递到 jQuery/Javascript 组件(例如 Highcharts)的最佳方法,以便我的 Web 应用程序以动态、实时的方式生成/显示数据。我在 Java 方面非常扎实,但我对 JavaScript/jQuery 的了解非常有限,这显然是我失败的地方。据我所知,最好的方法是 Ajaxify 我的网络应用程序上的隐藏字段并传递一个 JSON 对象或字符串?传入它,然后将该值传递给我的 JS 组件。

Firstly this seems a bit labour intensive as I would have an Ajax call to update the JSON data and then a setInterval call to re-read the data into the JS component? I was hoping that I could pass the data straight into the JS component...

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

Either way could someone just firm up my knowledge and tell me a good tried and tested method, if different from above... Guides/Demo's would also be massively appreciated!!

无论哪种方式,有人都可以巩固我的知识并告诉我一个经过试验和测试的好方法,如果与上面不同的话......指南/演示也将不胜感激!

I also use Primeface's 2.2.1 if this will affect a suggested methodology?

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

Cheers

干杯

Ally

盟国

UPDATE:

更新:

Code is below but I just want to describe what I am trying to achieve quickly: Effectively I am trying to implement a dynamic Highcharts chart, using a simple count++ function from my backing bean. Obviously further down the line I will be using a real-time feed to provide this data but at the moment I am just trying to get Highcharts to work based of changing information from my JSF backing bean.

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

Here is my simple count function and conversion to JSON (I am not sure if the JSON method is really necessary since only 1 value(int) is being passed, but I would like to retain this method as I am sure I will be using more extensively on other parts of the web app):

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

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 External JS File, again its worth noting that I have maintained the series function at the bottom of the chart to build/populate the graph before I start appending values obtained from the JSF Beans:

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;
            })()
        }]
    });        
}); 

And the inline JS Function held on my XHTML page:

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

This works:

这有效:

 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
}

but when I try to pass my bean value:

但是当我尝试传递我的 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
}

That doesnt work...

那行不通...

Also I've been trying both remoteCommand and Poll to get the chart to work, neither of which I have been successful with:

此外,我一直在尝试使用 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>

As I've said before Bhesh, your help is massively appreciated and anymore would be great!

正如我在 Bhesh 之前所说的那样,非常感谢您的帮助,而且再好不过了!

Cheers

干杯

Ally

盟国

回答by Bhesh Gurung

If you are using PrimeFaces 2.2.1then it should be pretty easy to acheive what you are trying to do.

如果您使用的是PrimeFaces 2.2.1,那么实现您想要做的事情应该很容易。

PF has a component p:remoteCommandwith which you can Ajaxicaly invoke a managed-bean method.

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

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

And in the method prepareChartData()you produce your JSON string and use RequestContextprovided by PF to send it back to client:

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

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

And in the Javascript callback function updateChartData(xhr, status, args)you can process the JSON response and load into the chart:

在 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
}

And to periodically update the chart just use the Javascript setIntervalor setTimeoutand pass the nameof the remoteCommandwhich is actually a Javascript function.

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

setInterval("fetchChartData()", 5000);

That's how I do it.

我就是这样做的。

PF also has another component p:pollwhich makes it easier to implement live charts.

PF 还有另一个组件p:poll,可以更轻松地实现实时图表。

Update:

更新:

You got it wrong. On

你理解错了。在

What you need to do is on document-ready render the chart first and then start you poll.

您需要做的是先在文档就绪时渲染图表,然后开始轮询。

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

The p:pollcallback function updateChartData(xhr, status, args)needs be global so that the poll can call it on oncompleteevent.

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
}

And when you are using poll you do not need the setTimeoutor setInterval.

当您使用 poll 时,您不需要setTimeoutor setInterval

Update 2:

更新 2:

First of all, in updateChartDatafunction you are supposed to update the chartthat you created:

首先,在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);
}

Next, updateChartDatais callback function so don't call it yourself, it is called by the remote-command every time the request is complete.

接下来updateChartData是回调函数,所以不要自己调用它,每次请求完成时都会由远程命令调用它。

And, give the remote-command a separate form of it's own:

并且,给远程命令一个单独的形式:

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

Note in oncomplete="updateChartTest(xhr, status, args);"in your code the callback function should be updateChartTestinstead of updateChartTest.

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

Trigger the ajaxical polling after the chart is done loading:

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

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

For testing only, trying returning a random value from you managed-bean:

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

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