最近用JSF做项目,其中有很多图表要绘制,而JSF框架自带的制图插件太鸡肋了,不得不使用强大的JS制图插件。可是怎么交互数据实在是脑疼的事情。js请求JSF后台managed bean是个很纠结的问题,不像请求servlet一样。本人想到三种方法:
第一种就是利用jsf.js(这是jsf核心库里面的js函数),这个里面的mojarra.ab(s, e, n, ex, re, op)方法,其实就是jsf.ajax.request(s, e, op)方法,s是请求源的id,e是事件类型,op是一组请求的属性,例如jsf.ajax.request("testform:test", event, { execute: 'testform:test', render: 'testform:testValue'})。使用这种方法必须要现在jsf页面中先有一个存值的jsf标签,下面的代码对应上面请求的页面代码。
<h:form id="testform">
<h:commandButton styleClass="cbutton" value="测试" id="test" action="#{userLogin.testAction()}"/>
<h:outputText id="testValue" styleClass="testvalue" value="#{userLogin.i}"/>
</h:form>
而value="#{userLogin.i}"中的i就是我要请求的值。如果用jquery来对一个一个div(id="test")标签赋值,js写法如下:
<script>
$(function(){
jsf.ajax.request("testform:test", event, { execute: 'testform:test', render: 'testform:testValue'});
$("div#test").val($(".testvalue").val());
});
</script>
看上去这种方法很笨重,但是这也是没办法的事情。
第二种其实是一个折中的方法,现在后台managed bean中生成数据,储存在制定的文件里面,然后前台用ajax请求数据的地址。我现在就用的这种方法,重点讲一下这个实现方法:
我需要用一个叫highcharts的制图插件,具体用法不说了,贴一点代码上来再解释一下:
首先是js代码
<script type="text/javascript">
Highcharts.setOptions({
global: {
useUTC: true
}
});
var chart;
jQuery(document).ready(function() {
function getRootPath(){
var strFullPath=window.document.location.href;
var strPath=window.document.location.pathname;
var pos=strFullPath.indexOf(strPath);
var prePath=strFullPath.substring(0,pos);
var postPath=strPath.substring(0,strPath.substr(1).indexOf('/')+1);
return(prePath+postPath);
}
var options = {
chart: {
renderTo: 'errorstatisticcontainer',
defaultSeriesType: 'spline',
marginRight: 10,
zoomType: 'xy'
},
title: {
text: '\u529f率对比图'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: '\u529f率'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
crosshairs: [{
width: 1
}, {
width: 1
}],
shared: true
},
legend: {
enabled: true
},
exporting: {
enabled: true
},
plotOptions: {
spline: {
marker: {
radius: 5,
lineWidth: 1
}
}
},
series: [{
name: '\u5b9e发功率',
lineWidth: 2,
marker: {
symbol: 'circle',
radius: 2
}
}, {
name: '\u9884测功率',
lineWidth: 2,
marker: {
symbol: 'triangle',
radius: 2
}
}]
};
var url = getRootPath()+'/resources/json/temp.json';
jQuery.getJSON(url,function(json, state, xhr){
var rdata = [];
var fdata = [];
var _data = json.data;
jQuery.each(_data,function(i){
rdata.push([
_data[i].time, _data[i].r
]);
fdata.push([
_data[i].time, _data[i].f
]);
})
options.series[0].data = rdata;
options.series[1].data = fdata;
chart = new Highcharts.Chart(options);
})
})
</script>
这里面有三个部分,第一个是绘制图表。第二个就是获取URL,获取URL的方法就是getRootPath(),然后加上"/resources/json/temp.json",后面的这个字符串是后台指定的。第三部分就是获取数据了,这里用到的是jQuery.getJSON()方法了。
除了上面的js,还需要一个div来绘制图表,这个很简单,一句话(其中errorstatisticcontainer对应js中renderTo属性值):
<div id="errorstatisticcontainer" style="width: 1000px; height: 600px; margin: 0 auto"></div>
再者就是managedbean的方法了
private static String path = "resources\\json\\temp.json";
//把json格式的字符串写到文件
public static void writeFile(String filePath, String sets) {
FileWriter fw = null;
try {
fw = new FileWriter(filePath);
PrintWriter out = new PrintWriter(fw);
out.write(sets);
out.println();
fw.close();
out.close();
} catch (IOException ex) {
Logger.getLogger(ErrorStatisBean.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
fw.close();
} catch (IOException ex) {
Logger.getLogger(ErrorStatisBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void setDataAction(){
//获取json路径
FacesContext context = FacesContext.getCurrentInstance();
ServletContext servletContext = (ServletContext) context.getExternalContext().getContext();
String rootPath = servletContext.getContextPath();
String _rootPath = servletContext.getRealPath("/");
String filepath = _rootPath + path;
JSONObject jsonObj = new JSONObject();
for (long time = starttime; time <= endtime; time += timestep) {
try {
Object f = fMap.get(time);
Object r = rMap.get(time);
Map<String, Object> data = new HashMap<String, Object>();
data.put("time", time);
data.put("r", r);
data.put("f", f);
jsonObj.append("data", data);
} catch (JSONException ex) {
Logger.getLogger(ErrorStatisServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
writeFile(filepath,jsonObj );
}
这样就可以出现数据,发张截图如下:
还有低三种方法:就是另写一个jsp,在jsp中请求调用jsf后台的方法,这个看起来有点不伦不类,而且有参数的时候需要把参数值放入到session中,其实增加了一些麻烦!