在 Java 应用开发源动力:下载免费软件,快速启动开发 中,您做了以下几件事:
数据挖掘工具
- 下载和安装 DB2 Express-C、Application Server、Eclipse 和 Application Server plug-in for Eclipse。
- 安装在 DB2 Express-C 中包含员工信息的示例数据库(由 DB2 Express-C 安装提供)。
- 在 Application Server 中部署一个服务器托管的数据库池。
- 在 Eclipse 中配置集成的 Database Explorer 视图,以访问 DB2 示例数据库的模式和表内容。
- 使用 Eclipse 的 Web Tools Project (WTP) Web 应用程序开发支持编写一个 JSP 应用程序,用于访问 DB2 示例数据库以列出员工信息。
- 使用 Application Server plug-in for Eclipse 将 JSP 应用程序部署到 Application Server 以进行测试。
- 通过将其部署在 Application Server 的一个 Eclipse 托管的实例中,而对 JSP 应用程序进行测试。
从您在 Java 应用开发源动力:下载免费软件,快速启动开发 中创建的简单应用程序开始,本教程添加一个新的 JSP 页面,让您从 DB2 数据库交互式地查询员工信息。初始的应用程序在一个表中列出所有员工的信息,而该 JSP 应用程序则一次一条记录地显示员工信息。
数据挖掘研究院
显示的信息包括员工的照片,如图 1 所示: 数据挖掘研究院
图 1. 交互式员工信息显示应用程序
为了显示照片,一个专门的 servlet 在 DB2 数据库中查询存储在 BLOB 字段的二进制图像数据,然后将照片作为一个图像传输给浏览器。Eclipse 的 WTP 的应用程序开发和测试设施可以帮助您快速创建这个 servlet。
该设计的交互性是有限的,它不能处理较大的员工数据库,所以我将介绍一个改进的解决方案,通过应用现代轻量级 Ajax 技术来克服这些缺点。 数据挖掘实验室
创建基于 JSP 的员工信息应用程序 数据挖掘论坛
该应用程序的第一个版本显示一个员工的信息,包括他或她的照片(如果有的话),如 图 1 所示。用户从员工姓名下拉列表选择要显示的员工信息。在图 1 中,选择并显示的是 Bruce Adamson 的员工记录。 数据挖掘论坛
创建该应用程序最容易的方式是修改 Java 应用开发源动力:下载免费软件,快速启动开发 中的项目。图 2 展示了那个教程的 Eclipse IDE 项目: 数据挖掘研究院
图 2. 初始的 dwapp Eclipse 项目,显示一个员工表
数据挖掘交友
从图 2 所示的 dwapp 项目开始,您将添加或修改表 1 中的 Web 应用程序组件:
表 1. 员工信息 Web 应用程序的组件
| 组件 |
描述 |
| employee.jsp |
一个无脚本的(没有嵌入式的 Java 代码)JSP 页面,用于处理用户交互和使用 JSTL SQL 标记来在 DB2 数据库中查询信息。您将添加该组件。 |
| ShowPhoto.java servlet |
一个 Java servlet,用于在 DB2 数据库中查询员工照片信息。员工照片以多种格式存储在数据库的 BLOB 字段中。但我们只使用 GIF 格式的照片。该 servlet 以与浏览器 <IMG> 元素预期的 MIME 类型兼容的格式写入输出流。数据库访问是通过一个从 Java Naming and Directory Interface (JNDI) 中获得的系统数据源来完成的,这需要获得在 Java 应用开发源动力:下载免费软件,快速启动开发 中配置的 Application Server 系统范围内的数据库池的支持。您将添加该组件。 |
| dwstyles.css |
您将修改该样式表来处理新的 employee.jsp 页面的附加格式化。 |
数据挖掘交友
数据挖掘工具
应用程序组件如何协同工作
数据挖掘工具
图 3 展示了应用程序组件如何协同工作:
数据挖掘交友
图 3. 员工信息应用程序的结构
数据挖掘研究院
employee.jsp 组件生成包含用户界面的 Web 页面。这个生成的 Web 页面呈现在用户浏览器中。用户与生成的页面交互,以通过提交 HTML 表单查询员工信息。JSP 处理提交的表单数据,并从数据库取回员工信息。JSP 然后生成并返回一个带有信息的 Web 页面。GIF 格式的员工照片由 ShowPhoto servlet 独立生成。该 servlet 从同一 DB2 Express-C 数据库获得图像数据。 数据挖掘交友
数据挖掘论坛
使用 “Java 应用开发源动力” 套件编写、测试和部署应用程序 数据挖掘研究院
图 4 展示了 “Java 应用开发源动力” 套件如何帮助创建这个应用程序: 数据挖掘交友
图 4. 用免费工具开发应用程序
数据挖掘工具
您将在 Eclipse 中编写应用程序,并使用 Application Server 的一个实例在 Eclipse 的控制下部署和测试该应用程序。
应用程序的 JSP 组件通过 Application Server 托管的一个 JDBC 池访问 DB2 Express-C 示例数据库。应用程序的 servlet 组件也使用相同的托管池从数据库访问 BLOB 字段,并将它们转换成位图图形信息,显示员工照片。
员工选择 JSP
数据挖掘工具
从 图 2 所示的 Eclipse dwapp 项目开始,右击 Navigator 视图中的 WebContent 文件夹并选择 New>Other...(或者按 Ctrl+N)。从 New 向导选择 Web>JSP,如图 5 所示: 数据挖掘交友
图 5. 使用 Eclipse New 向导创建新的 JSP
单击 Next,然后输入 employee.jsp 作为新 JSP 的名称。单击 Finish 完成初始 JSP 模板的生成。 数据挖掘工具
现在编辑生成的 JSP,即添加清单 1 中粗体显示的代码:
清单 1. employee.jsp 组件,用于处理用户界面交互
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<link rel="stylesheet" type="text/css" href="dwstyles.css"/>
<title>dW Example Employee Information from DB2 Express C Table</title>
</head>
<body>
<h1>DB2 Employee Information</h1>
<br/>
<c:url value="/employee.jsp" var="empURL"/>
<form action="${empURL}" method="get">
<table>
<tr>
<td colspan="2">
<select name="empno">
<sql:query var="employees" dataSource="jdbc/DataSource">
SELECT * FROM EMPLOYEE ORDER BY LASTNAME
</sql:query>
<c:forEach var="employee" items="${employees.rows}">
<option value="${employee.empno}">${employee.lastname},
${employee.firstnme}</option>
</c:forEach>
</select>
</td>
<td>
<input type="submit" value="find employee"/>
</td>
</tr>
<c:if test="${!(empty param.empno)}">
<sql:query var="selected" dataSource="jdbc/DataSource">
SELECT * FROM EMPLOYEE WHERE EMPNO=′${param.empno}′
</sql:query>
<c:forEach var="employee" items="${selected.rows}">
<tr>
<td colspan="3" class="name">
${employee.lastname}, ${employee.firstnme}
<br/>
</td>
</tr>
<tr>
<td colspan="2" valign="top">
<table>
<tr>
<td class="label">Employee number:</td><td>${employee.empno}</td>
</tr>
<tr>
<td class="label">Position:</td><td>${employee.job}</td>
</tr>
<tr>
<td class="label">Hired:</td><td>${employee.hiredate}</td>
</tr>
<tr>
<td class="label">Department:</td><td>${employee.workdept}</td>
</tr>
<tr>
<td class="label">Phone number:</td><td>${employee.phoneno}</td>
</tr>
<tr>
<td class="label">Salary:</td><td>${employee.salary}</td>
</tr>
<tr>
<td class="label">Bonus:</td><td>${employee.bonus}</td>
</tr>
</table>
</td>
<td>
<c:url value="/ShowPhoto" var="photoURL">
<c:param name="empno" value="${param.empno}" />
</c:url>
<img src="${photoURL}"/>
</td>
</c:forEach>
</tr>
</c:if>
</table>
</form>
</body>
</html>
|
遵循 JSP 最佳实践,employee.jsp 不包含嵌入式的 Java 代码;所有动态代码生成都是通过 JSTL 和 Expression Language (EL) 处理的。 数据挖掘工具
employee.jsp 如何操作
数据挖掘研究院
图 1 展示了 employee.jsp 的布局。一个下拉列表(即一个 HTML <select> 元素)保持有员工姓名的列表。
数据挖掘论坛
用户从该列表选择任何一个员工并单击 find employee 按钮。所选择的员工的详细信息然后就会显示出来,还会显示员工的照片(如果有的话)。(并不是所有员工都在 DB2 示例数据库中有照片。)
在 employee.jsp 中,下拉列表是使用清单 2 中的 JSTL 代码生成的:
数据挖掘工具
清单 2. 用于选择的员工姓名的动态生成
<select name="empno">
<sql:query var="employees" dataSource="jdbc/DataSource">
SELECT * FROM EMPLOYEE ORDER BY LASTNAME
</sql:query>
<c:forEach var="employee" items="${employees.rows}">
<option value="${employee.empno}">${employee.lastname},
${employee.firstnme}</option>
</c:forEach>
</select>
数据挖掘工具
|
数据挖掘研究院
使用 JSTL SQL <sql:query> 标记来执行从 DB2 数据库选择所有员工记录的查询。这类似于在 Java 应用开发源动力:下载免费软件,快速启动开发 例子中使用的查询。这次,返回的员工信息是按姓氏的字母顺序排列的(由于 SQL 查询中使用了 ORDER BY LASTNAME 子句),以方便从下拉列表选择姓名。
数据挖掘工具
针对指定的 jdbc/DataSource 执行 SQL 查询。这配置在应用程序的 geronimo-web.xml 部署计划中,并指向名为 dwDatasource 的系统范围的数据库池,该池配置在 Application Server 上。
然后使用 <c:forEach> JSTL 迭代标记一行行地从头到尾的迭代员工选择列表。为每个员工生成一个 HTML <option>。<option> 的值是员工号,而显示的文本是员工的姓名。例如,为 Bruce Adamson 生成的 <option> 是:
数据挖掘论坛
<option value="000150">ADAMSON, BRUCE</option>
|
整个 <select> 元素存在于一个封闭的 HTML <form> 中,如清单 3 中的粗体所示: 数据挖掘交友
清单 3. <form> 元素中的 <select> 列表
<c:url value="/employee.jsp" var="empURL"/>
<form action="${empURL}" method="get">
<table>
<tr>
<td colspan="2">
<select name="empno">
...
</select>
</td>
<td>
<input type="submit" value="find employee"/>
</td>
</tr>
...
</table>
</form>
数据挖掘交友
|
数据挖掘实验室
<c:url> URL 链接生成标记为您创建一个正确格式化的 URL,为表单处理指回这同一个 employee.jsp。这个 URL 放置在一个名为 empURL 的变量中,并用于 <c:form> 标记的 action 属性中。 数据挖掘研究院
当一个用户选择一个员工(例如 Bruce Adamson,其 empno=000150)并单击 find employee 按钮时,表单信息被提交回 employee.jsp,以处理该 URL:
数据挖掘实验室
http://localhost:8080/dwapp/employee.jsp?empno=000150
数据挖掘交友
|
处理 HTML 表单提交 数据挖掘论坛
employee.jsp 页面具有两个角色: 数据挖掘实验室
要确定是否进行了表单提交,需要检查 empno HTTP GET 参数是否存在。对于这样的检查,您可以使用 JSTL 中的 empty 操作符。用于呈现员工信息和照片的代码包含在执行该测试的 <c:if> 标记中。该代码段展示在清单 4 中: 数据挖掘研究院
清单 4. 测试是否存在 empno 表单参数
<c:if test="${!(empty param.empno)}">
<sql:query var="selected" dataSource="jdbc/DataSource">
SELECT * FROM EMPLOYEE WHERE EMPNO=′${param.empno}′
</sql:query>
<c:forEach var="employee" items="${selected.rows}">
...
</c:forEach>
</c:if>
数据挖掘交友
|
数据挖掘论坛
如果提交的 HTTP 请求没有 empno 参数,就不会生成任何员工信息。
要生成员工详细信息,需要针对 EMPLOYEE 表执行另一个 <sql:query>。这个 SELECT 现在指向一个具有相应员工号的员工。JSTL 中的对象 param 被用于将提交的empno 参数的值传递到 SELECT 语句中 ,如清单 5 所示:
清单 5. 使用动态生成的 SQL 查询获得单个员工的记录
<c:if test=""${!(empty param.empno)}">
<sql:query var="selected" dataSource="jdbc/DataSource">
SELECT * FROM EMPLOYEE WHERE EMPNO=′${param.empno}′
</sql:query>
<c:forEach var="employee" items="${selected.rows}">
...
</c:forEach>
</c:if>
数据挖掘研究院
|
数据挖掘论坛
尽管这里使用了 <c:forEach> 构造,但是您也只处理一行(因为每个员工具有惟一的员工号)。这个 JSTL 构造简化了对返回的结果集中行数据的访问。要生成文本信息,可直接使用 <c:forEach> 设置的 employee 变量。例如,下面的 EL 表达式在 <c:forEach> 构造中生成员工的电话号码:
数据挖掘实验室
数据挖掘交友
为了生成员工照片,您使用一个 HTML <img> 标记。显示图像的 URL 是使用 JSTL <c:url> 标记生成的: 数据挖掘交友
<c:url value="/ShowPhoto" var="photoURL">
<c:param name="empno" value="${param.empno}" />
</c:url>
<img src="${photoURL}"/>
数据挖掘研究院
|
例如,为 Bruce Adamson(他的 empno 是 00150)生成的有效 <img> 标记是:
<img src="http://localhost:8080/dwapp/ShowPhoto?empno=00150"/>
数据挖掘工具
|
数据挖掘工具
这意味着以下 URL 必须生成代表员工照片的位流:
http://localhost:8080/dwapp/ShowPhoto?empno=00150
数据挖掘实验室
|
数据挖掘工具
ShowPhoto.java servlet 生成照片位流。
数据挖掘交友
从 DB2 BLOB 字段展示照片
员工照片存储在 DB2 示例数据库的 EMP_PHOTO 表中。表 2 描述了这个表的字段: 数据挖掘交友
表 2. EMP_PHOTO 表的字段
| 字段名 |
描述 |
empno |
相应员工的员工号。 |
photo_format |
照片的格式。照片以多种格式存储,以方便显示,而无需复杂的转换代码。该应用程序只使用 GIF 格式的照片。 |
picture |
图片的二进制位,存储在 BLOB 字段中。该字段的最大大小是 102,400 字节。 |
数据挖掘工具
要在 Eclipse IDE 中创建 ShowPhoto.java servlet,首先突出显示 WebContent 并选择 New>Other...(或者按 Ctrl+N)。在 New 向导中选择 Web>Servlet。为 Java Package 输入 com.ibm.dw,为类名输入 ShowPhoto,如图 6 所示: 数据挖掘工具
图 6. 利用 Eclipse WTP 的 Create Servlet 向导创建一个新的 servlet
数据挖掘交友
单击 Next。在下一个屏幕,您可以为 servlet 设置 URL 映射。该 URL 映射被作为 <servlet-mapping> 元素自动放入应用程序的 web.xml 部署描述符中。在本例中,您可以保持到 /ShowPhoto 的默认映射。单击 Finish。 数据挖掘实验室
如果查看 Navigator 视图,会在 WebContent 文件夹外面的 src 目录下看到 com.ibm.dw.ShowPhoto.java 文件。Eclipse WTP 将源代码保存在这里以便易于维护和组织,但是将已编译的类文件复制到 WEB-INF/classes 目录下的正确位置以自动部署 Web 应用程序。 数据挖掘实验室
刚才完成的这些步骤在 ShowPhoto.java 中生成一个骨架 servlet。现在通过添加清单 6 中粗体显示的代码行来编辑代码: 数据挖掘工具
清单 6. ShowPhoto.java servlet 的附加代码
package com.ibm.dw;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
/**
* Servlet implementation class for Servlet: ShowPhoto
*
*/
public class ShowPhoto extends javax.servlet.http.HttpServlet
implements javax.servlet.Servlet {
public ShowPhoto() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String query = "select picture from emp_photo where
photo_format=′gif′ and empno=′"
+ request.getParameter("empno") + "′";
DataSource dsource = null;
Statement stmt= null;
Connection conn =null;
ResultSet rset = null;
try {
InitialContext context = new InitialContext();
dsource =
(DataSource)context.lookup("java:comp/env/jdbc/DataSource");
conn = dsource.getConnection();
stmt = conn.createStatement();
rset = stmt.executeQuery(query);
if (rset.next()) {
byte[] buffer = new byte[32000];
int size=0;
InputStream istream;
istream = rset.getBinaryStream(1);
response.reset();
response.setContentType("image/gif");
while((size= istream.read(buffer))!= -1 ) {
response.getOutputStream().write(buffer,0,size);
}
response.flushBuffer();
istream.close();
}
} catch(NamingException e) {
} catch(SQLException e) {
}
finally {
try {
if (rset != null)
rset.close();
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
} catch (SQLException ex ) {}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
数据挖掘交友
|
数据挖掘交友
使用 Eclipse 的自动导入管理器
数据挖掘工具
如果愿意,您可以从本教程的源代码剪切并粘贴(参见 下载)。如果手动输入代码,也不需要输入大量的 import。Eclipse 可以在所有可用的项目库中搜索 import 符号。在代码编辑器中右击并选择 Source>Organize Imports(或者按 Ctrl+Shift+O)。这将在源代码中寻找所有未解析的 import 并在源代码的开始添加所有的 import 语句。如果 Eclipse 在解析 import 时遇到不确定的情况,它会提示您选择应该正确从中导入的库软件包。
该特性可让您在日常编码活动中省去大量烦琐的手动搜索。 数据挖掘实验室
数据挖掘研究院
ShowPhoto servlet 的操作
提交的 HTTP 请求包含一个名为 empno 的参数。该参数用于从 EMP_PHOTO 表取回正确的照片。下面设置了该查询: 数据挖掘工具
String query =
"select picture from emp_photo where photo_format=′gif′ and empno=′"
+ request.getParameter("empno") + "′";
数据挖掘实验室
|
数据挖掘研究院
该查询针对设置在部署计划 geronimo-web.xml 中的 jdbc/DataSource 而运行。该数据源链接到名为 dwDatasource 的系统范围的数据库池,该数据库池配置在 Application Server 上。对于宿主在 Application Server 中的 servlets,您可以使用 JNDI 执行查询: 数据挖掘工具
InitialContext context = new InitialContext();
dsource = (DataSource)context.lookup("java:comp/env/jdbc/DataSource");
数据挖掘实验室
|
数据挖掘实验室
一旦获得数据源,就可以使用标准 JDBC 编码执行查询了:
conn = dsource.getConnection();
stmt = conn.createStatement();
rset = stmt.executeQuery(query);
数据挖掘实验室
|
要取得 picture 字段作为二进制输入流,可使用字段 #1(该字段是 SELECT 查询得到的 JDBC ResultSet 中的 picture 字段)上的 getBinaryStream() 方法:
数据挖掘实验室
InputStream istream;
istream = rset.getBinaryStream(1);
数据挖掘实验室
|
您需要将 servlet 的响应设置为正确的 contentType,确保浏览器可以解释 image/gif mime 类型属性:
数据挖掘论坛
response.reset();
response.setContentType("image/gif");
数据挖掘交友
|
数据挖掘研究院
剩下要做的就是从 picture 字段的二进制流读取数据,并写到响应的输出流: 数据挖掘交友
while((size= istream.read(buffer))!= -1 ) {
response.getOutputStream().write(buffer,0,size);
}
数据挖掘论坛
|
数据挖掘交友
这就完成了 ShowPhoto.java servlet。接下来,将设置应用程序的初始欢迎页面。 数据挖掘论坛
数据挖掘工具
设置 Web 应用程序的欢迎页面 数据挖掘研究院
默认情况下,Web 应用程序将 index.jsp 显示为欢迎页面。这是请求以下 URL 时 Application Server 显示的页面:
数据挖掘实验室
http://localhost:8080/dwapp/
|
index.jsp 当前包含老员工列表应用程序。您需要将欢迎页面更改为指向 employee.jsp。从 Navigator 视图打开 web.xml 文件,然后查找 <welcome-file-list> 元素。该元素包含为应用程序显示欢迎页面时 Application Server 查找的文件。对该元素作出以下更改(在清单 7 中显示为粗体):
清单 7. 配置 employee.jsp 作为应用程序欢迎页面
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>employee.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
数据挖掘工具
|
数据挖掘研究院
修改样式表
您也需要修改初始的 dwstyles.css 样式表,以包含 employee.jsp 所使用的附加的样式元素,如清单 8 中的粗体所示: 数据挖掘论坛
清单 8. 添加到 dwstyles.css 样式表的新元素
@CHARSET "ISO-8859-1";
h1 {
font-family: arial;
font-size: 38;
align: left;
font-weight: bold;
font-style: italic;
color: green;
}
h2 {
font-family: serif, times;
font-size: 18;
align: left;
color: blue;
}
th {
font-family: verdana, arial;
font-size: 13;
font-weight: bold;
align: left;
background-color: black;
color: white;
}
td {
font-family: verdana, arial;
font-size: 12;
font-style: italic;
text-align: left;
}
table {
border-style: solid;
border-width: thin;
}
.label {
font-size: 16;
font-weight: bold;
font-style: normal;
text-align: right;
}
.name {
font-size: 24;
font-weight: bold;
font-style: italic;
font-family: serif, times roman;
}
|
数据挖掘实验室
试验员工信息应用程序 数据挖掘实验室
在可以运行应用程序之前,还需要通过编译 Java 代码和创建 WAR 文件而构建项目。在 Navigator 视图中右击 dwapp,并选择 Build Project。您的 Eclipse 项目也许会被设置为自动构建,在这样的情况下,您不需要每次都手动构建。检查 Eclipse 的菜单栏上的 Project 菜单,看项目是否设置为自动构建。 数据挖掘实验室
要将新的应用程序部署到 Application Server 并进行测试,在 Navigator 视图中右击 dwapp 项目并选择 Run As>Run on Server。
如果 Application Server 没在运行,Eclipse 将启动它。应用程序被打包为一个 WAR 文件并部署到 Application Server。Eclipse 启动一个内部 Web 浏览器并访问应用程序的欢迎页面。
数据挖掘实验室
您现在可以尝试选择数据库中的不同员工以查看他们的详细信息。如果您选择的员工具有照片,那么也会显示这个照片。 数据挖掘研究院