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应用程序。
超级会员免费看
973

被折叠的 条评论
为什么被折叠?



