添加动态逻辑

返回到在本教程前面创建的 index.jsp 和 response.jsp 占位符,您现在可以实现 JSTL 代码,通过该代码,页面可以动态生成内容(即,根据用户输入)。为此,请执行以下三个任务。

  1. 将 JSTL 库添加到项目的类路径中
  2. 实现 JSTL 代码

将 JSTL 库添加到项目的类路径中

您可以应用 JavaServer Pages 标准标记库 (JavaServer Pages Standard Tag Library, JSTL) 访问和显示从数据库提取的数据。GlassFish 服务器在缺省情况下包含 JSTL 库。通过在“项目”窗口中展开 IFPWAFCAD 的“库”> GlassFish 服务器节点并搜索 jstl-impl.jar 文件,可以对此进行验证。缺省情况下,GlassFish 服务器库会被添加到项目的类路径中,因此您不必为此任务执行任何步骤。

JSTL 提供了四个基本功能区。它们是:

  • core:常见的结构性任务,如处理流控制的迭代和条件
  • fmt:国际化和本地化消息格式设置
  • sql:简单数据库访问
  • xml:处理 XML 内容

本教程重点介绍 core 和 sql 标记库的使用。

有关 JSTL 的详细信息,请参见 Java EE 5 教程第 7 章:JavaServer Pages 标准标记库

实现 JSTL 代码

现在,您可以实现动态检索并显示每页数据的代码。两个页面需要您实现 SQL 查询,以便利用在本教程前面所创建的数据源。

