最近用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中,其實增加了一些麻煩!