JSP提供了很多简单实用的工具,其中包括从数据库中读出数据,发送数据,并能够把结果显示在一个饼状图形。现在让我们看看这一简单而实用的方法。
你所需要的东西
为了能正确运行这一文章相关的范例,你必须需要JDK 1.2或更高的版本、一个关系数据库管理系统、一个JSP网络服务器。我都是在Tomcat调试这些例子,同时我也使用了Sun Java 2 SDK发布的com.sun.image.codec.jpegclasses。
数据库设计
假设你在一家从事销售新鲜水果的公司上班,公司出售的水果包括:苹果、桔子、葡萄。现在你的老板想用一个饼状图形显示每一种水果的总出售量,饼状图形能使每一种产品的销售情况一目了然,老板可以迅速掌握公司的产品成交情况。
表A使用了本文中的两种数据库列表。第一种列表(Products)包含所有销售产品的名称;第二种列表(Sales)包含每一种产品对应的销售量。
Listing A
Database Design
---------------
p_products table
----------------
productID int (number) not null
productname String (varchar) not null
p_sales table
-------------
saleID int (number) not null
productID int (number) not null
amount float not null
产品(Products)列表包含productID和productname两个域。销售(Sales)列表包含saleID, productID,以及总额。销售列表中的productID提供了这两个列表之间的关联。销售列表中的总额包含了每一次出售的现金数额,这些数额以浮点型数据出现。
表B中的getProducts()方法连接了两个数据库,并把所有的产品名称保存在数组中:
Listing B
////////////////////////////////////////////////////////////
//Get products from the database as a String array
////////////////////////////////////////////////////////////
public String[] getProducts()
{
String[] arr = new String[0];
Connection con;
Statement stmt;
ResultSet rs;
int count = 0;
String sql = "select * from p_products order by productID";
try
{
//Load Driver: Class.forName(driver);
//Connect to the database with the url
con = DriverManager.getConnection(dburl , dbuid , dbpwd);
stmt = con.createStatement();
//Get ResultSet
rs = stmt.executeQuery(sql);
//Count the records
while(rs.next())
{count++;}
//Create an array of the correct size
arr = new String[count];
//Get ResultSet (the portable way of using rs a second time)
rs = stmt.executeQuery(sql);
while(rs.next())
{
arr[rs.getInt("productID")] = rs.getString("productname");
}
stmt.close();
con.close();
}
catch (java.lang.Exception ex)
{
arr[0] = ex.toString();
}
return arr;
}
我设置以下的数据库规则:
1、ProductID在产品列表中最独特,也是最关键;
2、ProductID对于第一个记录的值为0;
3、所有之后的连续的记录都是累加的,所以第二个记录的productID为1,第三个记录的productID为2,以此类推。
这些数据库规则允许在product数组中存储数据,如下所示:
arr[rs.getInt("productID")] = rs.getString("productname");
一些数据库管理系统在缺省情况下就允许数据的自动累加或者自动排序。当你在设计数据库时,一定先查明你的数据库管理系统遵循哪些规则,比如自动累加,自动排序等。
获取总销售量
在多数情况下,销售列表中会有很多个记录,所以访问数据库的快捷性和高效性显得非常重要。现在我们只需要访问数据库中每一种产品的总额销售量。
表C中的getSales()方法与数据库连接并返回一个数组,这个数组包含每一种产品的总额出售量。
Listing C
////////////////////////////////////////////////////////////
//Get the sales totals from the database
////////////////////////////////////////////////////////////
public float[] getSales(int products)
{
float[] arr = new float[products];
Connection con;
Statement stmt;
ResultSet rs;
int count = 0;
String sql = "select productID, amount from p_sales";
try
{
//Load Driver:
Class.forName(driver);
//Connect to the database with the url
con = DriverManager.getConnection(dburl , dbuid , dbpwd);
stmt = con.createStatement();
//Get ResultSet
rs = stmt.executeQuery(sql);
while(rs.next())
{
int product = rs.getInt("productID");
//Check that the productID is valid
if (product >= 0 && product < products)
{
//Add to product total
arr[product] += rs.getFloat("amount");
count++;
}
}
stmt.close();
con.close();
}
catch (java.lang.Exception ex)
{
arr[0] = -1.0f;
}
return arr;
}
当getSales()遍历所有的记录后,它只存储的是每一种产品新的出售量:
int product = rs.getInt("productID");
arr[product] += rs.getFloat("amount");
pieColor对象
饼状图形上的每一种产品应该以不同的颜色显示。为了达到这一目的,我们建立一个pieColor对象(如表D)所示,这一对象包含有关颜色的数组:
Color pieColorArray[] = {new Color(210,60,60), new Color(60,210,60)…}
pieColor类定义了一个setNewColor()的方法,这一方法能够使curPieColor和索引递增,同时它可以检查索引不要超过边界范围,即采用的方法是:如果curPieColor过大即赋0值。
更有效的是,setNewColor()循环每一种颜色后,并在第一种颜色下执行以下的代码:
curPieColor++;
if(curPieColor >= pieColorArray.length)
{curPieColor = 0;}
RenderingHints和antialiasing类
java.awt.RenderingHints类定义了很多方法以显示二维图形,包括alpha_interpolation, 抖动,以及antialiasing方法。RenderingHints有助于决定图形如何显示以及图形如何达到最佳处理。
为了能以平滑显示,可以使用antialiasing方法来处理饼状图形。Antialiasing是一种图形的平滑处理方法。其算法是选择一个特殊象素的颜色值并取代交叉处的象素,从而能够使线条交叉处得到平滑化。
图A说明了antialiasing方法的效果。可以看出使用antialiasing方法的饼状图形的线条交叉处变得很平滑。