IDE 提供了几个特定于数据库的 JSTL 代码片段,您可以从“组件面板”(Ctrl-Shift-8 组合键;在 Mac 上为 &#8984-Shift-8 组合键)中选择它们。

可从“组件面板”获取的数据库代码片段 

您也可以通过在编辑器中按 Ctrl-空格键访问组件面板的各项。键入 "db",然后按 Ctrl-空格键,可以过滤数据库项。

可从“组件面板”获取的数据库代码片段
index.jsp

要在 index.jsp 中动态显示表单的内容,您需要从 Subject 数据库表访问所有 name

  1. 将鼠标悬停在“组件面板”中的“数据库报告”项上。 
    可从“组件面板”获取的数据库代码片段 
    “数据库报告”项使用 <sql:query> 标记创建 SQL 查询,然后使用 <c:forEach> 标记对查询的 resultset 执行循环操作并输出检索到的数据。
  2. 将光标置于 <%@page ... %> 声明(第 7 行)上方,然后双击“组件面板”中的“数据库报告”项。在显示的对话框中,输入以下详细信息:
    • 变量名称:subjects
    • 范围:page
    • 数据源:jdbc/IFPWAFCAD
    • 查询语句:SELECT subject_id, name FROM Subject
    “插入数据库报告”对话框
  3. 单击“确定”。在 index.jsp 文件中生成以下内容。(新内容以粗体显示。)
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%>
    <%--
        Document   : index
        Created on : Dec 22, 2009, 7:39:49 PM
        Author     : nbuser
    --%>
    
    <sql:query var="subjects" dataSource="jdbc/IFPWAFCAD">     SELECT subject_id, name FROM Subject </sql:query>  <table border="1">     <!-- column headers -->     <tr>     <c:forEach var="columnName" items="${subjects.columnNames}">         <th><c:out value="${columnName}"/></th>     </c:forEach> </tr> <!-- column data --> <c:forEach var="row" items="${subjects.rowsByIndex}">     <tr>     <c:forEach var="column" items="${row}">         <td><c:out value="${column}"/></td>     </c:forEach>     </tr> </c:forEach> </table>
    
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
    请注意,IDE 自动添加了生成的内容中使用的 JSTL 标记(<sql:query> 和 <c:forEach>)所需的 taglib 指令。taglib 指令声明 JSP 页使用定制(即,JSTL)标记,命名用于定义这些标记的标记库,并指定其标记前缀。
  4. 运行欢迎页以查看该页面在浏览器中的显示方式。在编辑器中单击鼠标右键,然后选择“运行文件”(Shift-F6 组合键;在 Mac 上为 Fn-Shift-F6 组合键)。 

    该文件部署到 GlassFish 服务器,编译为 Servlet,然后呈现在缺省浏览器中。通过“数据库报告”项生成的代码在欢迎页面中创建以下表格。 
    浏览器显示其中包含 Subject 数据库表数据的表格 
    正如所看到的,通过“数据库报告”项,您可以快速测试数据库连接,并在浏览器中查看数据库的表数据。这对于原型制作尤其有用。 

    以下步骤演示了如何将生成的代码集成到您在本教程前面所创建的 HTML 下拉列表中。
  5. 检查生成的代码中的列数据。共使用了两个 <c:forEach> 标记;其中一个标记嵌套在另一个标记内。这导致 JSP 容器(即,GlassFish 服务器)对所有表行执行循环,对于每行,可对其中的所有列执行循环操作。以此方式显示整个表的数据。
  6. 将 <c:forEach> 标记集成到 HTML 表单中,如下所示。根据数据库中记录的数据,每项的值将变为 subject_id,输出文本将变为 name。(所做的更改以粗体显示)。
    <form action="response.jsp">
        <strong>Select a subject:</strong>
        <select name="subject_id">
            <c:forEach var="row" items="${subjects.rowsByIndex}">             <c:forEach var="column" items="${row}">
                    <option value="<c:out value="${column}"/>"><c:out value="${column}"/></option>
                </c:forEach>         </c:forEach>
        </select>
        <input type="submit" value="submit" name="submit" />
    </form>
    将 <c:forEach> 标记集成到 HTML 表单中的更简单替代方法如下所示。
    <form action="response.jsp">
        <strong>Select a subject:</strong>
        <select name="subject_id">
            <c:forEach var="row" items="${subjects.rows}">
                <option value="${row.subject_id}">${row.name}</option>
            </c:forEach>
        </select>
        <input type="submit" value="submit" name="submit" />
    </form>
    在两种情况下,<c:forEach> 标记都会对 SQL 查询中的所有 subject_id 和 name 值执行循环操作,并将每对值插入 HTML <option> 标记中。在这种方式下,表单的下拉列表中会填入数据。
  7. 删除通过“数据库报告”项生成的表。(删除的内容在下面以 删除线文本 显示。)
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%@taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%>
    <%--
        Document   : index
        Created on : Dec 22, 2009, 7:39:49 PM
        Author     : nbuser
    --%>
    
    <sql:query var="subjects" dataSource="jdbc/IFPWAFCAD">
        SELECT subject_id, name FROM Subject
    </sql:query>
    
    
           
           
            
            <table border="1">     <!-- column headers -->     <tr>     <c:forEach var="columnName" items="${subjects.columnNames}">         <th><c:out value="${columnName}"/></th>     </c:forEach> </tr> <!-- column data --> <c:forEach var="row" items="${subjects.rowsByIndex}">     <tr>     <c:forEach var="column" items="${row}">         <td><c:out value="${column}"/></td>     </c:forEach>     </tr> </c:forEach> </table>
           
           
    
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
  8. 保存所做的更改(Ctrl-S 组合键;在 Mac 上为 &#8984-S 组合键),然后在编辑器中单击鼠标右键并选择“运行文件”(Shift-F6 组合键)。请注意,浏览器中的下拉列表现在包含从数据库检索到的主题名称: 
    在浏览器中显示的主题下拉列表
response.jsp

响应页面提供与欢迎页面中所选主题相对应的顾问详细信息。您创建的查询必须选择符合以下条件的顾问记录:counselor_id 与所选主题记录中的 counselor_idfk 相匹配。

  1. 将光标置于 <%@page ... %> 声明(第 7 行)上方,键入 "db",然后按 Ctrl-空格键。选择“数据库查询”。(请参见上面显示的代码完成提示。)
  2. 在显示的对话框中,输入以下详细信息:
    • 变量名称:counselorQuery
    • 范围:page
    • 数据源:jdbc/IFPWAFCAD
    • 查询语句:SELECT * FROM Subject, Counselor WHERE Counselor.counselor_id = Subject.counselor_idfk AND Subject.subject_id = ? <sql:param value="${param.subject_id}"/>
    “插入数据库查询”对话框
  3. 单击“确定”。在 response.jsp 文件中生成以下内容。(新内容以粗体显示。)
    <%@taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%>
    <%--
        Document   : response
        Created on : Dec 22, 2009, 8:52:57 PM
        Author     : nbuser
    --%>
    
    <sql:query var="counselorQuery" dataSource="jdbc/IFPWAFCAD">     SELECT * FROM Subject, Counselor     WHERE Counselor.counselor_id = Subject.counselor_idfk     AND Subject.subject_id = ? <sql:param value="${param.subject_id}"/> </sql:query>
    
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
    请注意,IDE 自动添加了 <sql:query> 标记所需的 taglib 指令。另请注意,您在查询中直接使用了 <sql:param> 标记。由于此查询依赖于从 index.jsp 提交的subject_id 值,因此可以使用 ${param.subject_id} 格式的 EL(Expression Language,表达式语言)语句提取值,然后将其传递到 <sql:param> 标记,以便在运行时可以使用该值替换 SQL 问号 (?)。
  4. 使用 <c:set> 标记设置与查询所返回的 resultset 的第一个记录(即,行)相对应的变量。(新内容以粗体显示。)
    <sql:query var="counselorQuery" dataSource="jdbc/IFPWAFCAD">
        SELECT * FROM Subject, Counselor
        WHERE Counselor.counselor_id = Subject.counselor_idfk
        AND Subject.subject_id = ? <sql:param value="${param.subject_id}"/>
    </sql:query>
    
    <c:set var="counselorDetails" value="${counselorQuery.rows[0]}"/>
    尽管查询所返回的 resultset 应仅包含一个记录,但此步骤非常有必要,因为页面需要使用 EL(Expression Language,表达式语言)语句访问记录中的值。回想一下,在 index.jsp 中,您使用 <c:forEach> 标记即可轻松访问 resultset 中的值。但是,<c:forEach> 标记的操作方式是通过为查询中包含的行设置变量,从而使您可以通过在 EL 语句中包含行变量来提取值。
  5. 将 JSTL core 库的 taglib 指令添加到文件顶部,以便可以识别 <c:set> 标记。(新内容以粗体显示。)
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%@taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%>
  6. 在 HTML 标记中,将所有占位符替换为 EL 语句代码,该代码显示 counselorDetails 变量中保存的数据。(所做的更改在下面以粗体显示):
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
            <link rel="stylesheet" type="text/css" href="style.css">
            <title>${counselorDetails.name}</title>
        </head>
    
        <body>
            <table>
                <tr>
                    <th colspan="2">${counselorDetails.name}</th>
                </tr>
                <tr>
                    <td><strong>Description: </strong></td>
                    <td><span style="font-size:smaller; font-style:italic;">${counselorDetails.description}</span></td>
                </tr>
                <tr>
                    <td><strong>Counselor: </strong></td>
                    <td><strong>${counselorDetails.first_name} ${counselorDetails.nick_name} ${counselorDetails.last_name}</strong>
                        <br><span style="font-size:smaller; font-style:italic;">
                        <em>member since: ${counselorDetails.member_since}</em></span></td>
                </tr>
                <tr>
                    <td><strong>Contact Details: </strong></td>
                    <td><strong>email: </strong>
                        <a href="mailto:${counselorDetails.email}">${counselorDetails.email}</a>
                        <br><strong>phone: </strong>${counselorDetails.telephone}</td>
                </tr>
            </table>
        </body>
    </html>

 

运行完成的应用程序

现在,您已完成该应用程序。可以尝试再次运行它以查看其在浏览器中的显示方式。请注意,由于 NetBeans 具备“在保存时编译”功能,因此您无需担心编译或重新部署应用程序的问题。运行项目时,您可以确保部署包含您的最新更改。

单击主工具栏中的“运行项目”(“运行项目”按钮) 按钮。在 IDE 的缺省浏览器中打开 index.jsp 页。

当 index.jsp 显示在浏览器中时,从下拉列表中选择一个主题,然后单击 submit。应会立即转至 response.jsp 页,其中显示了与您的选择相对应的详细信息。

在浏览器中显示的 response.jsp,其中显示了从数据库检索到的数据

“使用 MySQL 数据库创建简单的 Web 应用程序”教程到此结束。本文档说明了如何创建用于连接 MySQL 数据库的简单 Web 应用程序。此外,还演示了如何使用基本的两层体系结构构建应用程序,并且使用了 JSP、JSTL、JDBC 和 JNDI 等大量技术作为动态访问和显示数据的方法。

 

疑难解答

教程应用程序出现的大多数问题是由于 GlassFish Server Open Source Edition 与 MySQL 数据库服务器之间的通信发生问题。如果您的应用程序未正确显示,或者如果您收到服务器错误,则执行以下检查会非常有用。

数据库资源是否存在?

使用 IDE 的“服务”窗口(Ctrl-5 组合键;在 Mac 上为 &#8984-5 组合键)确保 MySQL 服务器正在运行,并且 MyNewDatabase 可以访问且包含相应的表数据。

  • 要连接到 MySQL 数据库服务器,请右键单击 MySQL 服务器节点并选择“连接”。
  • 如果 MyNewDatabase 的连接节点 (数据库连接节点) 未显示在“服务”窗口中,可以通过右键单击 MySQL 驱动程序节点 (数据库驱动程序节点) 并选择“连接方法”来创建连接。在显示的对话框中输入所需的详细信息。 
    “新建数据库连接”对话框 
    “新建数据库连接”对话框中提供的字段是对“显示 JDBC URL”选项中输入的 URL 字符串的镜像。因此,如果您知道该 URL(例如jdbc:mysql://localhost:3306/MyNewDatabase),则可以将其粘贴到“显示 JDBC URL”字段中,随之将会自动填充其余对话框字段。
  • 要确保 Subject 和 Counselor 表存在且其中包含样例数据,请展开 "MyNewDatabase" 连接节点 (数据库连接节点),然后找到 "MyNewDatabase" 目录节点 (数据库目录节点)。展开该目录节点以查看现有表。可以通过右键单击表节点并选择“查看数据”来查看表数据。 
    “服务”窗口 - 数据库表节点的右键单击菜单

服务器上是否存在连接池和数据源?

将应用程序部署到 GlassFish 服务器后,项目中包含的 sun-resources.xml 应指示服务器创建 JDBC 资源和连接池。您可以从“服务”窗口中的“服务器”节点确定 JDBC 资源和连接池是否存在。

  • 展开“服务器”> "GlassFish Server 3.0.1" >“资源”节点。展开“JDBC 资源”以查看从 sun-resources.xml 创建的 jdbc/IFPWAFCAD 数据源。展开“连接池”节点以查看从 sun-resources.xml 创建的 IfpwafcadPool 连接池。(这在上面部分进行了演示。)

GlassFish 服务器是否可以访问 MySQL Connector/J 驱动程序?

确保已将 MySQL Connector/J 驱动程序部署到 GlassFish 服务器。(这在将数据库驱动程序的 JAR 文件添加到服务器中进行了讨论。)

  • 找到您计算机上的 GlassFish 服务器安装文件夹,然后向下浏览到 GlassFish domains/domain1/lib 子文件夹。您在此处应该可以找到 mysql-connector-java-5.1.6-bin.jar 文件。

数据库是否受口令保护?

数据库需要受口令保护才能在本教程中使 GlassFish 服务器数据源正常工作。如果您使用的是缺省 MySQL root 帐户和空口令,则可以通过命令行提示符设置口令。

  • 要将口令设置为 nbuser,请在命令行提示符下导航至 MySQL 安装的 bin 目录,然后输入以下内容:
    shell> mysql -u root
    mysql> UPDATE mysql.user SET Password = PASSWORD('nbuser')
        ->     WHERE User = 'root';
    mysql> FLUSH PRIVILEGES;
    有关详细信息,请参见正式的 MySQL 参考手册:《确保初始 MySQL 帐户安全》

连接池属性是否设置正确?

确保服务器的连接池工作正常。

  1. 打开“服务”窗口(Ctrl-5 组合键;在 Mac 上为 &#8984-5 组合键),然后展开“服务器”节点。
  2. 右键单击 GlassFish 服务器节点,然后选择“查看管理控制台”。
  3. 输入 admin/adminadmin 分别作为缺省用户名/口令。
  4. 在控制台左侧的树中,展开“资源”> "JDBC" >“连接池”> "IfpwafcadPool" 节点。IfpwafcadPool 连接池的详细信息将显示在主窗口中。
  5. 单击 "Ping" 按钮。如果连接池设置正确,将看到“Ping 成功”消息。 
    显示的 GlassFish 服务器管理控制台 - 连接池