42、JavaServer Pages:动态网页开发的高效解决方案

JavaServer Pages:动态网页开发的高效解决方案

在网页开发中,我们常常需要处理动态内容和静态内容。Java Servlets能轻松动态生成HTML文本,但在处理不变的HTML文本时却显得力不从心。而JavaServer Pages(JSP)则为这个问题提供了很好的解决方案。

1. 页面背景颜色修改

在网页开发中,有时需要修改页面的背景颜色。操作步骤如下:
- 打开相关页面,找到“Choose a new color”文本框。
- 在该文本框中输入新的颜色值。颜色值以“#”开头,后面跟着三个两位的十六进制数字,例如“#AAFFAA” 。这些数字分别代表颜色中红、绿、蓝的含量,取值范围从“00”到“FF” 。
- 点击“Change Color”按钮,即可完成背景颜色的修改。

以下是一些常见的十六进制颜色值及其对应的颜色:
| 颜色值 | 颜色 |
| ---- | ---- |
| #FF0000 | 亮红色 |
| #00FF00 | 亮绿色 |
| #0000FF | 亮蓝色 |
| #FFAAAA | 浅红色 |
| #AAFFAA | 浅绿色 |
| #AAAAFF | 浅蓝色 |
| #FFCC66 | 奶油糖果色 |

2. JavaServer Pages概述

Java Servlets虽然能动态生成HTML文本,根据用户输入和数据改变页面内容,但在处理静态HTML文本时存在困难。每次修改HTML都需要Java程序员编辑、重新编译并部署Servlet,这对于很多组织来说,让非程序员处理这样的任务是不现实的。

JavaServer Pages是Sun Microsystems和Apache Software Foundation的Tomcat规范的一部分,它是Servlet的补充而非替代。JSP可以将静态HTML与Servlet的输出以及Java语言的元素(如表达式和Java语句)混合在一起,方便地分离两种类型的Web内容:
- 静态内容 :网页中不变的部分,如在线商店中每个产品的描述。
- 动态内容 :由Servlet生成的部分,如商店中每个产品的价格和库存数据,这些数据会随着商品售罄而改变。

使用JSP,我们可以将网页的静态内容放在HTML文档中,并在其中调用Servlet。同时,还可以在页面中使用Java语言的其他部分,如表达式、if - then块和变量。支持Tomcat规范的Web服务器能够读取这些页面并执行其中的Java代码,就像编写一个Servlet来处理整个任务一样。实际上,JSP在底层还是使用Servlet来完成所有工作。

创建JSP页面的步骤如下:
- 使用文本编辑器或Web发布程序(如Microsoft FrontPage 2002或Macromedia Dreamweaver)创建页面,就像创建HTML文档一样。
- 保存页面时,使用.jsp文件扩展名,以表明这是一个JavaServer Page而不是HTML文档。
- 将页面发布到支持Tomcat的Web服务器上,就像发布HTML文档一样。

当用户首次请求JSP页面时,Web服务器会编译一个新的Servlet来呈现该页面。这会导致页面加载速度变慢,但后续请求将使用已编译的Servlet,不会再出现这种情况。这个过程可以用以下mermaid流程图表示:

graph TD;
    A[用户请求JSP页面] --> B[Web服务器编译新Servlet];
    B --> C[呈现页面,加载速度慢];
    C --> D[后续请求使用已编译Servlet,加载正常];
3. 编写JavaServer Page

一个JavaServer Page由三种元素组成,每种元素都有类似HTML的特殊标记:
- Scriptlets :页面加载时执行的Java语句,每个语句被 <% %> 标记包围。
- Expressions :被求值的Java表达式,其输出会显示在页面上,这些表达式被 <%= %> 标记包围。
- Declarations :用于创建实例变量和处理页面呈现所需的其他设置任务的语句,被 <%! %> 标记包围。

3.1 使用Expressions

以下是一个包含表达式的JSP页面示例( time.jsp ):

<html>
<head>
<title>Clock</title>
</head>
<body>
<h1 align="Center">
<%= new java.util.Date() %>
</h1>
</body>
</html>

