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

Posted

技术标签:

【中文标题】将数据从 Java/JSF2 bean 传递到 Javascript/jQuery 组件作为返回值的最佳方法【英文标题】:Best method for passing Data from Java/JSF2 bean to Javascript/jQuery Components as return values 【发布时间】:2011-12-17 07:40:48 【问题描述】:

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

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

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

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

干杯

盟友

更新:

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

这是我的简单计数函数并转换为 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 Bean 获得的值之前,我在图表底部维护了系列函数以构建/填充图表:

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

还有我的 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

但是当我尝试传递我的 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 之前所说的,我们非常感谢您的帮助,并且再好不过了!

干杯

盟友

【问题讨论】:

【参考方案1】:

如果您使用的是 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 并传递 remoteCommandname,这实际上是一个 Javascript 函数。

setInterval("fetchChartData()", 5000);

我就是这样做的。

PF 还有另一个组件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

当您使用投票时,您不需要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);

接下来updateChartData是回调函数,不要自己调用,每次请求完成都会被remote-command调用。

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

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

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

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

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

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

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

【讨论】:

是的,我正在使用 p:poll 来更新我的网络应用程序中的值,我只是不确定如何将它传递给一个 JS 函数,即 Highcharts!我会试一试,让你知道!谢谢。 您是否有机会展示结构或举例说明 JSON 数据以及如何将其加载到 HighCharts 中?我有你上面写的,但它加载到 highcharts 我仍在努力......我不确定它是我想要传递的还是我试图加载它的方式! 它和你在上面发布的差不多,除了我使用投票: ...我还在我的脚本中添加了一个警报,所以每 10 秒我就会看到我的字符串更新。目前我只是想传递我的'Y'轴值字符串,保持x轴为:var x = (new Date()).getTime(),但正如我所说,我试图通过我的方法将值放入我认为完全错误的 Highcharts JS 文件中! @Ally:那么您在fetchChartData(); 中正确接收JSON 了吗?如果是,请发布您的 JS 代码(Highcharts 之一)而不是评论,更新您的原始帖子。 我已经添加了 highcharts 代码,将点添加到图表中!正如我提到的,我只是想在 mo 上想象增加一个数字!

以上是关于将数据从 Java/JSF2 bean 传递到 Javascript/jQuery 组件作为返回值的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

Apache Shiro,无法将值从登录表单传递到支持 bean

迁移到 tomcat 后,将枚举值作为参数从 JSF 页面传递给 bean 方法失败

JSF 2.0在bean(或页面?)之间传递数据

在servlet中从数据库中获取完整的行并使用bean类将它们传递给jsp

将活动之间的数据从列表视图传递到另一个活动

将 JSF2 托管 pojo bean 传递到 EJB 或将所需内容放入传输对象