在一些Web软件的开发过程中,我们会遇到显示动态图片的问题,如根据数据库内容生成的柱状图、饼图等等。下面的例子是利用Servlet绘制一个成绩统计柱状图,并把图形和相关文字信息一同显示到网页上。数据用Access存储,如果需要运行该程序,应在Access中建立一个"test"表,并设计其唯一列名为"score",类型为数字即可。输入若干成绩数据之后建立一个数据源(如test),并把web.xml文件的<param-value>sample</param-value>处sample改成数据源名称。
web.xml的内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>CreateImage</servlet-name>
<servlet-class>CreateImage</servlet-class>
<init-param>
<param-name>dsn</param-name>
<param-value>sample</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>CreateImage</servlet-name>
<url-pattern>/CreateImage</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
index.jsp内容如下:
<%@ page contentType="text/html;charset=gb2312" %>
<html>
<head>
<title>Servlet动态统计图实例</title>
</head>
<body>
<h2>Servlet动态统计图实例</h2><hr>
<jsp:include page="CreateImage?type=text" />
</body>
</html>
CreateImage.java内容如下:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
public class CreateImage extends HttpServlet {
String url=null;
public void init(){
url="jdbc:odbc:"+getInitParameter("dsn");
}
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Connection con = null;
Statement stmt = null;
ResultSet rs=null;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //装载数据库驱动
con= DriverManager.getConnection(url,"","");
stmt = con.createStatement();
}
catch(Exception e){
log(e.toString());
}
String type=request.getParameter("type");
if ("text".equals(type)){
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("共有"+executeQuery(stmt,"select count(*) from test")+"名学生,其中:<ul>");
out.println("<li>最高分为"+executeQuery(stmt,"select max(score) from test")+"分,");
out.println("最低分为"+executeQuery(stmt,"select min(score) from test")+"分,");
out.printf("平均分为%5.2f分,",(double)executeQuery(stmt,"select sum(score) from test") / executeQuery(stmt,"select count(*) from test"));
out.printf("及格率为%5.2f%。</li>",(double)executeQuery(stmt,"select count(*) from test where score>=60")*100/executeQuery(stmt,"select count(*) from test"));
out.println("<li>90-100分为"+executeQuery(stmt,"select count(*) from test where score>=90")+"人,");
out.println("80-90分为"+executeQuery(stmt,"select count(*) from test where score>=80 and score<90")+"人,");
out.println("70-80分为"+executeQuery(stmt,"select count(*) from test where score>=70 and score<80")+"人,");
out.println("60-70分为"+executeQuery(stmt,"select count(*) from test where score>=60 and score<70")+"人,");
out.println("60分以下为"+executeQuery(stmt,"select count(*) from test where score<60")+"人。</li></ul><p>");
out.println("<img src='CreateImage?type=image'>");
out.flush();
out.close();
}
else{
int maxCount=0;
int width = 600, height = 240;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(Color.white);
g.fillRect(0,0,width,height);
g.setColor(Color.black);
g.drawRect(0,0,width-1,height-1);
g.setColor(Color.green);
g.drawLine(20,210,570,210); //画横坐标轴
g.drawLine(20,10,20,210); //画竖坐标轴
g.setColor(Color.black);
g.setFont(new Font("Verdana",Font.ITALIC,9));
for(int i=1;i<=10;i++) //分数段标识
g.drawString((i*10-10)+"-"+(i*10),i*50,220);
try {
int cnt[]=new int[10];
for(int i=0;i<10;i++){
String sqlString="Select count(*) from test where score>="+(i*10)+" and score<"+(i*10+10);
rs=stmt.executeQuery(sqlString);
rs.next();
cnt[i]=rs.getInt(1);
rs.close();
}
for(int i=0;i<10;i++)
if (maxCount<cnt[i]) maxCount=cnt[i];
for(int i=0;i<10;i++){
g.setColor(Color.red);
g.fillRect((i+1)*50+8, 210-cnt[i]*200/maxCount,14,cnt[i]*200/maxCount);
g.setColor(Color.black);
if (cnt[i]!=0) g.drawString(""+cnt[i], (i+1)*50+22,215-cnt[i]*5*40/maxCount);
}
}
catch(Exception e){
log(e.toString());
}
g.dispose();
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
ServletOutputStream sos=response.getOutputStream();
ImageIO.write(image, "jpeg", sos);
sos.close();
}
}
private int executeQuery(Statement stmt,String query){
try{
ResultSet rs=stmt.executeQuery(query);
rs.next();
return rs.getInt(1);
}
catch(Exception e){
log(e.toString());
return 0;
}
}
}