操作步骤如下:
- 使用任何能保存为纯文本的文本编辑器输入上述代码。
- 保存文件后,将其上传到Web服务器上存储其他网页的文件夹中。与Java Servlets不同,JSP页面可以放在Web上可访问的任何文件夹中。
- 首次加载该页面的URL时,Web服务器会将JSP页面编译成Servlet,导致页面加载缓慢。但后续请求将使用已编译的Servlet,不会再出现这种情况。

在JSP页面的表达式和其他元素中,可以引用以下几个Servlet变量:
- application :用于与Web服务器通信的Servlet上下文。
- config :用于查看Servlet初始化方式的Servlet配置对象。
- out :Servlet输出流。
- request :HTTP Servlet请求。
- response :HTTP Servlet响应。
- session :当前的HTTP会话。

这些变量引用的对象与我们在Java Servlets中使用的对象相同,在JSP页面中可以调用与Servlet中相同的方法。

另一个示例 environment.jsp 展示了如何在页面中使用 request 变量:

<html>
<head>
<title>Environment Variables</title>
</head>
<body>
<ul>
<li>Accept: <%= request.getHeader("Accept") %>
<li>Accept-Encoding: <%= request.getHeader("Accept-Encoding") %>
<li>Connection: <%= request.getHeader("Connection") %>
<li>Content-Length: <%= request.getHeader("Content-Length") %>
<li>Content-Type: <%= request.getHeader("Content-Type") %>
<li>Cookie: <%= request.getHeader("Cookie") %>
<li>Host: <%= request.getHeader("Host") %>
<li>Referer: <%= request.getHeader("Referer") %>
<li>User-Agent: <%= request.getHeader("User-Agent") %>
</ul>
</body>
</html>

在这个页面的第7 - 15行,每行都包含一个对 getHeader() 方法的调用,用于检索不同的HTTP请求头。每个头的输出值取决于Web服务器和使用的Web浏览器。

3.2 使用Scriptlets

在JSP页面中,还可以使用Java语句,如调用方法、为变量赋值、创建条件语句等。这些语句以 <% 标记开始,以 %> 标记结束,多个语句可以包含在这些标记内。这些出现在JSP页面内的语句被称为Scriptlets,并且可以使用与表达式中相同的Servlet变量。

以下是一个名为 shopforbooks.jsp 的JSP页面示例,它显示了一个书籍列表,并提供了到在线书店中每本书页面的超链接:

<html>
<head>
<title>Shop for Books</title>
</head>
<body>
<h2 align="Left">Favorite Books</h2>
<%
String[] bookTitle = { "Catch-22", "Something Happened",
    "Good as Gold" };
String[] isbn = { "0684833395", "0684841215", "0684839741" };
String amazonLink = "http://www.amazon.com/exec/obidos/ASIN/";
String bnLink = "http://shop.bn.com/booksearch/isbnInquiry.asp?isbn=";

String store = request.getParameter("store");
if (store == null) {
    store = "Amazon";
}
for (int i = 0; i < bookTitle.length; i++) {
    if (store.equals("Amazon"))
        out.println("<li><a href=\"" + amazonLink + isbn[i] + "\">" +
            bookTitle[i] + "</a>");
    else
        out.println("<li><a href=\"" + bnLink + isbn[i] + "\">" +
            bookTitle[i] + "</a>");
}
%>
<p>Preferred Bookstore:
<form action="shopforbooks.jsp" method="POST">
<p><input type="radio" value="Amazon" <%= (store.equals("Amazon") ?  "checked" : "") %>
name="store"> Amazon.Com
<p><input type="radio" value="BN" <%= (store.equals("BN") ? " checked" : "") %>
name="store"> Barnes & Noble
<p><input type="submit" value="Change Store">
</form>
</body>
</html>

这个JSP页面底部包含一个表单,允许用户选择他们喜欢的在线书店。在第28行,表单提交到该JSP页面的URL。由于JSP页面实际上是Servlet,它们也可以接收通过POST或GET发送的表单数据。

需要注意的是,表单上的单选按钮会始终与用户选择的书店匹配,这是因为第29行和第31行的表达式。例如:

<%= (store.equals("Amazon") ? " checked" : "") %>

这个表达式使用三元运算符,根据 store.equals("Amazon") 的条件进行判断。如果条件为真,表达式的值为“checked”;否则,为一个空字符串。表达式的值会作为JSP页面的一部分显示出来。

3.3 使用Declarations

可以插入到JSP页面中的最后一种元素是声明,它是在页面编译成Servlet时定义变量或方法的语句。这个功能主要与表达式和Servlet结合使用。声明被 <%! %> 标记包围,例如:

<%! boolean noCookie = true %>
<%! String userName = "New user" %>

这些声明创建了两个实例变量 noCookie userName 。当JSP页面编译成Servlet时,这些变量将成为该类定义的一部分。

以下是一个使用声明来呈现计数器的JSP页面示例( counter.jsp ):

<%@ page import="counter.*" %>
<html>
<head>
<title>Counter Example</title>
</head>
<body>
<h1>JSP Stats</h1>
<%! Counter visits; %>
<%! int count; %>

<%
visits = new Counter(application.getRealPath("counter.dat"));
count = visits.getCount() + 1;
%>

<p>This page has been loaded <%= count %> times.

<% visits.setCount(count); %>
</body>
</html>

在尝试这个页面之前,需要创建一个辅助类 Counter ,它在页面的第8、12、13和18行的语句中被调用。以下是 Counter 类的代码:

package counter;

import java.io.*;
import java.util.*;

public class Counter {
    private int count;
    private String filepath;

    public Counter(String inFilepath) {
        count = 0;
        filepath = inFilepath;
    }

    public int getCount() {
        try {
            File countFile = new File(filepath);
            FileReader file = new FileReader(countFile);
            BufferedReader buff = new BufferedReader(file);
            String current = buff.readLine();
            count = Integer.parseInt(current);
            buff.close();
        } catch (IOException e) {
            // do nothing
        } catch (NumberFormatException nfe) {
            // do nothing
        }
        return count;
    }

    public void setCount(int newCount) {
        count = newCount;
        try {
            File countFile = new File(filepath);
            FileWriter file = new FileWriter(countFile);
            BufferedWriter buff = new BufferedWriter(file);
            String output = "" + newCount;
            buff.write(output, 0, output.length());
            buff.close();
        } catch (IOException e) {
            // do nothing
        }
    }
}

成功编译这个类后,将其存储在Web服务器上与之前创建的Java Servlets相同的文件夹中。尽管 Counter 类不是Servlet,但Tomcat会在该文件夹中查找JSP页面引用的类。

Counter 类从Web服务器上存储的 counter.dat 文件中加载一个整数值。 getCount() 方法检索计数器的当前值, setCount(int) 方法设置当前值。设置值后,它会保存到文件中,以便计数器继续递增。

4. 创建Web应用程序

通过结合Java类、Servlet和JavaServer Pages,我们可以创建交互式Web应用程序,这些应用程序能够以复杂且连贯的方式根据用户输入动态生成内容。例如,每次在像Amazon.com这样的电子商务网站购物,或者使用像Internet Movie Database(IMDB)这样的在线参考资料时,我们都在运行一个Web应用程序。

下面我们将创建一个名为Guestbook的Web应用程序,它允许访问者为网站创建者留下消息。Guestbook项目由以下三部分组成:
- guestbook.jsp :一个JavaServer Page,用于显示Web服务器上文本文件中的留言簿条目,并提供一个表单,让访问者可以添加新条目。
- guestbookpost.jsp :一个JavaServer Page,用于将新的留言簿条目保存到文本文件中。
- Guestbook.java :一个类,用于在将字符保存到留言簿之前过滤掉一些字符。

4.1 guestbook.jsp页面

以下是 guestbook.jsp 的源代码:

