写在JSP页面中的Cewolf,能用于基于web工程的Servlet/JSP,来制作复杂的统计图表.它提供几乎图的所有特征,象颜色,线条,图形等等.所以能够在不写任何JAVA代码的情况下让JSP页面显示图表.
Cewolf是基于
JFreechart的,利用JFreechart的绘制引擎,将最终的图片写入客户端.在服务器端不会创建任何文件.一切都是基于轻量级的会话对象和动态的数据分析的.
Cewolf有一个单例的servlet,这个servlet用来处理图的绘画和标签库时,用这个标签库将在JSP页面的图的定义转成HTML img tag,servlet按HTML img tag绘制想要的图片送给客户端.
特点:
1:免费开源
2:可跑于J2EE compliant server or servlet container
3:图标签库特征: jsp不需要编写java代码 ; 由xml编写
4:图类型丰富:
Line [XY]
[3D] Pie
[3D] Horizonal Bar
[3D] Vertical [XY] Bar
[3D] Stacked Vertical Bar
Area [XY]
Scatter Plot
Candlestick
High Low
Gantt
Overlaid
Combined
例子:在JSP中写下以下代码来表示一个图:
<
cewolf:chart
id
="XYChart"
type
="xy"
title
="XYChart"
>

<
cewolf:gradient
>
<
cewolf:point
x
="0"
y
="0"
color
="#FFFFFF"
/>
<
cewolf:point
x
="0"
y
="300"
color
="#C8C8C8"
/>
</
cewolf:gradient
>

<
cewolf:data
>
<
cewolf:producer
id
="xyData"
/>
</
cewolf:data
>

</
cewolf:chart
>

<
cewolf:img
chartid
="XYChart"
renderer
="cewolf"
width
="400"
height
="300"
/>
当然这个xyData在JSP上下文是必须有效的,这个图是由id为xyData的DataProducer产生.
第一步:准备
下载标签库jar包:
将jar包下/Lib文件内容放在工程的/WEB-INF/lib 下面,/Lib文件内容:
jfreechart-*-demo.jar
jfreechart-*.jar
jcommon-*.jar
commons-logging.jar
cewolf.jar
batik-xml.jar
batik-util.jar
batik-svggen.jar
batik-dom.jar
batik-awt-util.jar
Mozilla浏览器需要/example目录下的overlib.js,放入webapps根目录下。
在用Cewolf标签出现问题时,例如:"No Tags" is displayed in your containers console。你可以将cewolf.tld或cewolf-1.1.tld 文件放入你在WEB项目根目录下的新建的文件夹中,就能在JSP中使用这些标签咯。
第二步:生成一个DatasetProducer
因为Cewolf使用MVC (Model-View-Control)处理显示在图中的数据,而这些数据是于定义在JSP页面中的VIEW层分离开的。为了给图提供正确的数据,你必须生成一个实现了de.laures.cewolf.DatasetProducer接口的对象,每次重画一个新的图的时候这个对象将被用到。
下面请看一个DatasetProducer实现的例子。
package
de.laures.cewolf.example;
import
java.io.Serializable;
import
java.util.Date;
import
java.util.Map;
import
org.apache.commons.logging.Log;
import
org.apache.commons.logging.LogFactory;
import
org.jfree.data.category.CategoryDataset;
import
org.jfree.data.category.DefaultCategoryDataset;
import
de.laures.cewolf.DatasetProduceException;
import
de.laures.cewolf.DatasetProducer;
import
de.laures.cewolf.links.CategoryItemLinkGenerator;
import
de.laures.cewolf.tooltips.CategoryToolTipGenerator;

/** */
/**
* An example data producer.
* @author Guido Laures
*/
public
class
PageViewCountData
implements
DatasetProducer,
CategoryToolTipGenerator,
CategoryItemLinkGenerator,

