最近,由于项目的需要,我做了一个关于OFC与JSP结合做报表的Demo,之所以选择使用Struts框架,是因为公司的项目系统比较老用的是这个框架。
首先,我必须要向我参考的文章致敬:
http://hi.baidu.com/javagril/item/2ca42e3501554382c2cf29d6
上边这个文章虽然粘了主要的代码,但你要是直接用的话,还是会有错误,我下面会更详细的说明使用的过程,我的思路是由jsp页面开始,框架,后台。
结合上面的文章,我想展示的是一个包括“hello worle”字符串和饼图的页面,内容如下:
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"%>
<%@include file="/jsp/inc/inc.jsp"%>
<%-- <%@page import="snt.common.web.util.WebUtils"%> --%>
<%-- <link href="${ctxPath}/css/policy.css" rel="stylesheet" type="text/css"/> --%>
<html>
<head>
<title>OFC用例</title>
<script type="text/javascript" src="${ctxPath}/js/OFC/common.js" charset="UTF-8"></script>
<script type="text/javascript" src="${ctxPath}/js/OFC/json2.js" charset="UTF-8"></script>
<script type="text/javascript" src="${ctxPath}/js/OFC/swfobject.js" charset="UTF-8"></script>
<script type="text/javascript">
swfobject.embedSWF(
"${ctxPath}/jsp/ofc_test2/open-flash-chart.swf",
"my_piechart",
"40%",
"40%",
"10.0.0",
"playerProductInstall.swf",
{"data-file":"<%=request.getContextPath()%>/ofcTest2.do?cmd=toPieChart"},
{wmode:"transparent"}
);
swfobject.embedSWF(
"${ctxPath}/jsp/ofc_test2/open-flash-chart.swf",
"my_barchart",
"40%",
"40%",
"10.0.0",
"playerProductInstall.swf",
{"data-file":"<%=request.getContextPath()%>/ofcTest2.do?cmd=toBarChart"},
{wmode:"transparent"}
);
</script>
</head>
<body>
<p>Hello World</p>
<div id="my_piechart"></div>
<div id="my_barchart"></div>
</body>
</html>
1.我们看到上面的jsp页面,我想之前的父页面不管是什么,我们都需要一个action来跳转到改页面,那么在编写这个action之前,我们需要的配置Struts框架的一些配置文件,这里关于Struts的东西不详细说,只是粘出源码,供参考:
(1). action-servlet_ofcTest.xml(这个名字你随便起,只是在web.xml中配置时需要注意),
这里你们主要看的所有带“2”的文件,带“1”的文件是我用别的方法实现的用例
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<!-- OFC用例 -->
<beans default-lazy-init="true">
<!-- OFC1 -->
<bean name="/ofcTest" class="snt.riskmanager.web.action.ofc_test.OFCTestAction" parent="baseAction">
<property name="OFCTestService" ref="OFCTestService"></property>
</bean>
<bean name="/ofcTest2" class="snt.riskmanager.web.action.ofc_test2.OFCTestAction2" parent="baseAction">
</bean></beans>
(2)struts-config_ofcTest.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<action-mappings>
<!-- OFC用例-->
<action path="/ofcTest" type="snt.riskmanager.web.action.ofc_test.OFCTestAction" >
<forward name="ofcTestMain" path="/jsp/ofc_test/ofcTest.jsp"></forward>
<forward name="ofcTestMain2" path="/jsp/ofc_test2/ofcTest2.jsp"></forward>
</action>
action path="/ofcTest2" type="snt.riskmanager.web.action.ofc_test2.OFCTestAction2" >
<forward name="ofcTestMain2" path="/jsp/ofc_test2/ofcTest2.jsp"></forward></action>
</action-mappings>
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
<message-resources parameter="langres.Application"/>
</struts-config>
(3)另外还应该有两个文件需要配置,一个是Struts-servlet.xml,另一个是web.xml
说白一点就是对(1)(2)这两个文件的配置。
(4)此时如果你能访问到页面,并且看到helloworld,你的struts就ok了,不行的话找个同事儿帮看看,注意检查那个文件没有配置哦~~
2.我们再来说Action,我的文件为:OFCTestAction2.java,此名字可以随便起,但是要注意改名字和路径要与action-servlet_ofcTest.xml中第二个bean的class属性值匹配,这个我说的够傻瓜了吧,其中的道理还希望自己体会。
(1)action代码和包:
public class OFCTestAction2 extends BaseAction{
protected ActionForward doExecute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
// TODO Auto-generated method stub
String cmd = request.getParameter("cmd");
String rtn = null;
if("ofcTestMain2".equals(cmd)){//查询所有的客户
rtn = toofcTest2(request);
}else if("toPieChart".equals(cmd)){
rtn=toPieChart(response);
}else if("toBarChart".equals(cmd)){
rtn=toBarChart(response);
}
return mapping.findForward(rtn);
}
private String toofcTest2(HttpServletRequest request) throws Exception {
//将结果返回到ofcTest2.jsp页面
return "ofcTestMain2";
}
private String toPieChart(HttpServletResponse response) throws Exception {
PieChart pie = new PieChart();
pie.setFontSize(15);// 设置字体
pie.addSlice(200000000, " 实收费用 " );// 分类
pie.addSlice(60000000, " 欠费金额 " );
pie.addSlice(30000000, " 报停金额 " );
pie.addSlice(20000000, " 减免金额 " );
pie.setStartAngle(100);// 设置角度
pie.setAnimate( true );
// 设置颜色
pie.setColours( new String[] { "0x336699" , "0x88AACC" , "0x999933" ,
"0x666699" , "0xCC9933" , "0x006666" , "0x3399FF" , "0x993300" ,
"0xAAAA77" , "0x666666" , "0xFFCC66" , "0x6699CC" , "0x663366" ,
"0x9999CC" , "0xAAAAAA" , "0x669999" , "0xBBBB55" , "0xCC6600" ,
"0x9999FF" , "0x0066CC" , "0x99CCCC" , "0x999999" , "0xFFCC00" ,
"0x009999" , "0x99CC33" , "0xFF9900" , "0x999966" , "0x66CCCC" ,
"0x339966" , "0xCCCC33" });
pie.setTooltip( "#val# / #total#<br> 占百分之 #percent#");// 鼠标移动上去后提示内容
pie.setRadius(20);
Chart flashChart = new Chart( " 2009至2010年度 包烧费分析 " , "font-size:30px;color:#ff0000;" ); // 整个图的标题
//flashChart.setBackgroundColour("#3EFFFF");
flashChart.addElements(pie); // 把饼图加入到图表
String json = flashChart.toString();// 转成 json 格式
response.setContentType( "application/json-rpc;charset=utf-8" );
response.setHeader( "Cache-Control" , "no-cache" );
response.setHeader( "Expires" , "0" );
response.setHeader( "Pragma" , "No-cache" );
response.getWriter().print(json);// 写到客户端
return null;
}
private String toBarChart(HttpServletResponse response) throws Exception {
BarChart chart = new BarChart(BarChart.Style. GLASS ); // 设置条状图样式
//FilledBarChart chart = new FilledBarChart("red","blue");// 设置条状图样式
//String sMax = "10000" ;
long max = 900; // //Y 轴最大值
Map<String,Long> map = new HashMap<String,Long>();
map.put( "5" , new Long(50));
map.put( "6" , new Long(45));
map.put( "7" , new Long(60));
map.put( "8" , new Long(30));
map.put( "9" , new Long(80));
map.put( "10" , new Long(500));
map.put( "11" , new Long(800));
map.put( "12" , new Long(200));
XAxis x = new XAxis(); // X 轴
int i = 5;
for (String key:map.keySet()){
x.addLabels(i+"月份"); // x 轴的文字
Bar bar = new Bar(map.get(""+i), " 万元 " );
i++;
bar.setColour( "0x336699" ); // 颜色
bar.setTooltip(map.get(""+i) + " 万元 " ); // 鼠标移动上去后的提示
chart.addBars(bar); // 条标题,显示在 x 轴上
}
Chart flashChart = new Chart();
flashChart.addElements(chart); // 把柱图加入到图表
YAxis y = new YAxis(); //y 轴
y.setMax(max+10.0); //y 轴最大值
y.setSteps(max/10*1.0); // 步进
flashChart.setYAxis(y);
flashChart.setXAxis(x);
String json = flashChart.toString();
response.setContentType( "application/json-rpc;charset=utf-8" );
response.setHeader( "Cache-Control" , "no-cache" );
response.setHeader( "Expires" , "0" );
response.setHeader( "Pragma" , "No-cache" );
response.getWriter().print(json);// 写到客户端
return null;
}
}
其实,这个你在用ofc这个flex插件做图表时,你想啊,你得有数据吧,比如:饼图或者柱状图要显示的数据、x和y轴的标题、x和y轴每个分点代表什么之类,我以前用flex和java做时,需要将flex前端的所有信息在flex端组织成对象传给java端,java端在利用js解析这些对象的属性。但现在我们不用了,我们可以用别人直接封装好的类,利用类中的属性和方法直接将数据送给OFC。
那么问题就来了,这个类是什么呢???你们可能也发现少了包的引用吧,嘿嘿~,我先把所有用到的包贴出来:
package snt.riskmanager.web.action.ofc_test2;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jofc2.model.Chart;
import jofc2.model.axis.XAxis;
import jofc2.model.axis.YAxis;
import jofc2.model.elements.BarChart;
import jofc2.model.elements.BarChart.Bar;
import jofc2.model.elements.PieChart;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import snt.riskmanager.web.action.BaseAction;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
以snt开头的包,使我们公司自己的,我想你的公司肯定也有相同功能的东西吧~~
(2).首先我们需要的jar包是:jofc2,我下载的名字是jofc2-1.0.0.jar,顾名思义:ofc的java实现,所以jofc,哈哈,我瞎理解的~
一会儿去“附件”里找吧,jofc2-1.0-0.zip解压后就有那个jar包。
有了上面这个jar包,当时我的情况是hello world打印,但是用来显示图表的区域还是什么都没有,还报错,我报的错但是没看懂,是关于这个东西的:com.thoughtworks.xstream.io.HierarchicalStreamDriver,好吧,果断没看过,我谷歌了一下,发现没有这个包xstream-1.3.1.jar,嘿嘿,我还是放在附件中,解压缩找找吧~~
3.现在有了这些,我想你的图表应该出来了吧,如果还没出来,那么别着急,我们去检查下一下几点,主要是关于jsp页面中的内容:
(1).检查下面js文件的路径对不对
<script type="text/javascript" src="${ctxPath}/js/OFC/json2.js" charset="UTF-8"></script>
<script type="text/javascript" src="${ctxPath}/js/OFC/swfobject.js" charset="UTF-8"></script>
(2).检查对“open-flash-chart.swf”这个文件应用的路径对不对
swfobject.embedSWF(
"${ctxPath}/jsp/ofc_test2/open-flash-chart.swf",
"my_piechart",
"40%",
"40%",
"10.0.0",
"playerProductInstall.swf",
{"data-file":"<%=request.getContextPath()%>/ofcTest2.do?cmd=toPieChart"},
{wmode:"transparent"}
);
(3)备注:代码中的${ctxPath},你们不用纠结,其实你只要从项目名写到你文件所在的位置就行啦,这个解释也够直白吧~~,但要注意data-file这个属性的中action(.do)的写法以及不要忘了写cmd哦~~
4.再次啰嗦几句吧,对于swfObject.embedSWF文件的理解,其实就是你要想在jsp和html中嵌入flex,就需要这个东西,我自己从网上找了资料汇总了下,请仔细看下面的解释:
//2.0 embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj)
//2.2 embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr,xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn)
//swfUrlStr(必须):swf位置 ;
//replaceElemIdStr(必须):html中要替换成flash的元素的id
//widthStr(必须):宽
//heightStr(必须):高
//swfVersionStr(必须):flash版本
//xiSwfUrlStr(可选):指定express install SWF的URL并激活Adobe express install
//flashvarsObj(可选):用"name:value对"指定你的flashvars
//parObj(可选):用"name:value对 "指定你的嵌套object元素的params(张熠的理解:指的是被用于"盛放"swf文件的那个元素的属性 )
//attObj(可选):用"name:value对"指定object的属性(张熠的理解:指的是swf文件的属性)
好了,我想说的就是这些了,当你看完这篇文章时,我相信你能用ofc展示饼图了,柱状图之类的你继续参照开头提到的文章将action中的实现写出来即可!
该例子的不足就是action里的数据是直接写的,而不是从数据库抓出来的,不过这个实现起来很容易,我现在没时间,等过两天做报表时我会实现这个,到时再给大家补充一下。
不过,是否理解了,我想还是看每个人的主管能动性吧,我的出发点是那些基础不好或者懂得少但是真心想学的人,我相信这些人他们做完后会自己思考的~~
最后,其实我就是这样的人,我以前专学c++,flex有基础,java会,但java应用会的太少,当时不会做就是希望有个人手把手教教我,因为有些东西即使我再和他较劲,没人提点我还是想不出来,所以我当时心里就一直在想,谁能教教我,说仔细些,从例子出发,我自己也一定会思考,不会照搬的.......哈哈,我觉得我还是很幸运的,公司的“老前辈”会不厌其烦的教我,默默感谢他们!!!希望大家一起学习,别人帮你是你的幸运,但我们要永远立足于自己学习,哈哈,这话说的够文艺吧~~