<%@ page import="java.util.*,java.io.*" %>
<html>
<head>
<title>Visitors Who Signed our Guestbook</title>
</head>
<body>
<h3>Visitors Who Signed our Guestbook</h3>
<%
String id = request.getParameter("id");
boolean noSignatures = true;
try {
    String filename = application.getRealPath(id + ".gbf");
    FileReader file = new FileReader(filename);
    BufferedReader buff = new BufferedReader(file);
    boolean eof = false;
    while (!eof) {
        String entry = buff.readLine();
        if (entry == null)
            eof = true;
        else {
            StringTokenizer entryData = new StringTokenizer(entry, "^");
            String name = (String) entryData.nextElement();
            String email = (String) entryData.nextElement();
            String url = (String) entryData.nextElement();
            String entryDate = (String) entryData.nextElement();
            String ip = (String) entryData.nextElement();
            String comments = (String) entryData.nextElement();
            out.print("<p>From: " + name);
            if (!email.equals("None"))
                out.println(" <" + email + "><br>");
            else
                out.println("<br>");
            if (!url.equals("None"))
                out.println("Home Page: <a href=\"" + url + "\">" + url + "</a><br>");
            out.println("Date: " + entryDate + "<br>");
            out.println("IP: " + ip);
            out.println("<blockquote>");
            out.println("<p>" + comments);
            out.println("</blockquote>");
            noSignatures = false;
        }
    }
    buff.close();
} catch (IOException e) {
    out.println("<p>This guestbook could not be read because of an error.");
    log("Guestbook Error: " + e.toString());
}
if (noSignatures)
    out.println("<p>No one has signed our guestbook yet.");
%>
<h3>Sign Our Guestbook</h3>
<form method="POST" action="guestbookpost.jsp">
  <table border="0" cellpadding="5" cellspacing="0" width="100%">
    <tr>
      <td width="15%" valign="top" align="right">Your Name:</td>
      <td width="50%"><input type="text" name="name" size="40"></td>
    </tr>
    <tr>
      <td width="15%" valign="top" align="right">Your E-mail Address:</td>
      <td width="50%"><input type="text" name="email" size="40"></td>
    </tr>
    <tr>
      <td width="15%" valign="top" align="right">Your Home Page:</td>
      <td width="50%"><input type="text" name="url" size="40"></td>
    </tr>
    <tr>
      <td width="15%" valign="top" align="right">Your Comments:</td>
      <td width="50%"><textarea rows="6" name="comments" cols="40"></textarea></td>
    </tr>
  </table>
  <p align="center"><input type="submit" value="Submit" name="B1">
  <input type="reset" value="Reset" name="Reset"></p>
<input type="hidden" name="id" value="<%= id %>">
</form>
</body>
</html>

保存此页面后,将其存储在配备Tomcat的Web服务器上任何可以存储页面的文件夹中。在项目的其他部分完成之前,只要有一个空的留言簿文件,就可以对其进行测试。创建留言簿文件的步骤如下:
1. 在系统上保存一个空的文本文件,并将其命名为 cinema.gbf
2. 将该文件存储在Web上与 guestbook.jsp 相同的文件夹中。

当加载这个JavaServer Page时,必须包含一个参数来指定要加载的留言簿的ID,例如URL: http://www.java21pro.com/guestbook.jsp?id=cinema 。服务器名称和文件夹取决于 guestbook.jsp 的发布位置。

留言簿文件将每个留言簿条目存储在单独的一行中,每个条目中的字段用脱字符( ^ )分隔。访问者可以提供他们的姓名、电子邮件地址、主页地址和评论。每个条目还会保存另外两项信息:留言的日期和时间,以及访问者的IP地址。以下是一个包含两个条目的留言簿文件示例:

John Smith^jsmith@prefect.com^http://www.tvguide.com^Thu Apr 25 01:19:27 EST 2002^65.80.105.19^Your Web site is great.
D. James^deejay@naviseek.com^http://www.imdb.com^ Thu Apr 25 01:19:53 EST 2002^165.40.10.18^Thanks for the information.
4.2 guestbookpost.jsp页面

以下是 guestbookpost.jsp 的源代码:

<%@ page import="java.util.*,java.io.*,guestbook.*" %>
<html>
<head>
<title>Thank You For Signing Our Guestbook</title>
</head>
<body>
<h3>Thank You For Signing Our Guestbook</h3>
<%
String id = request.getParameter("id");
String[] entryFields = { "name", "email", "url", "comments" };
String[] entry = new String[4];
for (int i = 0; i < entryFields.length; i++) {
    entry[i] = Guestbook.filterString(request.getParameter(entryFields[i]));
}
Date now = new Date();
String entryDate = now.toString();
String ip = request.getRemoteAddr();
%>

<p>Your entry looks like this:
<p>From: <%= entry[0] %><%= (!entry[1].equals("None") ? "<"+entry[1]+">" : "") %><br>
<% if (!entry[2].equals("None")) { %>
Home Page: <a href="<%= entry[2] %>"><%= entry[2] %></a><br>
<% } %>
Date: <%= entryDate %><br>
IP: <%= ip %>
<blockquote>
<p><%= entry[3] %>
</blockquote>

<%
try {
    boolean append = true;
    String filename = application.getRealPath(id + ".gbf");
    FileWriter fw = new FileWriter(filename, append);
    BufferedWriter fileOut = new BufferedWriter(fw);
    String newEntry = entry[0] + "^" + entry[1] + "^" + entry[2] + "^"
        + entryDate + "^" + ip + "^" + entry[3];
    fileOut.write(newEntry, 0, newEntry.length());
    fileOut.newLine();
    fileOut.close();
} catch (IOException e) {
    out.println("<p>This guestbook could not be updated because of an error.");
    log("Guestbook Error: " + e.toString());
}
%>

<p><a href="guestbook.jsp?id=<%= id %>">View the Guestbook</a>
</body>
</html>

guestbookpost.jsp JavaServer Page从Web表单收集数据,从数据中移除不能放入留言簿的字符,并将结果存储在文本文件中。每个留言簿都有自己的文件,文件名以留言簿的ID参数开头,以 .gbf 文件扩展名结尾。例如,如果留言簿的ID是 cinema ,则文件名是 cinema.gbf 。与该Web应用程序中的其他JavaServer Page一样, guestbookpost.jsp 可以存储在Web服务器上任何可以存储HTML文档的文件夹中。对于这个项目,将该页面存储在与 guestbook.jsp cinema.gbf 相同的文件夹中。

4.3 Guestbook.java类

在尝试Guestbook应用程序之前,必须创建一个Java类 Guestbook ,用于在将留言簿条目发布之前过滤掉一些不需要的文本。由于条目在文件中的存储方式,留言簿中不能包含以下三个字符:
- 脱字符( ^
- 回车字符(在Java中整数值为13)
- 换行字符(在Java中整数值为10)

以下是 Guestbook.java 的源代码:

package guestbook;

public class Guestbook {
    public static String filterString(String input) {
        input = replaceText(input, '^', ' ');
        input = replaceText(input, (char)13, ' ');
        input = replaceText(input, (char)10, ' ');
        return input;
    }

    private static String replaceText(String inString, char oldChar,
        char newChar) {

        while (inString.indexOf(oldChar) != -1) {
            int oldPosition = inString.indexOf(oldChar);
            StringBuffer data = new StringBuffer(inString);
            data.setCharAt(oldPosition, newChar);
            inString = data.toString();
        }
        return inString;
    }
}

这个类有一个静态方法 filterString(String) ,用于从字符串中移除上述三个字符。

整个Guestbook应用程序的运行流程可以用以下mermaid流程图表示:

graph LR;
    A[用户访问guestbook.jsp] --> B[显示留言簿条目和表单];
    B --> C{用户提交表单};
    C -->|是| D[guestbookpost.jsp收集数据];
    D --> E[Guestbook.java过滤数据];
    E --> F[数据保存到.gbf文件];
    F --> G[显示新条目并提供查看留言簿链接];
    C -->|否| B;

通过以上步骤,我们成功创建了一个完整的Web应用程序Guestbook,展示了Java类、Servlet和JavaServer Pages如何协同工作,以实现动态网页内容的生成和管理。在实际开发中,可以根据需求对这些技术进行进一步扩展和优化,以创建更复杂、更强大的Web应用程序。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值