Serializable
...
{
private static final Log log = LogFactory.getLog(PageViewCountData.class);
// These values would normally not be hard coded but produced by
// some kind of data source like a database or a file

private final String[] categories = ...{ "mon",
"tue",
"wen",
"thu",
"fri",
"sat",
"sun"};

private final String[] seriesNames = ...{ "cewolfset.jsp",
"tutorial.jsp",
"testpage.jsp",
"performancetest.jsp"};

/** *//**
* Produces some random data.
*/
public Object produceDataset(Map params)

throws DatasetProduceException ...{
log.debug("producing data.");

DefaultCategoryDataset dataset = new DefaultCategoryDataset()...{

/** *//**
* @see java.lang.Object#finalize()
*当垃圾回收器确定不存在对该对象的更多引用时,
*由对象的垃圾回收器调用此方法
*/

protected void finalize() throws Throwable ...{
super.finalize();
log.debug(this +" finalized.");
}
};

for (int series = 0; series < seriesNames.length; series ++) ...{
int lastY = (int)(Math.random() * 1000 + 1000);

for (int i = 0; i < categories.length; i++) ...{
final int y = lastY + (int)(Math.random() * 200 - 100);
lastY = y;
dataset.addValue(y, seriesNames[series], categories[i]);
}
}
return dataset;
}

/** *//**
* This producer's data is invalidated after 5 seconds. By this method the
* producer can influence Cewolf's caching behaviour the way it wants to.
*/

public boolean hasExpired(Map params, Date since) ...{
log.debug(getClass().getName() + "hasExpired()");
return (System.currentTimeMillis() - since.getTime()) > 5000;
}

/** *//**
* Returns a unique ID for this DatasetProducer
*/

public String getProducerId() ...{
return "PageViewCountData DatasetProducer";
}

/** *//**
* Returns a link target for a special data item.
*/

public String generateLink(Object data, int series, Object category) ...{
return seriesNames[series];
}

/** *//**
* @see java.lang.Object#finalize()
*/

protected void finalize() throws Throwable ...{
super.finalize();
log.debug(this + " finalized.");
}

/** *//**
* @see org.jfree.chart.tooltips.CategoryToolTipGenerator#generateToolTip(CategoryDataset, int, int)
*/

public String generateToolTip(CategoryDataset arg0, int series, int arg2) ...{
return seriesNames[series];
}
}
正如所见,这个datasetproducer不是很有用,通常,这个类会去访问一个数据源(例如一个数据库)获得需要的数据,这里仅作例子展示而已。
一个DatasetProducer需要实现3个方法,最重要的一个是produceDataset()方法,它实际上生成了一个用于画图的数据。这个方法用一个map作参数,这个map由许多指定的JSP标签填充,这个一会再介绍。
在当前生数据成器确实生成数据对象后,方法hasExpired()被才被Cewolf框架调用。当返回TRUE时,产生器将释放以前的数据。
Cewolf框架通过 getProducerId()方法提生成的一个唯一ID来标识一个生成者。2个具有相同ID生成实例将被认为时生成相同的数据。
编译该方法,然后把它放在WEB工程的/WEB-INF/类目录下。
第三步:在WEB工程下安装Cewolf Servlet
整个图的绘制由一个servle产生,所以要事先装入WEB工程,Cewolf提供了一个servlet类de.laures.cewolf.CewolfRenderer用来完成这个工作。
为了配置你的web工程,你必须编辑 /WEB-INF/web.xml,添加下列行。
<servlet>
<servlet-name>CewolfServlet</servlet-name>
<servlet-class>de.laures.cewolf.CewolfRenderer</servlet-class>
</servlet>
另外你要提供一个servlet-mapping来告诉容器URL与Cewolf绘图servlet的映射关系.
Additionally you should provide a servlet-mapping to tell the container which URL maps to your Cewolf rendering servlet.
<servlet-mapping>
<servlet-name>CewolfServlet</servlet-name>
<url-pattern>/cewolf/ *</url-pattern>
</servlet-mapping>
你还需要告诉CeWolf的启动:
<load-on-startup>1</load-on-startup>
检查配置是否正确:
例如浏览器输入
http://localhost:8080/myapp/cewolf?state
Cewolf应该回应: "Cewolf servlet up and running."
下面是例子 web.xml的配置:
<
web-app
>
<
servlet
>
<
servlet-name
>
CewolfServlet
</
servlet-name
>
<
servlet-class
>
de.laures.cewolf.CewolfRenderer
</
servlet-class
>
<!--
sets storage implementation
-->
<
init-param
>
<
param-name
>
storage
</
param-name
>
<
param-value
>
de.laures.cewolf.storage.TransientSessionStorage
</
param-value
>
</
init-param
>
<!--
sets overlib.js location relative to webapp
-->
<
init-param
>
<
param-name
>
overliburl
</
param-name
>
<
param-value
>
etc/overlib.js
</
param-value
>
</
init-param
>
<!--
turn on or off debugging logging
-->
<
init-param
>
<
param-name
>
debug
</
param-name
>
<
param-value
>
true
</
param-value
>
</
init-param
>
<
load-on-startup
>
1
</
load-on-startup
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>
CewolfServlet
</
servlet-name
>
<
url-pattern
>
/cewolf/ *
</
url-pattern
>
</
servlet-mapping
>
<
session-config
>
<
session-timeout
>
1
</
session-timeout
>
</
session-config
>
<
mime-mapping
>
<
extension
>
css
</
extension
>
<
mime-type
>
text/css
</
mime-type
>
</
mime-mapping
>
<
welcome-file-list
>
<
welcome-file
>
index.html
</
welcome-file
>
<
welcome-file
>
index.htm
</
welcome-file
>
</
welcome-file-list
>
<!--
resource-ref>
<description>
Resource reference to a factory for java.sql.Connection
instances that may be used for talking to a particular
database that is configured in the server.xml file.
</description>
<resource-ref-name>
jdbc/testdb
</resource-ref-name>
<res-type>
javax.sql.DataSource
</res-type>
<res-auth>
Container
</res-auth>
</resource-ref
-->
</
web-app
>
第四步:在JSP定义图
第五步:生成ImageMap和Tooltip信息
为了给你的图生成ImageMap和Tooltip信息,你必须自己额外写java类或者修改象下面的一个已经存在的类。在这一步我们将向datasetproducer添加新的方法。
...
public String generateLink(Object data, int series, Object category)
{ return seriesNames[series]; }
public String generateToolTip(CategoryDataset arg0, int series, int arg2)
{ return seriesNames[series]; }
...
可见,生成ImageMap和Tooltip信息是很简单的事情,
首先要实现接口CategoryItemLinkGenerator和CategoryToolTipGenerator (因为生成的是CategoryDataset). 别的数据类型请参见cewolf java api:http://cewolf.sourceforge.net/new/apidoc/index.html
de.laures.cewolf.tooltips下有4个接口:
CategoryToolTipGenerator
PieToolTipGenerator
ToolTipGenerator
XYToolTipGenerator