JSP – 从入门到精通

JSP – 概述

什么是 JavaServer Pages?

JavaServer Pages (JSP) 是一种用于开发支持动态内容的网页的技术。这有助于开发人员通过使用特殊的 JSP 标记在 HTML 页面中插入 java 代码,其中大多数标记以 <% 开头并以 %> 结尾。

JavaServer Pages 组件是一种 Java servlet,旨在充当 Java Web 应用程序的用户界面。Web 开发人员将 JSP 编写为结合了 HTML 或 XHTML 代码、XML 元素以及嵌入式 JSP 操作和命令的文本文件。

使用 JSP,您可以通过网页表单收集用户的输入,显示来自数据库或其他来源的记录,并动态创建网页。

JSP 标记可用于多种目的,例如从数据库中检索信息或注册用户首选项、访问 JavaBeans 组件、在页面之间传递控制以及在请求、页面之间共享信息等。

为什么使用 JSP?

JavaServer Pages 通常与使用通用网关接口 (CGI)实现的程序具有相同的目的。但是与 CGI 相比,JSP 提供了几个优势。

  • 性能明显更好,因为 JSP 允许在 HTML 页面本身中嵌入动态元素,而不是使用单独的 CGI 文件。
  • 与 CGI/Perl 不同,JSP 总是在被服务器处理之前进行编译,CGI/Perl 每次请求页面时都需要服务器加载解释器和目标脚本。
  • JavaServer Pages 建立在 Java Servlets API 之上,因此与 Servlets 一样,JSP 也可以访问所有强大的企业 Java API,包括JDBC、JNDI、EJB、JAXP等。
  • JSP 页面可以与处理业务逻辑的 servlet 结合使用,这是 Java servlet 模板引擎支持的模型。

最后,JSP 是 Java EE 不可或缺的一部分,Java EE 是企业级应用程序的完整平台。这意味着 JSP 可以在最简单的应用程序到最复杂和要求最高的应用程序中发挥作用。

JSP的优点

下表列出了使用 JSP 相对于其他技术的其他优势 –

与活动服务器页面 (ASP)

JSP 的优点是双重的。首先,动态部分是用 Java 编写的,而不是 Visual Basic 或其他 MS 特定语言,因此它更强大且更易于使用。其次,它可以移植到其他操作系统和非 Microsoft Web 服务器。

与纯 Servlet

编写(和修改!)常规 HTML 比使用大量生成 HTML 的 println 语句更方便。

与服务器端包含 (SSI)

SSI 实际上仅用于简单的包含,而不用于使用表单数据、建立数据库连接等的“真实”程序。

与 JavaScript

JavaScript 可以在客户端动态生成 HTML,但很难与 Web 服务器交互以执行复杂的任务,如数据库访问和图像处理等。

与静态 HTML

当然,常规 HTML 不能包含动态信息。

接下来是什么?

我将带您一步一步地设置您的环境以开始使用 JSP。我假设您有良好的 Java 编程实践经验,可以继续学习 JSP。

如果您不了解 Java 编程语言,那么我们建议您阅读我们的Java 教程以了解 Java 编程。

JSP – 环境设置

开发环境是您开发 JSP 程序、测试它们并最终运行它们的地方。

本教程将指导您设置 JSP 开发环境,包括以下步骤 –

设置 Java 开发工具包

此步骤涉及下载 Java 软件开发工具包 (SDK) 的实现并适当地设置 PATH 环境变量。

您可以从 Oracle 的 Java 站点 – Java SE 下载下载 SDK 。

下载 Java 实现后,请按照给定的说明安装和配置设置。最后设置PATH 和 JAVA_HOME环境变量以引用包含javajavac的目录,通常分别是java_install_dir/binjava_install_dir

如果您运行的是 Windows 并将 SDK 安装在C:\jdk1.5.0_20中,则需要在C:\autoexec.bat文件中添加以下行。

set PATH = C:\jdk1.5.0_20\bin;%PATH%
set JAVA_HOME = C:\jdk1.5.0_20

或者,在Windows NT/2000/XP上,您也可以右键单击“我的电脑”,选择“属性”,然后选择“高级”,然后选择“环境变量” 。然后,您将更新 PATH 值并按下 OK 按钮。

在 Unix(Solaris、Linux 等)上,如果 SDK 安装在/usr/local/jdk1.5.0_20中并且您使用 C shell,则需要将以下内容放入.cshrc文件中。

setenv PATH /usr/local/jdk1.5.0_20/bin:$PATH
setenv JAVA_HOME /usr/local/jdk1.5.0_20

或者,如果您使用Borland JBuilder、Eclipse、IntelliJ IDEASun ONE Studio集成开发环境 (IDE),请编译并运行一个简单的程序以确认 IDE 知道您安装 Java 的位置。

设置网络服务器:Tomcat

市场上有许多支持 JavaServer Pages 和 Servlets 开发的 Web 服务器。一些网络服务器可以免费下载,Tomcat 就是其中之一。

Apache Tomcat 是 JavaServer Pages 和 Servlet 技术的开源软件实现,可以作为测试 JSP 和 Servlet 的独立服务器,也可以与 Apache Web Server 集成。以下是在您的机器上设置 Tomcat 的步骤 –

  • 从https://tomcat.apache.org/下载最新版本的 Tomcat 。
  • 下载安装后,将二进制分发包解压到一个方便的位置。例如,在Windows 上的C:\apache-tomcat-5.5.29 或Linux/Unix 上的 /usr/local/apache-tomcat-5.5.29 中,并创建指向这些位置的CATALINA_HOME环境变量。

可以通过在 Windows 机器上执行以下命令来启动 Tomcat –

%CATALINA_HOME%\bin\startup.bat
 
or
 
C:\apache-tomcat-5.5.29\bin\startup.bat

可以通过在 Unix(Solaris、Linux 等)机器上执行以下命令来启动 Tomcat –

$CATALINA_HOME/bin/startup.sh
 
or
 
/usr/local/apache-tomcat-5.5.29/bin/startup.sh

成功启动后,可以通过访问http://localhost:8080/访问 Tomcat 中包含的默认 Web 应用程序。

执行后,您将收到以下输出 –

有关配置和运行 Tomcat 的更多信息,请参见此处包含的文档以及 Tomcat 网站 – https://tomcat.apache.org/

可以通过在 Windows 机器上执行以下命令来停止 Tomcat –

%CATALINA_HOME%\bin\shutdown
or

C:\apache-tomcat-5.5.29\bin\shutdown

可以通过在 Unix(Solaris、Linux 等)机器上执行以下命令来停止 Tomcat –

$CATALINA_HOME/bin/shutdown.sh

or

/usr/local/apache-tomcat-5.5.29/bin/shutdown.sh

设置类路径

由于 servlet 不是 Java Platform, Standard Edition 的一部分,您必须向编译器标识 servlet 类。

如果您运行的是 Windows,则需要将以下行放入C:\autoexec.bat文件中。

set CATALINA = C:\apache-tomcat-5.5.29
set CLASSPATH = %CATALINA%\common\lib\jsp-api.jar;%CLASSPATH%

或者,在Windows NT/2000/XP上,您也可以右键单击我的电脑,选择属性,然后选择高级,然后选择环境变量。然后,您将更新 CLASSPATH 值并按下 OK 按钮。

在 Unix(Solaris、Linux 等)上,如果您使用的是 C shell,则应将以下行放入.cshrc文件中。

setenv CATALINA = /usr/local/apache-tomcat-5.5.29
setenv CLASSPATH $CATALINA/common/lib/jsp-api.jar:$CLASSPATH

注意– 假设您的开发目录是C:\JSPDev (Windows)/usr/JSPDev (Unix),那么您还需要在 CLASSPATH 中添加这些目录。

JSP-架构

Web服务器需要一个JSP引擎,即一个容器来处理JSP页面。JSP 容器负责拦截对 JSP 页面的请求。本教程利用 Apache 内置的 JSP 容器来支持 JSP 页面开发。

JSP 容器与 Web 服务器一起工作,以提供 JSP 需要的运行时环境和其他服务。它知道如何理解作为 JSP 一部分的特殊元素。

下图显示了 JSP 容器和 JSP 文件在 Web 应用程序中的位置。

JSP处理

以下步骤解释了 Web 服务器如何使用 JSP 创建网页 –

  • 与普通页面一样,您的浏览器向 Web 服务器发送 HTTP 请求。
  • Web 服务器识别出 HTTP 请求是针对 JSP 页面的,并将其转发给 JSP 引擎。这是通过使用以.jsp而不是.html结尾的 URL 或 JSP 页面来完成的。
  • JSP 引擎从磁盘加载 JSP 页面并将其转换为 servlet 内容。这种转换非常简单,其中所有模板文本都转换为 println() 语句,所有 JSP 元素都转换为 Java 代码。这段代码实现了页面相应的动态行为。
  • JSP 引擎将 servlet 编译成可执行类,并将原始请求转发给 servlet 引擎。
  • 称为 servlet 引擎的 Web 服务器的一部分加载 Servlet 类并执行它。在执行期间,servlet 生成 HTML 格式的输出。输出由 HTTP 响应中的 servlet 引擎进一步传递到 Web 服务器。
  • Web 服务器以静态 HTML 内容的形式将 HTTP 响应转发给您的浏览器。
  • 最后,Web 浏览器处理 HTTP 响应中动态生成的 HTML 页面就像处理静态页面一样。

所有上述步骤都可以在下图中看到 –

通常,JSP 引擎会检查 JSP 文件的 servlet 是否已经存在,以及 JSP 上的修改日期是否早于 servlet。如果 JSP 比其生成的 servlet 旧,则 JSP 容器假定 JSP 没有更改并且生成的 servlet 仍然与 JSP 的内容匹配。这使得该过程比其他脚本语言(如 PHP)更高效,因此速度更快。

因此,在某种程度上,JSP 页面实际上只是编写 servlet 的另一种方式,无需成为 Java 编程专家。除了转换阶段,JSP 页面的处理方式与常规 servlet 完全相同。

JSP——生命周期

在本章中,我们将讨论 JSP 的生命周期。了解 JSP 低级功能的关键是了解它们遵循的简单生命周期。

JSP 生命周期定义为从创建到销毁的过程。这类似于一个 servlet 生命周期,带有将 JSP 编译成 servlet 所需的额外步骤。

JSP遵循的路径

以下是 JSP 遵循的路径 –

  • 汇编
  • 初始化
  • 执行
  • 清理

JSP 生命周期的四个主要阶段与 Servlet 生命周期非常相似。下面描述了四个阶段 –

JSP 编译

当浏览器请求 JSP 时,JSP 引擎首先检查是否需要编译页面。如果该页面从未被编译过,或者如果 JSP 自上次编译后已被修改,则 JSP 引擎会编译该页面。

编译过程包括三个步骤 –

  • 解析 JSP。
  • 将 JSP 转换为 servlet。
  • 编译 servlet。

JSP 初始化

当容器加载 JSP 时,它会在服务任何请求之前调用jspInit()方法。如果您需要执行特定于 JSP 的初始化,请覆盖jspInit()方法 –

public void jspInit(){
   // Initialization code...
}

通常,初始化只执行一次,与 servlet init 方法一样,您通常在 jspInit 方法中初始化数据库连接、打开文件和创建查找表。

JSP执行

JSP 生命周期的这个阶段表示在 JSP 被销毁之前与请求的所有交互。

每当浏览器请求 JSP 并且页面已加载和初始化时,JSP 引擎就会调用 JSP 中的_jspService()方法。

_jspService() 方法采用HttpServletRequestHttpServletResponse作为其参数,如下所示 –

void _jspService(HttpServletRequest request, HttpServletResponse response) {
   // Service handling code...
}

JSP的_jspService()方法是根据请求调用的。它负责为该请求生成响应,并且该方法还负责生成对所有七种 HTTP 方法(即GET、POST、DELETE等)的响应。

JSP 清理

JSP 生命周期的销毁阶段表示 JSP 何时不再被容器使用。

jspDestroy ()方法在 JSP 中相当于 servlet 的 destroy 方法。当您需要执行任何清理时覆盖 jspDestroy,例如释放数据库连接或关闭打开的文件。

jspDestroy() 方法具有以下形式 –

public void jspDestroy() {
   // Your cleanup code goes here.
}

JSP-语法

在本章中,我们将讨论 JSP 中的语法。我们将了解 JSP 开发中涉及的简单语法(即元素)的基本用法。

JSP 的元素

JSP 的元素描述如下 –

剧本

Scriptlet 可以包含任意数量的 JAVA 语言语句、变量或方法声明,或者在页面脚本语言中有效的表达式。

以下是 Scriptlet 的语法 –

<% code fragment %>

您可以编写与上述语法等效的 XML,如下所示 –

<jsp:scriptlet>
   code fragment
</jsp:scriptlet>

您编写的任何文本、HTML 标记或 JSP 元素都必须在 scriptlet 之外。以下是 JSP 的第一个简单示例 –

<html>
   <head><title>Hello World</title></head>
   
   <body>
      Hello World!<br/>
      <%
         out.println("Your IP address is " + request.getRemoteAddr());
      %>
   </body>
</html>

注意– 假设 Apache Tomcat 安装在 C:\apache-tomcat-7.0.2 中,并且您的环境是按照环境设置教程设置的。

让我们将上述代码保存在JSP 文件hello.jsp中,并将此文件放在C:\apache-tomcat7.0.2\webapps\ROOT目录下。使用 URL http://localhost:8080/hello.jsp浏览相同的内容。上面的代码将生成以下结果 –

JSP 声明

声明声明一个或多个变量或方法,您稍后可以在 JSP 文件中的 Java 代码中使用这些变量或方法。在 JSP 文件中使用变量或方法之前,必须对其进行声明。

以下是 JSP 声明的语法 –

<%! declaration; [ declaration; ]+ ... %>

您可以编写与上述语法等效的 XML,如下所示 –

<jsp:declaration>
   code fragment
</jsp:declaration>

以下是 JSP 声明的示例 –

<%! int i = 0; %> 
<%! int a, b, c; %> 
<%! Circle a = new Circle(2.0); %> 

JSP 表达式

JSP 表达式元素包含一个脚本语言表达式,该表达式经过计算、转换为字符串并插入到表达式在 JSP 文件中出现的位置。

因为表达式的值被转换为字符串,所以您可以在 JSP 文件中的一行文本中使用表达式,无论它是否用 HTML 标记。

expression 元素可以包含根据 Java 语言规范有效的任何表达式,但不能使用分号来结束表达式。

以下是 JSP 表达式的语法 –

<%= expression %>

您可以编写与上述语法等效的 XML,如下所示 –

<jsp:expression>
   expression
</jsp:expression>

以下示例显示了一个 JSP 表达式 –

<html> 
   <head><title>A Comment Test</title></head> 
   
   <body>
      <p>Today's date: <%= (new java.util.Date()).toLocaleString()%></p>
   </body> 
</html> 

上面的代码将生成以下结果 –

Today's date: 11-Sep-2010 21:24:25

JSP 注释

JSP 注释标记 JSP 容器应忽略的文本或语句。当您想隐藏或“注释掉”JSP 页面的一部分时,JSP 注释很有用。

以下是 JSP 注释的语法 –

<%-- This is JSP comment --%>

以下示例显示了 JSP 注释 –

<html> 
   <head><title>A Comment Test</title></head> 
   
   <body> 
      <h2>A Test of Comments</h2> 
      <%-- This comment will not be visible in the page source --%> 
   </body> 
</html> 

上面的代码将生成以下结果 –

A Test of Comments  

在各种情况下,您可以使用少量特殊结构来插入本来会被特殊处理的注释或字符。这是一个总结 –

编号语法和目的
1<%–注释–%>JSP 注释。被 JSP 引擎忽略。
2<!– 注释 –>HTML 注释。被浏览器忽略。
3<\%表示静态 <% 文字。
4%\>表示静态 %> 文字。
5\’使用单引号的属性中的单引号。
6\”使用双引号的属性中的双引号。

JSP 指令

JSP 指令会影响 servlet 类的整体结构。它通常具有以下形式 –

<%@ directive attribute="value" %>

指令标签分为三种类型 –

编号指令和说明
1<%@ page … %>定义与页面相关的属性,例如脚本语言、错误页面和缓冲要求。
2<%@ include … %>在翻译阶段包括一个文件。
3<%@ taglib … %>声明一个标签库,包含页面中使用的自定义操作

我们将在单独的章节JSP – 指令中解释 JSP 指令

JSP 动作

JSP 动作使用XML 语法结构来控制 servlet 引擎的行为。您可以动态插入文件、重用 JavaBeans 组件、将用户转到另一个页面或为 Java 插件生成 HTML。

Action 元素只有一种语法,因为它符合 XML 标准 –

<jsp:action_name attribute="value" />

动作元素基本上是预定义的功能。下表列出了可用的 JSP 操作 –

编号语法和目的
1jsp:include 在请求页面时包括一个文件。
2jsp:useBean 查找或实例化 JavaBean。
3jsp:setProperty 设置 JavaBean 的属性。
4jsp:getProperty 将 JavaBean 的属性插入到输出中。
5jsp:forward 将请求者转发到新页面。
6jsp:plugin 生成特定于浏览器的代码,为 Java 插件创建 OBJECT 或 EMBED 标记。
7jsp:element 动态定义 XML 元素。
8jsp:attribute 定义动态定义的 XML 元素的属性。
9jsp:body 定义动态定义的 XML 元素的主体。
10jsp:text 用于在 JSP 页面和文档中编写模板文本。

我们将在单独的一章JSP – 动作中解释 JSP 动作

JSP 隐式对象

JSP 支持九个自动定义的变量,也称为隐式对象。这些变量是 –

编号对象和描述
1个request
这是与请求关联的HttpServletRequest对象。
2个response
这是与对客户端的响应关联的HttpServletResponse对象。
3个out
这是用于将输出发送到客户端的PrintWriter对象。
4个session
这是与请求关联的HttpSession对象。
5个application
这是与应用程序上下文关联的ServletContext对象。
6个config
这是与页面关联的ServletConfig对象。
7pageContext
这封装了特定于服务器的功能的使用,例如更高性能的JspWriters
8个page
这只是this的同义词,用于调用翻译后的 servlet 类定义的方法。
9Exception
Exception对象允许指定的JSP 访问异常数据。

我们将在单独的一章JSP – 隐式对象中解释 JSP 隐式对象。

控制流语句

您可以在 JSP 编程中使用 Java 的所有 API 和构建块,包括决策语句、循环等。

决策声明

if…else块开始时与普通的 Scriptlet类似,但 Scriptlet 在每一行结束时在 Scriptlet 标记之间包含 HTML 文本。

<%! int day = 3; %> 
<html> 
   <head><title>IF...ELSE Example</title></head> 
   
   <body>
      <% if (day == 1 || day == 7) { %>
         <p> Today is weekend</p>
      <% } else { %>
         <p> Today is not weekend</p>
      <% } %>
   </body> 
</html> 

上面的代码将生成以下结果 –

Today is not weekend

现在看看下面的switch…case块,它使用out.println()和内部 Scriptletas编写得有点不同-

<%! int day = 3; %> 
<html> 
   <head><title>SWITCH...CASE Example</title></head> 
   
   <body>
      <% 
         switch(day) {
            case 0:
               out.println("It\'s Sunday.");
               break;
            case 1:
               out.println("It\'s Monday.");
               break;
            case 2:
               out.println("It\'s Tuesday.");
               break;
            case 3:
               out.println("It\'s Wednesday.");
               break;
            case 4:
               out.println("It\'s Thursday.");
               break;
            case 5:
               out.println("It\'s Friday.");
               break;
            default:
               out.println("It's Saturday.");
         }
      %>
   </body> 
</html> 

上面的代码将生成以下结果 –

It's Wednesday.

循环语句

您还可以在 Java 中使用三种基本类型的循环块:for、while 和 do…while在 JSP 编程中的块。

让我们看看下面的 for循环示例 –

<%! int fontSize; %> 
<html> 
   <head><title>FOR LOOP Example</title></head> 
   
   <body>
      <%for ( fontSize = 1; fontSize <= 3; fontSize++){ %>
         <font color = "green" size = "<%= fontSize %>">
            JSP Tutorial
      </font><br />
      <%}%>
   </body> 
</html> 

上面的代码将生成以下结果 –

   JSP Tutorial

JSP Tutorial
JSP Tutorial

上面的例子可以使用while循环编写如下 –

<%! int fontSize; %> 
<html> 
   <head><title>WHILE LOOP Example</title></head> 
   
   <body>
      <%while ( fontSize <= 3){ %>
         <font color = "green" size = "<%= fontSize %>">
            JSP Tutorial
         </font><br />
         <%fontSize++;%>
      <%}%>
   </body> 
</html> 

上面的代码将生成以下结果 –

   JSP Tutorial



   JSP Tutorial



   JSP Tutorial

JSP 运算符

JSP 支持 Java 支持的所有逻辑和算术运算符。下表列出了所有具有最高优先级的运算符出现在表的顶部,具有最低优先级的运算符出现在底部。

在表达式中,将首先评估优先级较高的运算符。

类别运算符结合性
后缀() [] .(点运算符)左到右
一元++ – – !~右到左
乘法* / %左到右
添加剂+ –左到右
转移>> >>> <<左到右
关系型> >= < <=左到右
平等== !=左到右
按位与&左到右
按位异或^左到右
按位或|左到右
逻辑与&&左到右
逻辑或||左到右
有条件的?:右到左
任务= += -= *= /= %= >>= <<= &= ^= |=右到左
逗号,左到右

JSP 常量

JSP 表达式语言定义了以下常量 –

  • Boolean– 真假
  • Integer– 与 Java 一样
  • 浮点数– 与 Java 一样
  • 字符串– 带单引号和双引号;” 转义为 \”,’ 转义为 \’,\ 转义为 \\。
  • Null– 空

JSP – 指令

在本章中,我们将讨论 JSP 中的指令。这些指令向容器提供方向和指示,告诉它如何处理 JSP 处理的某些方面。

JSP 指令会影响 servlet 类的整体结构。它通常具有以下形式 –

<%@ directive attribute = "value" %>

指令可以有许多属性,您可以将它们列为键值对并用逗号分隔。

@ 符号和指令名称之间以及最后一个属性和结束 %> 之间的空格是可选的。

指令标签分为三种类型 –

编号指令和说明
1<%@ page … %>
定义与页面相关的属性,例如脚本语言、错误页面和缓冲要求。
2<%@ include … %>
在翻译阶段包括一个文件。
3<%@ taglib … %>
声明一个标签库,包含页面中使用的自定义操作

JSP – 页面指令

page 指​​令用于向容器提供指令。这些说明适用于当前的 JSP 页面。您可以在 JSP 页面中的任何位置对页面指令进行编码。按照惯例,页面指令编码在 JSP 页面的顶部。

以下是页面指令的基本语法 –

<%@ page attribute = "value" %>

您可以编写与上述语法等效的 XML,如下所示 –

<jsp:directive.page attribute = "value" />

属性

下表列出了与页面指令相关的属性 –

编号属性和目的
1个buffer
指定输出流的缓冲模型。
2个autoFlush
控制 servlet 输出缓冲区的行为。
3个contentType
定义字符编码方案。
4个errorPage
定义另一个报告 Java 未经检查的运行时异常的 JSP 的 URL。
5个isErrorPage
指示此 JSP 页面是否是由另一个 JSP 页面的 errorPage 属性指定的 URL。
6个extends
指定生成的 servlet 必须扩展的超类。
7import
指定要在 JSP 中使用的包或类的列表,就像 Java import 语句对 Java 类所做的那样。
8个info
定义可以使用 servlet 的getServletInfo()方法访问的字符串。
9isThreadSafe
为生成的 servlet 定义线程模型。
10language
定义 JSP 页面中使用的编程语言。
11session
指定 JSP 页面是否参与 HTTP 会话
12isELIgnored
指定是否忽略 JSP 页面中的 EL 表达式。
13isScriptingEnabled
确定是否允许使用脚本元素。

在页面指令中查看与上述所有属性相关的更多详细信息。

包含指令

include指令用于在翻译阶段包含文件。该指令告诉容器在翻译阶段将其他外部文件的内容与当前 JSP 合并。您可以在 JSP 页面的任何位置编写include指令。

该指令的一般用法形式如下 –

<%@ include file = "relative url" >

include 指令中的文件名实际上是一个相对 URL。如果您只指定一个没有关联路径的文件名,JSP 编译器会假定该文件与您的 JSP 位于同一目录中。

您可以编写与上述语法等效的 XML,如下所示 –

<jsp:directive.include file = "relative url" />

有关包含指令的更多详细信息,请查看包含指令。

taglib 指令

JavaServer Pages API 允许您定义看起来像 HTML 或 XML 标记的自定义 JSP 标记,标记库是一组实现自定义行为的用户定义标记。

taglib指令声明您的 JSP 页面使用一组自定义标记,标识库的位置,并提供识别 JSP 页面中自定义标记的方法。

taglib 指令遵循下面给出的语法 –

<%@ taglib uri="uri" prefix = "prefixOfTag" >

在这里,uri属性值解析为容器理解的位置,prefix属性通知容器哪些标记是自定义操作。

您可以编写与上述语法等效的 XML,如下所示 –

<jsp:directive.taglib uri = "uri" prefix = "prefixOfTag" />

有关 taglib 指令的更多详细信息,请查看Taglib 指令。

JSP-动作

在本章中,我们将讨论 JSP 中的 Actions。这些操作使用 XML 语法结构来控制 servlet 引擎的行为。您可以动态插入文件、重用 JavaBeans 组件、将用户转到另一个页面或为 Java 插件生成 HTML。

Action 元素只有一种语法,因为它符合 XML 标准 –

<jsp:action_name attribute = "value" />

动作元素基本上是预定义的功能。下表列出了可用的 JSP 操作 –

编号语法和目的
1个jsp:include
在请求页面时包括一个文件。
2个jsp:useBean
查找或实例化 JavaBean。
3个jsp:setProperty
设置 JavaBean 的属性。
4个jsp:getProperty
将 JavaBean 的属性插入到输出中。
5个jsp:forward
将请求者转发到新页面。
6个jsp:plugin
生成特定于浏览器的代码,为 Java 插件创建 OBJECT 或 EMBED 标记。
7jsp:element
动态定义 XML 元素。
8个jsp:attribute
定义动态定义的 XML 元素的属性。
9jsp:body
定义动态定义的 XML 元素的主体。
10jsp:text
用于在 JSP 页面和文档中编写模板文本。

共同属性

所有 Action 元素共有两个属性:id属性和scope属性。

标识属性

id 属性唯一标识 Action 元素,并允许在 JSP 页面内引用该操作。如果 Action 创建了对象的实例,则可以使用 id 值通过隐式对象 PageContext 引用它。

范围属性

此属性标识 Action 元素的生命周期。id 属性和 scope 属性直接相关,因为 scope 属性决定了与 id 关联的对象的生命周期。scope 属性有四个可能的值:(a) page、(b)request、(c)session(d) application

<jsp:include> 动作

此操作允许您将文件插入到正在生成的页面中。语法看起来像这样 –

<jsp:include page = "relative URL" flush = "true" />

与在将 JSP 页面转换为 servlet 时插入文件的include指令不同,此操​​作在请求页面时插入文件。

下表列出了与包含操作相关的属性 –

编号属性和描述
1个page
要包含的页面的相对 URL。
2个flush
布尔属性确定包含的资源在包含之前是否刷新了缓冲区。

例子

让我们定义以下两个文件(a)date.jsp(b) main.jsp如下 –

以下是date.jsp文件的内容 –

<p>Today's date: <%= (new java.util.Date()).toLocaleString()%></p>

以下是main.jsp文件的内容 –

<html>
   <head>
      <title>The include Action Example</title>
   </head>
   
   <body>
      <center>
         <h2>The include action Example</h2>
         <jsp:include page = "date.jsp" flush = "true" />
      </center>
   </body>
</html>

现在让我们将所有这些文件保存在根目录中并尝试访问main.jsp。您将收到以下输出 –

The include action Example
   Today's date: 12-Sep-2010 14:54:22

<jsp:useBean> 动作

useBean操作非常通用。它首先使用 id 和 scope 变量搜索现有对象。如果未找到对象,则它会尝试创建指定的对象。

加载 bean 的最简单方法如下 –

<jsp:useBean id = "name" class = "package.class" />

加载 bean 类后,您可以使用jsp:setPropertyjsp:getProperty操作来修改和检索 bean 属性。

下表列出了与 useBean 操作相关的属性 –

编号属性和描述
1个class
指定 bean 的完整包名。
2个type
指定将引用对象的变量的类型。
3个beanName
给出由 java.beans.Beans 类的 instantiate () 方法指定的 bean 名称。

在给出与这些操作相关的有效示例之前,让我们现在讨论jsp:setPropertyjsp:getProperty操作。

<jsp:setProperty> 动作

setProperty操作设置 Bean的属性。必须在此操作之前预先定义 Bean。有两种使用 setProperty 操作的基本方法 –

您可以在之后使用jsp:setProperty,但在jsp:useBean元素之外,如下所示 –

<jsp:useBean id = "myName" ... />
...
<jsp:setProperty name = "myName" property = "someProperty" .../>

在这种情况下,无论是实例化了新 bean 还是找到了现有 bean,都会执行jsp:setProperty 。

jsp:setProperty 可以出现的第二个上下文是在jsp:useBean元素的主体内,如下所示 –

<jsp:useBean id = "myName" ... >
   ...
   <jsp:setProperty name = "myName" property = "someProperty" .../>
</jsp:useBean>

在这里,jsp:setProperty 仅在实例化新对象时执行,而不是在找到现有对象时执行。

下表列出了与setProperty操作相关的属性 –

编号属性和描述
1个name
指定将设置其属性的 bean。Bean 之前必须已经定义。
2个property
指示您要设置的属性。“*”值表示名称与 bean 属性名称匹配的所有请求参数都将传递给适当的 setter 方法。
3个value
要分配给给定属性的值。参数值为空,或参数不存在,setProperty 动作被忽略。
4个param
param 属性是属性要接收其值的请求参数的名称。您不能同时使用 value 和 param,但允许两者都不使用。

<jsp:getProperty> 操作

getProperty操作用于检索给定属性的值并将其转换为字符串,最后将其插入到输出中。

getProperty 操作只有两个属性,这两个属性都是必需的。getProperty 操作的语法如下 –

<jsp:useBean id = "myName" ... />
...
<jsp:getProperty name = "myName" property = "someProperty" .../>

下表列出了与getProperty操作相关的必需属性 –

编号属性和描述
1个name
具有要检索的属性的 Bean 的名称。Bean 之前必须已经定义。
2个property
property 属性是要检索的 Bean 属性的名称。

例子

让我们定义一个将在我们的示例中进一步使用的测试 bean –

/* File: TestBean.java */
package action;
 
public class TestBean {
   private String message = "No message specified";
 
   public String getMessage() {
      return(message);
   }
   public void setMessage(String message) {
      this.message = message;
   }
}

将上面的代码编译到生成的TestBean.class文件中,确保你复制了C:\apache-tomcat-7.0.2\webapps\WEB-INF\classes\action文件夹中的 TestBean.class 并且CLASSPATH变量也应该是设置到这个文件夹 –

现在在main.jsp文件中使用以下代码。这将加载 bean 并设置/获取一个简单的字符串参数 –

<html>
   
   <head>
      <title>Using JavaBeans in JSP</title>
   </head>
   
   <body>
      <center>
         <h2>Using JavaBeans in JSP</h2>
         <jsp:useBean id = "test" class = "action.TestBean" />
         <jsp:setProperty name = "test"  property = "message" 
            value = "Hello JSP..." />
            
         <p>Got message....</p>
         <jsp:getProperty name = "test" property = "message" />
      </center>
   </body>
</html>

现在让我们尝试访问main.jsp,它会显示以下结果 –

Using JavaBeans in JSP
Got message....
Hello JSP...

<jsp:forward> 动作

转发动作终止当前页面的动作,并将请求转发到另一个资源,如静态页面、另一个 JSP 页面或 Java Servlet。

以下是转发操作的语法 –

<jsp:forward page = "Relative URL" />

下表列出了与转发操作相关的必需属性 –

编号属性和描述
1个page
应该包含另一个资源的相对 URL,例如静态页面、另一个 JSP 页面或 Java Servlet。

例子

让我们重用以下两个文件(a) date.jsp(b) main.jsp如下 –

以下是date.jsp文件的内容 –

<p>Today's date: <%= (new java.util.Date()).toLocaleString()%></p>

以下是main.jsp文件的内容 –

<html>
   <head>
      <title>The include Action Example</title>
   </head>
   
   <body>
      <center>
         <h2>The include action Example</h2>
         <jsp:forward page = "date.jsp" />
      </center>
   </body>
</html>

现在让我们将所有这些文件保存在根目录中并尝试访问main.jsp。这将显示如下所示的结果。

这里它丢弃了主页面的内容,只显示转发页面的内容。

   Today's date: 12-Sep-2010 14:54:22

<jsp:plugin> 动作

插件操作用于将Java 组件插入到 JSP 页面中。它确定浏览器的类型并根据需要插入<object><embed>标记。

如果所需的插件不存在,它会下载插件,然后执行 Java 组件。Java 组件可以是 Applet 或 JavaBean。

插件操作有几个属性对应于用于格式化 Java 组件的常见 HTML 标记。< param>元素也可用于向 Applet 或 Bean 发送参数。

以下是使用插件操作的典型语法 –

<jsp:plugin type = "applet" codebase = "dirname" code = "MyApplet.class"
   width = "60" height = "80">
   <jsp:param name = "fontcolor" value = "red" />
   <jsp:param name = "background" value = "black" />
 
   <jsp:fallback>
      Unable to initialize Java Plugin
   </jsp:fallback>
 
</jsp:plugin>

如果您有兴趣,可以使用一些小程序尝试此操作。新元素<fallback>元素可用于指定在组件失败时发送给用户的错误字符串。

The <jsp:element> Action
The <jsp:attribute> Action
The <jsp:body> Action

jsp:element>、<jsp:attribute><jsp:body>操作用于动态定义 XML 元素。动态这个词很重要,因为它意味着 XML 元素可以在请求时生成,而不是在编译时静态生成。

以下是动态定义 XML 元素的简单示例 –

<%@page language = "java" contentType = "text/html"%>
<html xmlns = "http://www.w3c.org/1999/xhtml"
   xmlns:jsp = "http://java.sun.com/JSP/Page">
   
   <head><title>Generate XML Element</title></head>
   
   <body>
      <jsp:element name = "xmlElement">
         <jsp:attribute name = "xmlElementAttr">
            Value for the attribute
         </jsp:attribute>
         
         <jsp:body>
            Body for XML element
         </jsp:body>
      
      </jsp:element>
   </body>
</html>

这将在运行时生成以下 HTML 代码 –

<html xmlns = "http://www.w3c.org/1999/xhtml" xmlns:jsp = "http://java.sun.com/JSP/Page">
   <head><title>Generate XML Element</title></head>
   
   <body>
      <xmlElement xmlElementAttr = "Value for the attribute">
         Body for XML element
      </xmlElement>
   </body>
</html>

<jsp:text> 动作

jsp:text>动作可用于在 JSP 页面和文档中编写模板文本。以下是此操作的简单语法 –

<jsp:text>Template data</jsp:text>

模板主体不能包含其他元素;它只能包含文本和 EL 表达式(注 – EL 表达式将在后续章节中解释)。请注意,在 XML 文件中,您不能使用${whatever > 0}等表达式,因为大于号是非法的。相反,使用gt形式,例如${whatever gt 0}或者替代方法是将值嵌入CDATA部分。

<jsp:text><![CDATA[<br>]]></jsp:text>

如果您需要包含DOCTYPE声明,例如XHTML,您还必须使用<jsp:text>元素,如下所示 –

<jsp:text><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "DTD/xhtml1-strict.dtd">]]></jsp:text>

   <head><title>jsp:text action</title></head>
   
   <body>
      <books><book><jsp:text>  
         Welcome to JSP Programming
      </jsp:text></book></books>
   </body>
</html>

尝试使用和不使用<jsp:text>操作的上述示例。

JSP – 隐式对象

在本章中,我们将讨论 JSP 中的隐式对象。这些Object是JSP Container在每个页面中提供给开发者的Java对象,开发者可以直接调用它们而无需显式声明。JSP 隐式对象也称为预定义变量

下表列出了 JSP 支持的九个隐式对象 –

编号对象和描述
1个request
这是与请求关联的HttpServletRequest对象。
2个response
这是与对客户端的响应关联的HttpServletResponse对象。
3个out
这是用于将输出发送到客户端的PrintWriter对象。
4个session
这是与请求关联的HttpSession对象。
5个application
这是与应用程序上下文关联的ServletContext对象。
6个config
这是与页面关联的ServletConfig对象。
7pageContext
这封装了特定于服务器的功能的使用,例如更高性能的JspWriters
8个page
这只是this的同义词,用于调用翻译后的 servlet 类定义的方法。
9Exception
Exception对象允许指定的JSP 访问异常数据。

request 请求对象

请求对象是javax.servlet.http.HttpServletRequest对象的实例。每次客户端请求页面时,JSP 引擎都会创建一个新对象来表示该请求。

请求对象提供了获取 HTTP 头信息的方法,包括表单数据、cookie、HTTP 方法等。

我们可以在后续章节 – JSP – Client Request中介绍与请求对象相关的一整套方法。

response 响应对象

响应对象是javax.servlet.http.HttpServletResponse对象的实例。就像服务器创建请求对象一样,它也会创建一个对象来表示对客户端的响应。

响应对象还定义了处理创建新 HTTP 标头的接口。通过这个对象,JSP 程序员可以添加新的 cookie 或日期戳、HTTP 状态代码等。

我们将在后续章节 – JSP – 服务器响应中介绍与响应对象相关的一整套方法。

out 输出对象

out 隐式对象是javax.servlet.jsp.JspWriter对象的实例,用于在响应中发送内容。

根据页面是否缓冲,初始 JspWriter 对象的实例化有所不同。使用页面指令的buffered = ‘false’属性可以轻松关闭缓冲。

JspWriter 对象包含与java.io.PrintWriter类大部分相同的方法。但是,JspWriter 有一些额外的方法来处理缓冲。与 PrintWriter 对象不同,JspWriter 抛出IOExceptions

下表列出了我们将用于编写boolean char、int、double、object、String等的重要方法。

编号方法及说明
1个out.print(dataType dt)
打印数据类型值
2个out.println(dataType dt)
打印一个数据类型值,然后用换行符终止该行。
3个out.flush()
冲洗流。

session 会话对象

会话对象是javax.servlet.http.HttpSession的实例,其行为方式与会话对象在 Java Servlet 下的行为方式完全相同。

会话对象用于跟踪客户端请求之间的客户端会话。我们将在后续章节 – JSP – Session Tracking中介绍会话对象的完整用法。

application 应用对象

应用程序对象是生成的 Servlet 的ServletContext对象的直接包装器,实际上是javax.servlet.ServletContext对象的实例。

此对象是 JSP 页面在其整个生命周期中的表示。该对象在 JSP 页面初始化时创建,并在通过jspDestroy()方法删除 JSP 页面时删除。

通过向应用程序添加属性,您可以确保构成 Web 应用程序的所有 JSP 文件都可以访问它。

我们将在JSP – Hits Counter一章中检查应用程序对象的使用。

配置对象

配置对象是javax.servlet.ServletConfig的实例化,是生成的 servlet的ServletConfig对象的直接包装器。

该对象允许 JSP 程序员访问 Servlet 或 JSP 引擎初始化参数,例如路径或文件位置等。

下面的配置方法是你唯一可能用到的方法,它的用法很简单 –

config.getServletName();

这将返回 servlet 名称,它是包含在WEB-INF\web.xml文件中定义的<servlet-name>元素中的字符串。

pageContext 对象

pageContext 对象是javax.servlet.jsp.PageContext对象的一个​​实例。pageContext 对象用于表示整个 JSP 页面。

该对象旨在作为一种访问页面信息的方式,同时避免大部分实现细节。

该对象存储对每个请求的请求和响应对象的引用。application、config、session和 out 对象是通过访问此对象的属性派生的。

pageContext 对象还包含有关向 JSP 页面发出的指令的信息,包括缓冲信息、errorPageURL 和页面范围。

PageContext 类定义了几个字段,包括PAGE_SCOPE、REQUEST_SCOPE、SESSION_SCOPEAPPLICATION_SCOPE,它们标识了四个范围。它还支持 40 多种方法,其中大约一半是从javax.servlet.jsp.JspContext 类继承的。

其中一个重要的方法是removeAttribute。此方法接受一个或两个参数。例如,pageContext.removeAttribute (“attrName”)从所有范围中删除该属性,而以下代码仅将其从页面范围中删除 –

pageContext.removeAttribute("attrName", PAGE_SCOPE);

pageContext 的使用可以在JSP – 文件上传章节中查看。

页面page 对象

该对象是对页面实例的实际引用。它可以被认为是一个代表整个 JSP 页面的对象。

page 对象实际上是this对象的直接同义词。

异常exception 对象

异常对象是一个包装器,包含从上一页抛出的异常。它通常用于生成对错误条件的适当响应。

我们将在JSP – 异常处理章节中介绍此对象的完整用法。

JSP – 客户端请求

在本章中,我们将讨论 JSP 中的客户端请求。当浏览器请求网页时,它会向网络服务器发送大量信息。此信息无法直接读取,因为此信息作为 HTTP 请求标头的一部分传输。您可以检查HTTP 协议以获取更多信息。

下表列出了来自浏览器的重要标头信息。此信息经常用于网络编程 –

编号标题和说明
1个Accept
此标头指定浏览器或其他客户端可以处理的MIME类型。image/pngimage/jpeg的值是两种最常见的可能性。
2个Accept-Charset
此标头指定浏览器可用于显示信息的字符集。例如,ISO-8859-1
3个Accept-Encoding
此标头指定浏览器知道如何处理的编码类型。gzipcompress的值是两种最常见的可能性。
4个Accept-Language
此标头指定客户端的首选语言,以防 servlet 可以用多种语言生成结果。例如en、en-us、ru等。
5个Authorization
客户端在访问受密码保护的网页时使用此标头来标识自己。
6个Connection
此标头指示客户端是否可以处理持久 HTTP 连接。持久连接允许客户端或其他浏览器通过单个请求检索多个文件。Keep-Alive的值意味着应该使用持久连接。
7Content-Length
此标头仅适用于POST请求,并以字节为单位给出 POST 数据的大小。
8个Cookie
此标头将 cookie 返回给先前将它们发送到浏览器的服务器。
9Host
此标头指定原始 URL 中给出的主机和端口。
10If-Modified-Since
此标头表示客户仅在指定日期后更改页面时才需要该页面。如果没有更新的结果可用,服务器会发送一个代码 304,这意味着未修改标头。
11If-Unmodified-Since
此标头与If-Modified-Since相反;它指定仅当文档早于指定日期时操作才应该成功。
12Referer
此标头指示引用网页的 URL。例如,如果您在网页 1 上单击指向网页 2 的链接,则当浏览器请求网页 2 时,网页 1 的 URL 将包含在 Referer 标头中。
13User-Agent
此标头标识发出请求的浏览器或其他客户端,可用于向不同类型的浏览器返回不同的内容。

HttpServletRequest 对象

请求对象是javax.servlet.http.HttpServletRequest对象的实例。每次客户端请求页面时,JSP 引擎都会创建一个新对象来表示该请求。

request对象提供了获取HTTP头信息的方法,包括表单数据、cookies、HTTP方法等。

下表列出了可用于在 JSP 程序中读取 HTTP 标头的重要方法。这些方法可用于表示客户端对网络服务器的请求的HttpServletRequest对象。

编号方法及说明
1个Cookie[] getCookies()
返回一个数组,其中包含客户端随此请求发送的所有 Cookie 对象。
2个Enumeration getAttributeNames()
返回一个枚举,其中包含可用于此请求的属性的名称。
3个Enumeration getHeaderNames()
返回此请求包含的所有标头名称的枚举。
4个Enumeration getParameterNames()
返回包含此请求中包含的参数名称的 String 对象的枚举。
5个HttpSession getSession()
返回与此请求关联的当前会话,或者如果请求没有会话,则创建一个。
6个HttpSession getSession(boolean create)
返回与此请求关联的当前 HttpSession,或者如果没有当前会话且 create 为真,则返回一个新会话。
7Locale getLocale()
根据 Accept-Language 标头返回客户端将接受内容的首选区域设置。
8个Object getAttribute(String name)
将指定属性的值作为对象返回,如果不存在给定名称的属性,则返回 null。
9ServletInputStream getInputStream() 方法使用 ServletInputStream 以二进制数据的形式检索请求的主体。
10String getAuthType()
返回用于保护 servlet 的身份验证方案的名称,例如“BASIC”或“SSL”,如果 JSP 未受保护,则返回 null。
11String getCharacterEncoding()
返回此请求正文中使用的字符编码的名称。
12String getContentType()
返回请求正文的 MIME 类型,如果类型未知,则返回 null。
13String getContextPath()
返回指示请求上下文的请求 URI 部分。
14String getHeader(String name)
以字符串形式返回指定请求标头的值。
15String getMethod()
返回发出此请求的 HTTP 方法的名称,例如 GET、POST 或 PUT。
16String getParameter(String name)
以字符串形式返回请求参数的值,如果参数不存在则返回 null。
17String getPathInfo()
返回与客户端发出此请求时发送的 URL 关联的任何额外路径信息。
18String getProtocol()
返回请求使用的协议的名称和版本。
19String getQueryString()
返回路径后包含在请求 URL 中的查询字符串。
20String getRemoteAddr()
返回发送请求的客户端的 Internet 协议 (IP) 地址。
21String getRemoteHost()
返回发送请求的客户端的完全限定名称。
22String getRemoteUser()
如果用户已通过身份验证,则返回发出此请求的用户的登录名;如果用户未通过身份验证,则返回 null。
23String getRequestURI()
返回此请求的 URL 从协议名称到 HTTP 请求第一行中的查询字符串的部分。
24String getRequestedSessionId()
返回客户端指定的会话 ID。
25String getServletPath()
返回此请求的 URL 中调用 JSP 的部分。
26String[] getParameterValues(String name)
返回包含给定请求参数具有的所有值的 String 对象数组,如果参数不存在则返回 null。
27boolean isSecure()
返回一个布尔值,指示此请求是否使用安全通道(例如 HTTPS)发出。
28int getContentLength()
返回请求主体的长度(以字节为单位)并由输入流提供,如果长度未知,则返回 -1。
29int getIntHeader(String name)
以 int 形式返回指定请求标头的值。
30int getServerPort()
返回接收此请求的端口号。

HTTP 标头请求示例

以下是使用HttpServletRequest的getHeaderNames()方法读取 HTTP 头信息的示例。此方法返回一个枚举,其中包含与当前 HTTP 请求关联的标头信息。

一旦我们有了枚举,我们就可以以标准方式循环枚举。我们将使用hasMoreElements()方法来确定何时停止,并使用nextElement()方法来获取每个参数名称的名称。

<%@ page import = "java.io.*,java.util.*" %>

<html>
   <head>
      <title>HTTP Header Request Example</title>
   </head>

   <body>
      <center>
         <h2>HTTP Header Request Example</h2>
         
         <table width = "100%" border = "1" align = "center">
            <tr bgcolor = "#949494">
               <th>Header Name</th>
               <th>Header Value(s)</th>
            </tr>
            <%
               Enumeration headerNames = request.getHeaderNames();
               while(headerNames.hasMoreElements()) {
                  String paramName = (String)headerNames.nextElement();
                  out.print("<tr><td>" + paramName + "</td>\n");
                  String paramValue = request.getHeader(paramName);
                  out.println("<td> " + paramValue + "</td></tr>\n");
               }
            %>
         </table>
      </center>
   
   </body>
</html>

现在让我们把上面的代码放在main.jsp中并尝试访问它。

HTTP 标头请求示例

Header NameHeader Value(s)
accept*/*
accept-languageen-us
user-agentMozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; InfoPath.2; MS-RTC LM 8)
accept-encodinggzip, deflate
hostlocalhost:8080
connectionKeep-Alive
cache-controlno-cache

您可以尝试以类似的方式处理所有方法。

JSP – 服务器响应

在本章中,我们将讨论 JSP 中的服务器响应。当 Web 服务器响应 HTTP 请求时,响应通常由状态行、一些响应标头、空行和文档组成。一个典型的回应是这样的 –

HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
   (Blank Line)
<!doctype ...>

<html>
   <head>...</head>
   <body>
      ...
   </body>
</html>

状态行由 HTTP 版本(示例中的 HTTP/1.1)、状态代码(示例中的 200)和与状态代码对应的非常短的消息(示例中的 OK)组成。

以下是从 Web 服务器返回到浏览器的最有用的 HTTP 1.1 响应标头的摘要。这些标头经常用于网络编程 –

编号标题和说明
1个Allow
此标头指定服务器支持的请求方法(GET 、 POST等)。
2个Cache-Control
此标头指定可以安全缓存响应文档的情况。它可以有public、privateno-cache等值。Public 表示文档是可缓存的,Private 表示文档供单个用户使用,并且只能存储在私有(非共享)缓存中,no-cache 表示文档永远不应该被缓存。
3个Connection
此标头指示浏览器是否使用持久 HTTP 连接。close值指示浏览器不要使用持久 HTTP 连接,keep-alive意味着使用持久连接。
4个Content-Disposition
此标头允许您请求浏览器要求用户将对磁盘的响应保存在给定名称的文件中。
5个Content-Encoding
此标头指定页面在传输过程中的编码方式。
6个Content-Language
此标题表示编写文档所用的语言。例如,en、en-us、ru等。
7Content-Length
此标头指示响应中的字节数。仅当浏览器使用持久(保持活动)HTTP 连接时才需要此信息。
8个Content-Type
此标头提供响应文档的MIME多用途 Internet 邮件扩展)类型。
9Expires
此标头指定内容应被视为过时并因此不再被缓存的时间。
10Last-Modified
此标头指示上次更改文档的时间。然后客户端可以缓存文档并在以后的请求中通过If-Modified-Since请求标头提供日期。
11Location
此标头应包含在状态代码为 300 的所有响应中。这会通知浏览器文档地址。浏览器会自动重新连接到该位置并检索新文档。
12Refresh
此标头指定浏览器应在多长时间内请求更新的页面。您可以指定刷新页面的时间(以秒为单位)。
13Retry-After
此标头可与503(服务不可用)响应结合使用,以告知客户端可以在多长时间内重复其请求。
14Set-Cookie
此标头指定与页面关联的 cookie。

HttpServletResponse 对象

响应对象是javax.servlet.http.HttpServletResponse 对象的实例。就像服务器创建请求对象一样,它也会创建一个对象来表示对客户端的响应。

响应对象还定义了处理创建新 HTTP 标头的接口。通过此对象,JSP 程序员可以添加新的 cookie 或日期戳、HTTP 状态代码等。

以下方法可用于在您的 servlet 程序中设置 HTTP 响应标头。这些方法可用于HttpServletResponse对象。该对象表示服务器响应。

编号方法及说明
1个String encodeRedirectURL(String url)
对指定的 URL 进行编码以在sendRedirect方法中使用,或者如果不需要编码,则返回未更改的 URL。
2个String encodeURL(String url)
通过在其中包含会话 ID 对指定的 URL 进行编码,或者,如果不需要编码,则返回未更改的 URL。
3个boolean containsHeader(String name)
返回一个布尔值,指示命名的响应标头是否已设置。
4个boolean isCommitted()
返回一个布尔值,指示响应是否已提交。
5个void addCookie(Cookie cookie)
将指定的 cookie 添加到响应中。
6个void addDateHeader(String name, long date)
添加具有给定名称和日期值的响应标头。
7void addHeader(String name, String value)
添加具有给定名称和值的响应标头。
8个void addIntHeader(String name, int value)
添加具有给定名称和整数值的响应标头。
9void flushBuffer()
强制将缓冲区中的任何内容写入客户端。
10void reset()
清除缓冲区中存在的所有数据以及状态代码和标头。
11void resetBuffer()
清除响应中底层缓冲区的内容,而不清除标头或状态代码。
12void sendError(int sc)
使用指定的状态代码并清除缓冲区向客户端发送错误响应。
13void sendError(int sc, String msg)
使用指定的状态向客户端发送错误响应。
14void sendRedirect(String location)
使用指定的重定向位置 URL 向客户端发送临时重定向响应。
15void setBufferSize(int size)
设置响应正文的首选缓冲区大小。
16void setCharacterEncoding(String charset)
将发送到客户端的响应的字符编码(MIME 字符集)设置为 UTF-8。
17void setContentLength(int len)
在 HTTP servlet 中设置响应中内容主体的长度;此方法还设置 HTTP Content-Length 标头。
18void setContentType(String type)
如果尚未提交响应,则设置发送到客户端的响应的内容类型。
19void setDateHeader(String name, long date)
设置具有给定名称和日期值的响应标头。
20void setHeader(String name, String value)
设置具有给定名称和值的响应标头。
21void setIntHeader(String name, int value)
设置具有给定名称和整数值的响应标头。
22void setLocale(Locale loc)
如果尚未提交响应,则设置响应的区域设置。
23void setStatus(int sc)
设置此响应的状态代码。

HTTP 标头响应示例

以下示例将使用setIntHeader()方法来设置刷新标头以模拟数字时钟 –

<%@ page import = "java.io.*,java.util.*" %>

<html>
   
   <head>
      <title>Auto Refresh Header Example</title>
   </head>
   
   <body>
      <center>
         <h2>Auto Refresh Header Example</h2>
         <%
            // Set refresh, autoload time as 5 seconds
            response.setIntHeader("Refresh", 5);
            
            // Get current time
            Calendar calendar = new GregorianCalendar();
            
            String am_pm;
            int hour = calendar.get(Calendar.HOUR);
            int minute = calendar.get(Calendar.MINUTE);
            int second = calendar.get(Calendar.SECOND);
            
            if(calendar.get(Calendar.AM_PM) == 0) 
               am_pm = "AM";
            else
               am_pm = "PM";
               String CT = hour+":"+ minute +":"+ second +" "+ am_pm;
               out.println("Current Time is: " + CT + "\n");
         %>
      </center>
   
   </body>
</html>

现在将上面的代码放到main.jsp中,尝试访问它。这将每隔 5 秒显示一次当前系统时间,如下所示。运行 JSP。您将收到以下输出: –

Auto Refresh Header Example
Current Time is: 9:44:50 PM

您可以尝试以类似的方式解决其他方法。

JSP – Http 状态代码

在本章中,我们将讨论 JSP 中的 Http 状态代码。HTTP 请求和 HTTP 响应消息的格式相似,具有以下结构 –

  • 初始状态行 + CRLF(回车 + 换行即换行)
  • 零个或多个标题行 + CRLF
  • 一个空行,即。一个CRLF
  • 可选的消息正文,如文件、查询数据或查询输出。

例如,服务器响应标头如下所示 –

HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
   (Blank Line)
<!doctype ...>

<html>
   <head>...</head>
   
   <body>
      ...
   </body>
</html>

状态行由HTTP 版本(示例中的 HTTP/1.1)、状态码(示例中的 200)和状态码对应的非常短的消息(示例中的 OK)组成。

下表列出了可能从 Web 服务器返回的 HTTP 状态代码和相关消息 –

代码信息描述
100Continue服务器只收到了请求的一部分,但只要没有被拒绝,客户端应该继续请求
101Switching Protocols服务器切换协议。
200OK请求OK
201Created请求完成,创建新资源 
202Accepted接受请求进行处理,但处理未完成。
203Non-authoritative Information
204No Content
205Reset Content
206Partial Content
300Multiple Choices链接列表;用户可以选择一个链接并转到该位置。最多五个地址。
301Moved Permanently请求的页面已移至新网址。
302Found请求的页面已暂时移至新网址。
303See Other请求的页面可以在不同的 url 下找到。
304Not Modified
305Use Proxy
306Unused此代码用于以前的版本。它不再使用,但代码已保留。
307Temporary Redirect请求的页面已暂时移至新网址。
400Bad Request服务器不理解请求。
401Unauthorized请求的页面需要用户名和密码。
402Payment Required您还不能使用此代码。
403Forbidden请求的页面被禁止访问
404Not Found服务器找不到请求的页面。
405Method Not Allowed不允许使用请求中指定的方法。
406Not Acceptable服务器只能生成客户端不接受的响应。
407Proxy Authentication Required您必须先通过代理服务器进行身份验证,然后才能为该请求提供服务。
408Request Timeout请求花费的时间比服务器准备等待的时间长。
409Conflict由于冲突,请求无法完成。
410Gone请求的页面不再可用。
411Length Required“内容长度”未定义。没有它,服务器将不会接受请求。
412Precondition Failed请求中给出的先决条件被服务器评估为 false。
413Request Entity Too Large服务器不会接受请求,因为请求实体太大。
414Request-url Too Long服务器不会接受请求,因为 url 太长。当您将“post”请求转换为具有长查询信息的“get”请求时,会发生这种情况。
415Unsupported Media Type服务器不会接受请求,因为不支持媒体类型。
417Expectation Failed
500Internal Server Error请求未完成。服务器遇到意外情况。
501Not Implemented请求未完成。服务器不支持所需的功能。
502Bad Gateway请求未完成。服务器收到来自上游服务器的无效响应。
503Service Unavailable请求未完成。服务器暂时过载或停机。
504Gateway Timeout网关已超时。
505HTTP Version Not SupportedThe server does not support the “http protocol” version.

设置 HTTP 状态代码的方法

以下方法可用于在您的 servlet 程序中设置 HTTP 状态代码。这些方法可用于HttpServletResponse对象。

编号方法及说明
1public void setStatus (int statusCode)
此方法设置任意状态代码。
setStatus 方法将 int(状态代码)作为参数。
如果您的响应包含特殊状态代码和文档,请务必在使用
PrintWriter实际返回任何内容之前调用
setStatus
2public void sendRedirect(String url)
此方法生成 302 响应以及提供新文档 URL 的Location标头。
3个public void sendError(int code, String message)
此方法发送一个状态代码(通常为 404)以及一条在 HTML 文档中自动格式化并发送给客户端的短消息。

HTTP 状态代码示例

以下示例显示了如何将 407 错误代码发送到客户端浏览器。在此之后,浏览器将显示“Need authentication!!! ”消息。

<html>
   <head>
      <title>Setting HTTP Status Code</title>
   </head>
   
   <body>
      <%
         // Set error code and reason.
         response.sendError(407, "Need authentication!!!" );
      %>
   </body>
</html>

您将收到以下输出 –

HTTP Status 407 - Need authentication!!!
type Status report
message Need authentication!!!
description The client must first authenticate itself with the proxy (Need authentication!!!).
Apache Tomcat/5.5.29

为了更加熟悉 HTTP 状态代码,请尝试设置不同的状态代码及其描述。

JSP – 表单处理

在本章中,我们将讨论 JSP 中的表单处理。当您需要将一些信息从浏览器传递到 Web 服务器并最终传递到后端程序时,您一定遇到过很多情况。浏览器使用两种方法将此信息传递给 Web 服务器。这些方法是 GET 方法和 POST 方法。

表单处理中的方法

现在让我们讨论表单处理中的方法。

获取方法

GET 方法发送附加到页面请求的编码用户信息。页面和编码信息由 ? 字符如下 –

http://www.code8cn.com/hello?key1=value1&key2=value2

GET 方法是将信息从浏览器传递到 Web 服务器的默认方法,它会生成一个长字符串,出现在浏览器的Location:box 中。建议最好不要使用 GET 方法。如果您有密码或其他敏感信息要传递给服务器。

GET 方法有大小限制:请求字符串中只能包含 1024 个字符

此信息使用QUERY_STRING 标头传递,可通过 QUERY_STRING 环境变量访问,该环境变量可使用请求对象的getQueryString()getParameter()方法处理。

POST方法

通常更可靠的向后端程序传递信息的方法是 POST 方法。

此方法以与 GET 方法完全相同的方式打包信息,但不是在 ? 之后将其作为文本字符串发送。在 URL 中,它将它作为单独的消息发送。此消息以标准输入的形式到达后端程序,您可以对其进行解析并用于处理。

JSP 处理此类请求使用getParameter()方法读取简单参数,并使用getInputStream()方法读取来自客户端的二进制数据流。

使用 JSP 读取表单数据

JSP 根据情况使用以下方法自动处理表单数据解析 –

  • getParameter() – 您调用request.getParameter()方法来获取表单参数的值。
  • getParameterValues() – 如果参数出现多次并返回多个值,例如复选框,则调用此方法。
  • getParameterNames() – 如果您想要当前请求中所有参数的完整列表,请调用此方法。
  • getInputStream() – 调用此方法以读取来自客户端的二进制数据流。

使用 URL 的 GET 方法示例

以下 URL 将使用 GET 方法将两个值传递给 HelloForm 程序。

http://localhost:8080/main.jsp?first_name=ZARA&last_name=ALI

下面是main.jsp JSP 程序,用于处理 Web 浏览器提供的输入。我们将使用getParameter()方法,这使得访问传递的信息变得非常容易 –

<html>
   <head>
      <title>Using GET Method to Read Form Data</title>
   </head>
   
   <body>
      <h1>Using GET Method to Read Form Data</h1>
      <ul>
         <li><p><b>First Name:</b>
            <%= request.getParameter("first_name")%>
         </p></li>
         <li><p><b>Last  Name:</b>
            <%= request.getParameter("last_name")%>
         </p></li>
      </ul>
   
   </body>
</html>

现在在浏览器的Location:box 中输入http://localhost:8080/main.jsp?first_name=ZARA&last_name=ALI。这将产生以下结果 –

Using GET Method to Read Form DataFirst Name: ZARALast Name: ALI

使用表单的 GET 方法示例

以下是使用 HTML 表单和提交按钮传递两个值的示例。我们将使用相同的 JSP main.jsp 来处理这个输入。

<html>
   <body>
      
      <form action = "main.jsp" method = "GET">
         First Name: <input type = "text" name = "first_name">
         <br />
         Last Name: <input type = "text" name = "last_name" />
         <input type = "submit" value = "Submit" />
      </form>
      
   </body>
</html>

将此 HTML 保存在文件 Hello.htm 中,并将其放在<Tomcat-installation-directory>/webapps/ROOT directory中。当您访问http://localhost:8080/Hello.htm时,您将收到以下输出。

< p>尝试输入 First Name 和 Last Name,然后单击提交按钮以在运行 tomcat 的本地计算机上查看结果。根据提供的输入,它将生成与上述示例中提到的类似的结果。

使用表单的 POST 方法示例

让我们在上面的 JSP 中做一点修改来处理 GET 和 POST 方法。下面是main.jsp JSP 程序,用于处理 Web 浏览器使用 GET 或 POST 方法提供的输入。

事实上,上面的 JSP 没有任何变化,因为传递参数的唯一方式发生了变化,并且没有二进制数据被传递给 JSP 程序。文件处理相关概念将在我们需要读取二进制数据流的单独章节中解释。

<html>
   <head>
      <title>Using GET and POST Method to Read Form Data</title>
   </head>
   
   <body>
      <center>
      <h1>Using POST Method to Read Form Data</h1>
      
      <ul>
         <li><p><b>First Name:</b>
            <%= request.getParameter("first_name")%>
         </p></li>
         <li><p><b>Last  Name:</b>
            <%= request.getParameter("last_name")%>
         </p></li>
      </ul>
   
   </body>
</html>

以下是Hello.htm文件的内容 –

<html>
   <body>
      
      <form action = "main.jsp" method = "POST">
         First Name: <input type = "text" name = "first_name">
         <br />
         Last Name: <input type = "text" name = "last_name" />
         <input type = "submit" value = "Submit" />
      </form>
      
   </body>
</html>

现在让我们将main.jsp和 hello.htm 保存在<Tomcat-installationdirectory>/webapps/ROOT 目录中。当您访问http://localhost:8080/Hello.htm时,您将收到以下输出。名:
姓: 

尝试输入名字和姓氏,然后单击提交按钮以在运行 tomcat 的本地计算机上查看结果。

根据提供的输入,您将收到与上述示例类似的结果。

将复选框数据传递给 JSP 程序

当需要选择多个选项时,使用复选框。

下面是一个示例HTML 代码 CheckBox.htm,用于具有两个复选框的表单。

<html>
   <body>
      
      <form action = "main.jsp" method = "POST" target = "_blank">
         <input type = "checkbox" name = "maths" checked = "checked" /> Maths
         <input type = "checkbox" name = "physics"  /> Physics
         <input type = "checkbox" name = "chemistry" checked = "checked" /> Chemistry
         <input type = "submit" value = "Select Subject" />
      </form>
      
   </body>
</html>

上面的代码将生成以下结果 -数学 物理 化学 

以下是 main.jsp JSP 程序,用于处理 Web 浏览器为复选框按钮提供的输入。

<html>
   <head>
      <title>Reading Checkbox Data</title>
   </head>
   
   <body>
      <h1>Reading Checkbox Data</h1>
      
      <ul>
         <li><p><b>Maths Flag:</b>
            <%= request.getParameter("maths")%>
         </p></li>
         <li><p><b>Physics Flag:</b>
            <%= request.getParameter("physics")%>
         </p></li>
         <li><p><b>Chemistry Flag:</b>
            <%= request.getParameter("chemistry")%>
         </p></li>
      </ul>
   
   </body>
</html>

上述程序将产生以下结果 –

Reading Checkbox Data

Maths Flag :: on
Physics Flag:: null
Chemistry Flag:: on

读取所有表单参数

以下是一个通用示例,它使用HttpServletRequest 的getParameterNames()方法来读取所有可用的表单参数。此方法返回一个枚举,其中包含未指定顺序的参数名称。

一旦我们有了枚举,我们就可以以标准方式循环枚举,使用hasMoreElements()方法确定何时停止并使用nextElement()方法获取每个参数名称。

<%@ page import = "java.io.*,java.util.*" %>

<html>
   <head>
      <title>HTTP Header Request Example</title>
   </head>

   <body>
      <center>
         <h2>HTTP Header Request Example</h2>
         <table width = "100%" border = "1" align = "center">
            <tr bgcolor = "#949494">
               <th>Param Name</th>
               <th>Param Value(s)</th>
            </tr>
            <%
               Enumeration paramNames = request.getParameterNames();
               while(paramNames.hasMoreElements()) {
                  String paramName = (String)paramNames.nextElement();
                  out.print("<tr><td>" + paramName + "</td>\n");
                  String paramValue = request.getHeader(paramName);
                  out.println("<td> " + paramValue + "</td></tr>\n");
               }
            %>
         </table>
      </center>
   
   </body>
</html>

以下是Hello.htm的内容-

<html>
   <body>
      
      <form action = "main.jsp" method = "POST" target = "_blank">
         <input type = "checkbox" name = "maths" checked = "checked" /> Maths
         <input type = "checkbox" name = "physics"  /> Physics
         <input type = "checkbox" name = "chemistry" checked = "checked" /> Chem
         <input type = "submit" value = "Select Subject" />
      </form>
   
   </body>
</html>

现在尝试使用上面的 Hello.htm 调用 JSP;这将根据提供的输入生成如下结果 –

读取所有表单参数

参数名称参数值
数学
化学

您可以尝试上面的 JSP 来读取任何其他表单的数据,这些数据具有其他对象,如文本框、单选按钮或下拉列表等。

JSP – 过滤器

在本章中,我们将讨论 JSP 中的过滤器。Servlet 和 JSP 过滤器是 Java 类,可在 Servlet 和 JSP 编程中用于以下目的 –

  • 在客户端访问后端资源之前拦截来自客户端的请求。
  • 在服务器将响应发送回客户端之前对其进行操作。

规范建议使用各种类型的过滤器 –

  • 身份验证过滤器
  • 数据压缩过滤器
  • 加密过滤器
  • 触发资源访问事件的过滤器
  • 图像转换滤镜
  • 日志记录和审计过滤器
  • MIME 类型链过滤器
  • 分词过滤器
  • 转换 XML 内容的 XSL/T 过滤器

过滤器部署在部署描述符文件web.xml中,然后映射到应用程序部署描述符中的 servlet 或 JSP 名称或 URL 模式。部署描述符文件 web.xml 可以在<Tomcat-installation-directory>\conf目录中找到。

当 JSP 容器启动您的 Web 应用程序时,它会为您在部署描述符中声明的每个过滤器创建一个实例。过滤器按照它们在部署描述符中声明的顺序执行。

Servlet 过滤方法

过滤器只是一个实现javax.servlet.Filter接口的 Java 类。javax.servlet.Filter 接口定义了三种方法 –

编号方法及说明
1个public void doFilter (ServletRequest, ServletResponse, FilterChain)每次由于客户端请求链末端的资源而通过链传递请求/响应对时,容器都会调用此方法。
2个public void init(FilterConfig filterConfig)Web 容器调用此方法以向过滤器表明它已投入使用。
3个公共无效销毁()Web 容器调用此方法以向过滤器表明它正在停止服务。

JSP 过滤器示例

下面的示例显示了每次访问任何 JSP 文件时如何打印客户端的 IP 地址和当前日期时间。这个例子会让您对 JSP 过滤器有一个基本的了解,但是您可以使用相同的概念编写更复杂的过滤器应用程序 –

// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
 
// Implements Filter class
public class LogFilter implements Filter  {
   public void  init(FilterConfig config) throws ServletException {
      // Get init parameter 
      String testParam = config.getInitParameter("test-param"); 
 
      //Print the init parameter 
      System.out.println("Test Param: " + testParam); 
   }
   public void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws java.io.IOException, ServletException {
      
      // Get the IP address of client machine.   
      String ipAddress = request.getRemoteAddr();
      
      // Log the IP address and current timestamp.
      System.out.println("IP "+ ipAddress + ", Time "+ new Date().toString());
      
      // Pass request back down the filter chain
      chain.doFilter(request,response);
   }
   public void destroy( ) {
      /* Called before the Filter instance is removed 
      from service by the web container*/
   }
}

以通常的方式编译LogFilter.java并将您的LogFilter.class文件放在<Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes中。

Web.xml 中的 JSP 过滤器映射

定义过滤器然后映射到 URL 或 JSP 文件名,这与定义 Servlet 然后映射到web.xml文件中的 URL 模式非常相似。在部署描述符文件web.xml中为过滤器标记创建以下条目

<filter>
   <filter-name>LogFilter</filter-name>
   <filter-class>LogFilter</filter-class>
   
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>

<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

上面的过滤器将应用于所有 servlet 和 JSP,因为我们在配置中指定了/*。如果您只想对少数 servlet 或 JSP 应用过滤器,则可以指定特定的 servlet 或 JSP 路径。

现在尝试调用任何 servlet 或 JSP,您将在 Web 服务器日志中看到生成的日志。您可以使用Log4J 记录器将上面的日志记录在一个单独的文件中。

使用多个过滤器

您的 Web 应用程序可能会定义多个具有特定用途的不同过滤器。考虑一下,您定义了两个过滤器AuthenFilterLogFilter。其余过程将保持如上所述,除非您需要创建一个不同的映射,如下所述 –

<filter>
   <filter-name>LogFilter</filter-name>
   <filter-class>LogFilter</filter-class>
   
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>
 
<filter>
   <filter-name>AuthenFilter</filter-name>
   <filter-class>AuthenFilter</filter-class>
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>
 
<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
 
<filter-mapping>
   <filter-name>AuthenFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

过滤器申请顺序

web.xml 中过滤器映射元素的顺序决定了 Web 容器将过滤器应用于 servlet 或 JSP 的顺序。要反转过滤器的顺序,只需反转web.xml文件中的过滤器映射元素。

例如,上面的示例将首先应用 LogFilter,然后将 AuthenFilter 应用到任何 servlet 或 JSP;以下示例将颠倒顺序 –

<filter-mapping>
   <filter-name>AuthenFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
 
<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

JSP – Cookie 处理

在本章中,我们将讨论 JSP 中的 Cookies 处理。Cookies 是存储在客户端计算机上的文本文件,它们被保存用于各种信息跟踪目的。JSP 使用底层 servlet 技术透明地支持 HTTP cookie。

识别和返回用户涉及三个步骤 –

  • 服务器脚本向浏览器发送一组 cookie。例如,姓名、年龄或身份证号码等。
  • 浏览器将此信息存储在本地计算机上以备将来使用。
  • 当浏览器下次向网络服务器发送任何请求时,它会将这些 cookie 信息发送到服务器,服务器使用该信息来识别用户或也可能用于其他目的。

本章将教您如何设置或重置 cookie,如何访问它们以及如何使用 JSP 程序删除它们。

Cookie的解剖

Cookie 通常设置在 HTTP 标头中(尽管 JavaScript 也可以直接在浏览器上设置 cookie)。设置 cookie 的 JSP 可能会发送如下所示的标头 –

HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name = xyz; expires = Friday, 04-Feb-07 22:03:38 GMT; 
   path = /; domain = tutorialspoint.com
Connection: close
Content-Type: text/html

如您所见,Set-Cookie 标头包含一个名称值对、一个 GMT 日期、一个路径一个域。名称和值将进行 URL 编码。expires字段是给浏览器的指令,在给定的时间和日期之后“忘记” cookie。

如果浏览器配置为存储 cookie,它将保留此信息直到到期日。如果用户将浏览器指向与 cookie 的路径和域相匹配的任何页面,它将向服务器重新发送 cookie。浏览器的标题可能看起来像这样 –

GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.6 (X11; I; Linux 2.2.6-15apmac ppc)
Host: zink.demon.co.uk:1126

Accept: image/gif, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Cookie: name = xyz

然后,JSP 脚本将可以通过返回Cookie对象数组的请求方法request.getCookies()访问 cookie。

Servlet Cookie 方法

下表列出了与 Cookie 对象关联的有用方法,您可以在 JSP 中操作 cookie 时使用这些方法 –

编号方法及说明
1个public void setDomain(String pattern)
此方法设置 cookie 适用的域;例如,tutorialspoint.com。
2个public String getDomain()
此方法获取 cookie 适用的域;例如,tutorialspoint.com。
3个public void setMaxAge(int expiry)
此方法设置在 cookie 过期之前应该经过多少时间(以秒为单位)。如果您不设置此项,则 cookie 将仅在当前会话中有效。
4个public int getMaxAge()
此方法返回 cookie 的最长期限,以秒为单位指定,默认情况下,-1表示 cookie 将持续到浏览器关闭。
5个public String getName()
此方法返回 cookie 的名称。创建后不能更改名称。
6个public void setValue(String newValue)
此方法设置与 cookie 关联的值。
7public String getValue()
此方法获取与 cookie 关联的值。
8个public void setPath(String uri)
此方法设置此 cookie 适用的路径。如果您不指定路径,则会为与当前页面相同的目录中的所有 URL 以及所有子目录返回 cookie。
9public String getPath()
此方法获取此 cookie 适用的路径。
10public void setSecure(boolean flag)
此方法设置布尔值,指示 cookie 是否应仅通过加密(即 SSL)连接发送。
11public void setComment(String purpose)
此方法指定描述 cookie 用途的注释。如果浏览器向用户显示 cookie,则注释很有用。
12public String getComment()
此方法返回描述此 cookie 用途的注释,如果 cookie 没有注释,则返回 null。

使用 JSP 设置 Cookie

使用 JSP 设置 cookie 涉及三个步骤 –

第 1 步:创建 Cookie 对象

您使用 cookie 名称和 cookie 值调用 Cookie 构造函数,它们都是字符串。

Cookie cookie = new Cookie("key","value");

请记住,名称和值都不应包含空格或以下任何字符 –

[ ] ( ) = , " / ? @ : ;

第 2 步:设置最大年龄

您使用setMaxAge来指定 cookie 的有效时间(以秒为单位)。以下代码将设置 cookie 24 小时。

cookie.setMaxAge(60*60*24); 

第 3 步:将 Cookie 发送到 HTTP 响应标头中

您使用response.addCookie在 HTTP 响应标头中添加 cookie,如下所示

response.addCookie(cookie);

例子

让我们修改我们的表单示例,为名字和姓氏设置 cookie。

<%
   // Create cookies for first and last names.      
   Cookie firstName = new Cookie("first_name", request.getParameter("first_name"));
   Cookie lastName = new Cookie("last_name", request.getParameter("last_name"));
   
   // Set expiry date after 24 Hrs for both the cookies.
   firstName.setMaxAge(60*60*24); 
   lastName.setMaxAge(60*60*24); 
   
   // Add both the cookies in the response header.
   response.addCookie( firstName );
   response.addCookie( lastName );
%>

<html>
   <head>
      <title>Setting Cookies</title>
   </head>
   
   <body>
      <center>
         <h1>Setting Cookies</h1>
      </center>
      <ul>
         <li><p><b>First Name:</b>
            <%= request.getParameter("first_name")%>
         </p></li>
         <li><p><b>Last  Name:</b>
            <%= request.getParameter("last_name")%>
         </p></li>
      </ul>
   
   </body>
</html>

让我们把上面的代码放在main.jsp文件中,并在下面的 HTML 页面中使用它 –

<html>
   <body>
      
      <form action = "main.jsp" method = "GET">
         First Name: <input type = "text" name = "first_name">
         <br />
         Last Name: <input type = "text" name = "last_name" />
         <input type = "submit" value = "Submit" />
      </form>
      
   </body>
</html>

将以上HTML内容保存在文件hello.jsp中,并将hello.jspmain.jsp放在<Tomcat-installation-directory>/webapps/ROOT目录下。当您访问http://localhost:8080/hello.jsp时,这里是上述表单的实际输出。名:
姓: 

尝试输入名字和姓氏,然后单击提交按钮。这将在您的屏幕上显示名字和姓氏,并且还将设置两个 cookie firstNamelastName。下次您单击“提交”按钮时,这些 cookie 将传回服务器。

在下一节中,我们将解释如何在您的 Web 应用程序中访问这些 cookie。

使用 JSP 读取 Cookie

要读取 cookie,您需要通过调用HttpServletRequest的getCookies()方法来创建一个javax.servlet.http.Cookie对象数组。然后循环遍历数组,并使用getName()getValue()方法访问每个 cookie 和关联的值。

例子

现在让我们阅读上一个示例中设置的 cookie –

<html>
   <head>
      <title>Reading Cookies</title>
   </head>
   
   <body>
      <center>
         <h1>Reading Cookies</h1>
      </center>
      <%
         Cookie cookie = null;
         Cookie[] cookies = null;
         
         // Get an array of Cookies associated with the this domain
         cookies = request.getCookies();
         
         if( cookies != null ) {
            out.println("<h2> Found Cookies Name and Value</h2>");
            
            for (int i = 0; i < cookies.length; i++) {
               cookie = cookies[i];
               out.print("Name : " + cookie.getName( ) + ",  ");
               out.print("Value: " + cookie.getValue( )+" <br/>");
            }
         } else {
            out.println("<h2>No cookies founds</h2>");
         }
      %>
   </body>
   
</html>

现在让我们将上面的代码放在main.jsp文件中并尝试访问它。如果将first_name cookie设置为“John”,将last_name cookie设置为“Player”,那么运行http://localhost:8080/main.jsp将显示以下结果 –

 Found Cookies Name and Value
Name : first_name, Value: John
Name : last_name,  Value: Player

使用 JSP 删除 Cookie

删除 cookie 非常简单。如果你想删除一个cookie,那么你只需要按照以下三个步骤 –

  • 读取一个已经存在的 cookie 并将其存储在 Cookie 对象中。
  • 使用setMaxAge()方法将 cookie 年龄设置为零以删除现有 cookie。
  • 将此 cookie 添加回响应标头。

例子

下面的示例将向您展示如何删除名为“first_name”的现有 cookie ,并且当您下次运行 main.jsp JSP 时,它将返回 first_name 的空值。

<html>
   <head>
      <title>Reading Cookies</title>
   </head>
   
   <body>
      <center>
         <h1>Reading Cookies</h1>
      </center>
      <%
         Cookie cookie = null;
         Cookie[] cookies = null;
         
         // Get an array of Cookies associated with the this domain
         cookies = request.getCookies();
         
         if( cookies != null ) {
            out.println("<h2> Found Cookies Name and Value</h2>");
            
            for (int i = 0; i < cookies.length; i++) {
               cookie = cookies[i];
               
               if((cookie.getName( )).compareTo("first_name") == 0 ) {
                  cookie.setMaxAge(0);
                  response.addCookie(cookie);
                  out.print("Deleted cookie: " + 
                  cookie.getName( ) + "<br/>");
               }
               out.print("Name : " + cookie.getName( ) + ",  ");
               out.print("Value: " + cookie.getValue( )+" <br/>");
            }
         } else {
            out.println(
            "<h2>No cookies founds</h2>");
         }
      %>
   </body>
   
</html>

现在让我们把上面的代码放到main.jsp文件中并尝试访问它。它将显示以下结果 –

Cookies Name and Value
Deleted cookie : first_name
Name : first_name, Value: John
Name : last_name,  Value: Player

现在再次运行http://localhost:8080/main.jsp ,它应该只显示一个 cookie,如下所示 –

 Found Cookies Name and Value
Name : last_name,  Value: Player

您可以在 Internet Explorer 中手动删除您的 cookie。从“工具”菜单开始,然后选择“Internet 选项”。要删除所有 cookie,请单击删除 Cookie 按钮。

JSP – 会话跟踪

在本章中,我们将讨论 JSP 中的会话跟踪。HTTP 是一种“无状态”协议,这意味着每次客户端检索网页时,客户端都会打开一个单独的到 Web 服务器的连接,服务器自动不保留以前客户端请求的任何记录。

维护 Web 客户端和服务器之间的会话

现在让我们讨论一些维持 Web 客户端和 Web 服务器之间会话的选项 –

Cookies

Web 服务器可以将唯一的会话 ID 作为 cookie 分配给每个 Web 客户端,并且对于来自客户端的后续请求,可以使用接收到的 cookie 来识别它们。

这可能不是一种有效的方法,因为浏览器有时不支持 cookie。不建议使用此过程来维护会话。

隐藏的表单域

Web 服务器可以发送一个隐藏的 HTML 表单字段以及一个唯一的会话 ID,如下所示 –

<input type = "hidden" name = "sessionid" value = "12345">

此条目意味着,当提交表单时,指定的名称和值将自动包含在GETPOST数据中。每次 Web 浏览器发回请求时,session_id值可用于跟踪不同的 Web 浏览器。

这可能是跟踪会话的有效方法,但单击常规 (<A HREF…>) 超文本链接不会导致表单提交,因此隐藏的表单字段也不能支持一般会话跟踪。

网址重写

您可以在每个 URL 的末尾附加一些额外的数据。此数据标识会话;服务器可以将该会话标识符与其存储的有关该会话的数据相关联。

例如,对于http://code8cn.com/file.htm;sessionid=12345,会话标识符作为sessionid = 12345附加,可以在 Web 服务器上访问以识别客户端。

URL 重写是维护会话的更好方法,并且在浏览器不支持 cookie 时也适用。这里的缺点是您必须动态生成每个 URL 以分配会话 ID,尽管页面是一个简单的静态 HTML 页面。

会话对象

除了上述选项外,JSP 还使用 servlet 提供的 HttpSession 接口。这个接口提供了一种识别跨域用户的方法。

  • 一页请求或
  • 访问网站或
  • 存储有关该用户的信息

默认情况下,JSP 启用会话跟踪,并为每个新客户端自动实例化一个新的 HttpSession 对象。禁用会话跟踪需要通过将页面指令会话属性设置为 false 来明确关闭它,如下所示 –

<%@ page session = "false" %>

JSP 引擎通过隐式会话对象向 JSP 作者公开 HttpSession对象。由于会话对象已经提供给 JSP 程序员,程序员可以立即开始存储和从对象中检索数据,而无需任何初始化或getSession()

以下是通过会话对象可用的重要方法的摘要 –

编号方法及说明
1个public Object getAttribute(String name)
此方法返回在本次会话中与指定名称绑定的对象,如果该名称下没有绑定任何对象,则返回 null。
2个public Enumeration getAttributeNames()
此方法返回包含绑定到此会话的所有对象的名称的 String 对象的枚举。
3个public long getCreationTime()
此方法返回创建此会话的时间,自格林威治标准时间 1970 年 1 月 1 日午夜起以毫秒为单位测量。
4个public String getId()
此方法返回一个字符串,其中包含分配给此会话的唯一标识符。
5个public long getLastAccessedTime()
此方法返回客户端最后一次发送与此会话关联的请求的时间,作为自格林威治标准时间 1970 年 1 月 1 日午夜以来的毫秒数。
6个public int getMaxInactiveInterval()
此方法返回最大时间间隔(以秒为单位),servlet 容器将在客户端访问之间保持此会话打开。
7public void invalidate()
此方法使此会话无效并解除绑定到它的任何对象。
8个public boolean isNew()
如果客户端还不知道会话或客户端选择不加入会话,则此方法返回 true。
9public void removeAttribute(String name)
此方法从此会话中删除与指定名称绑定的对象。
10public void setAttribute(String name, Object value)
此方法使用指定的名称将对象绑定到此会话。
11public void setMaxInactiveInterval(int interval)
此方法指定在 servlet 容器使此会话无效之前客户端请求之间的时间(以秒为单位)。

会话跟踪示例

此示例描述如何使用 HttpSession 对象找出会话的创建时间和上次访问时间。如果请求尚不存在,我们会将新会话与请求相关联。

<%@ page import = "java.io.*,java.util.*" %>
<%
   // Get session creation time.
   Date createTime = new Date(session.getCreationTime());
   
   // Get last access time of this Webpage.
   Date lastAccessTime = new Date(session.getLastAccessedTime());

   String title = "Welcome Back to my website";
   Integer visitCount = new Integer(0);
   String visitCountKey = new String("visitCount");
   String userIDKey = new String("userID");
   String userID = new String("ABCD");

   // Check if this is new comer on your Webpage.
   if (session.isNew() ){
      title = "Welcome to my website";
      session.setAttribute(userIDKey, userID);
      session.setAttribute(visitCountKey,  visitCount);
   } 
   visitCount = (Integer)session.getAttribute(visitCountKey);
   visitCount = visitCount + 1;
   userID = (String)session.getAttribute(userIDKey);
   session.setAttribute(visitCountKey,  visitCount);
%>

<html>
   <head>
      <title>Session Tracking</title>
   </head>
   
   <body>
      <center>
         <h1>Session Tracking</h1>
      </center>
      
      <table border = "1" align = "center"> 
         <tr bgcolor = "#949494">
            <th>Session info</th>
            <th>Value</th>
         </tr> 
         <tr>
            <td>id</td>
            <td><% out.print( session.getId()); %></td>
         </tr> 
         <tr>
            <td>Creation Time</td>
            <td><% out.print(createTime); %></td>
         </tr> 
         <tr>
            <td>Time of Last Access</td>
            <td><% out.print(lastAccessTime); %></td>
         </tr> 
         <tr>
            <td>User ID</td>
            <td><% out.print(userID); %></td>
         </tr> 
         <tr>
            <td>Number of visits</td>
            <td><% out.print(visitCount); %></td>
         </tr> 
      </table> 
   
   </body>
</html>

现在把上面的代码放在main.jsp中,尝试访问http://localhost:8080/main.jsp。运行 URL 后,您将收到以下结果 –

欢迎来到我的网站

Session信息

Session信息
ID0AE3EC93FF44E3C525B4351B77ABB2D5
创建时间2020 年 6 月 8 日星期二 17:26:40 GMT+04:00
上次访问时间2020 年 6 月 8 日星期二 17:26:40 GMT+04:00
用户身份A B C D
访问次数0

现在尝试第二次运行同一个 JSP,您将收到以下结果。

欢迎回到我的网站

会话信息

信息类型价值
ID0AE3EC93FF44E3C525B4351B77ABB2D5
创建时间2020 年 6 月 8 日星期二 17:26:40 GMT+04:00
上次访问时间2020 年 6 月 8 日星期二 17:26:40 GMT+04:00
用户身份A B C D
访问次数1个

删除会话数据

当您完成用户的会话数据时,您有几个选择 –

  • 删除特定属性– 您可以调用public void removeAttribute(String name)方法删除与特定键关联的值。
  • Delete the whole session – 您可以调用public void invalidate()方法来丢弃整个会话。
  • 设置会话超时– 您可以调用public void setMaxInactiveInterval(int interval)方法单独设置会话超时。
  • 注销用户– 支持 servlets 2.4 的服务器,您可以调用注销将客户端从 Web 服务器注销并使属于所有用户的所有会话无效。
  • web.xml 配置– 如果您使用的是 Tomcat,除了上述方法外,您还可以在 web.xml 文件中配置会话超时,如下所示。
<session-config>
   <session-timeout>15</session-timeout>
</session-config>

超时以分钟表示,并覆盖 Tomcat 中的默认超时 30 分钟。

servlet 中的getMaxInactiveInterval()方法返回该会话的超时时间(以秒为单位)。因此,如果您的会话在 web.xml 中配置为 15 分钟,getMaxInactiveInterval()将返回 900。

JSP – 文件上传

在本章中,我们将讨论 JSP 中的文件上传。JSP 可以与 HTML 表单标记一起使用,以允许用户将文件上传到服务器。上传的文件可以是文本文件或二进制文件或图像文件或任何文档。

创建文件上传表单

现在让我们了解如何创建文件上传表单。以下 HTML 代码创建一个上传器表单。以下是要注意的要点 –

  • 表单方法属性应设置为POST方法,不能使用GET方法。
  • 表单enctype属性应设置为multipart/form-data
  • 表单操作属性应设置为 JSP 文件,该文件将在后端服务器上处理文件上传。以下示例是使用uploadFile.jsp程序文件上传文件。
  • 要上传单个文件,您应该使用属性为 type = “file”的单个<input …/>标签。要允许上传多个文件,请包含多个具有不同名称属性值的输入标签。浏览器将浏览按钮与它们中的每一个相关联。
<html>
   <head>
      <title>File Uploading Form</title>
   </head>
   
   <body>
      <h3>File Upload:</h3>
      Select a file to upload: <br />
      <form action = "UploadServlet" method = "post"
         enctype = "multipart/form-data">
         <input type = "file" name = "file" size = "50" />
         <br />
         <input type = "submit" value = "Upload File" />
      </form>
   </body>
   
</html>

这将显示以下结果。您现在可以从本地 PC 中选择一个文件,当用户单击“上传文件”时,表单将与所选文件一起提交 –

File Upload − 
Select a file to upload − 

注意– 以上表格只是虚拟表格,不会工作,您应该在您的机器上尝试上面的代码以使其工作。

编写后端 JSP 脚本

现在让我们定义一个存储上传文件的位置。您可以在您的程序中对此进行硬编码,或者也可以使用外部配置添加此目录名称,例如 web.xml 中的context-param元素,如下所示 –

<web-app>
....
<context-param> 
   <description>Location to store uploaded file</description> 
   <param-name>file-upload</param-name> 
   <param-value>
      c:\apache-tomcat-5.5.29\webapps\data\
   </param-value> 
</context-param>
....
</web-app>

以下是UploadFile.jsp的源代码。这可以一次处理多个文件的上传。现在让我们在继续上传文件之前考虑以下事项。

  • 以下示例依赖于FileUpload;确保您的类路径中有最新版本的commons-fileupload.xxjar文件。您可以从https://commons.apache.org/fileupload/下载它。
  • FileUpload 依赖 Commons IO;确保你的类路径中有最新版本的commons-io-xxjar文件。您可以从https://commons.apache.org/io/下载它。
  • 在测试以下示例时,您应该上传一个小于maxFileSize的文件,否则该文件将不会被上传。
  • 确保您已提前创建目录c:\tempc:\apache-tomcat5.5.29\webapps\data 。
<%@ page import = "java.io.*,java.util.*, javax.servlet.*" %>
<%@ page import = "javax.servlet.http.*" %>
<%@ page import = "org.apache.commons.fileupload.*" %>
<%@ page import = "org.apache.commons.fileupload.disk.*" %>
<%@ page import = "org.apache.commons.fileupload.servlet.*" %>
<%@ page import = "org.apache.commons.io.output.*" %>

<%
   File file ;
   int maxFileSize = 5000 * 1024;
   int maxMemSize = 5000 * 1024;
   ServletContext context = pageContext.getServletContext();
   String filePath = context.getInitParameter("file-upload");

   // Verify the content type
   String contentType = request.getContentType();
   
   if ((contentType.indexOf("multipart/form-data") >= 0)) {
      DiskFileItemFactory factory = new DiskFileItemFactory();
      // maximum size that will be stored in memory
      factory.setSizeThreshold(maxMemSize);
      
      // Location to save data that is larger than maxMemSize.
      factory.setRepository(new File("c:\\temp"));

      // Create a new file upload handler
      ServletFileUpload upload = new ServletFileUpload(factory);
      
      // maximum file size to be uploaded.
      upload.setSizeMax( maxFileSize );
      
      try { 
         // Parse the request to get file items.
         List fileItems = upload.parseRequest(request);

         // Process the uploaded file items
         Iterator i = fileItems.iterator();

         out.println("<html>");
         out.println("<head>");
         out.println("<title>JSP File upload</title>");  
         out.println("</head>");
         out.println("<body>");
         
         while ( i.hasNext () ) {
            FileItem fi = (FileItem)i.next();
            if ( !fi.isFormField () ) {
               // Get the uploaded file parameters
               String fieldName = fi.getFieldName();
               String fileName = fi.getName();
               boolean isInMemory = fi.isInMemory();
               long sizeInBytes = fi.getSize();
            
               // Write the file
               if( fileName.lastIndexOf("\\") >= 0 ) {
                  file = new File( filePath + 
                  fileName.substring( fileName.lastIndexOf("\\"))) ;
               } else {
                  file = new File( filePath + 
                  fileName.substring(fileName.lastIndexOf("\\")+1)) ;
               }
               fi.write( file ) ;
               out.println("Uploaded Filename: " + filePath + 
               fileName + "<br>");
            }
         }
         out.println("</body>");
         out.println("</html>");
      } catch(Exception ex) {
         System.out.println(ex);
      }
   } else {
      out.println("<html>");
      out.println("<head>");
      out.println("<title>Servlet upload</title>");  
      out.println("</head>");
      out.println("<body>");
      out.println("<p>No file uploaded</p>"); 
      out.println("</body>");
      out.println("</html>");
   }
%>

现在尝试使用您在上面创建的 HTML 表单上传文件。当您尝试http://localhost:8080/UploadFile.htm时,它会显示以下结果。这将帮助您从本地计算机上传任何文件。

File Upload − 
Select a file to upload − 

如果您的 JSP 脚本工作正常,您的文件应该上传到c:\apache-tomcat5.5.29\webapps\data\目录中。

JSP – 处理日期

在本章中,我们将讨论如何在 JSP 中处理数据。使用 JSP 的最重要的优点之一是您可以使用核心 Java 中可用的所有方法。我们将带您了解java.util包中提供的Date类;这个类封装了当前的日期和时间。

Date 类支持两个构造函数。第一个构造函数用当前日期和时间初始化对象。

Date( )

以下构造函数接受一个参数,该参数等于自 1970 年 1 月 1 日午夜以来经过的毫秒数。

Date(long millisec)

一旦你有一个 Date 对象可用,你可以调用以下任何支持方法来处理日期 –

编号方法与说明
1个boolean after(Date date)
如果调用 Date 对象包含的日期晚于 date 指定的日期,则返回 true,否则返回 false。
2个boolean before(Date date)
如果调用 Date 对象包含的日期早于 date 指定的日期,则返回 true,否则返回 false。
3个Object clone( )
复制调用 Date 对象。
4个int compareTo(Date date)
将调用对象的值与日期的值进行比较。如果值相等,则返回 0。如果调用对象早于日期,则返回负值。如果调用对象晚于日期,则返回正值。
5个int compareTo(Object obj)
如果 obj 属于 Date 类,则与 compareTo(Date) 的操作相同。否则,它会抛出 ClassCastException。
6个long getTime( )
返回自 1970 年 1 月 1 日以来经过的毫秒数。
7long getTime( )
返回自 1970 年 1 月 1 日以来经过的毫秒数。
8个int hashCode( )
返回调用对象的哈希码。
9void setTime(long time)
设置由 time 指定的时间和日期,它表示从 1970 年 1 月 1 日午夜开始经过的时间(以毫秒为单位)
10String toString( )
将调用 Date 对象转换为字符串并返回结果。

获取当前日期和时间

使用 JSP 程序,很容易获得当前日期和时间。您可以使用带有toString()方法的简单 Date 对象来打印当前日期和时间,如下所示 –

<%@ page import = "java.io.*,java.util.*, javax.servlet.*" %>

<html>
   <head>
      <title>Display Current Date & Time</title>
   </head>
   
   <body>
      <center>
         <h1>Display Current Date & Time</h1>
      </center>
      <%
         Date date = new Date();
         out.print( "<h2 align = \"center\">" +date.toString()+"</h2>");
      %>
   </body>
</html>

现在让我们将代码保留在CurrentDate.jsp中,然后使用 URL http://localhost:8080/CurrentDate.jsp调用此 JSP 。您将收到以下结果 –

Display Current Date & Time
Mon Jun 21 21:46:49 GMT+04:00 2010

使用URL http://localhost:8080/CurrentDate.jsp刷新页面。每次刷新时,您都会发现以秒为单位的差异。

日期比较

如前几节所述,您可以在 JSP 脚本中使用所有可用的 Java 方法。如果您需要比较两个日期,请考虑以下方法 –

  • 您可以使用getTime()方法获取两个对象自 1970 年 1 月 1 日午夜以来经过的毫秒数,然后比较这两个值。
  • 您可以使用before( )、after( )equals( )方法,因为该月的 12 号在 18 号之前;例如,new Date(99, 2, 12).before(new Date (99, 2, 18))返回 true。
  • 您可以使用compareTo()方法;该方法由Comparable 接口定义,由 Date 实现。

使用 SimpleDateFormat 进行日期格式化

SimpleDateFormat 是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。SimpleDateFormat 允许您从选择任何用户定义的日期时间格式模式开始。

让我们修改上面的例子如下 –

<%@ page import = "java.io.*,java.util.*" %>
<%@ page import = "javax.servlet.*,java.text.*" %>

<html>
   <head>
      <title>Display Current Date & Time</title>
   </head>
   
   <body>
      <center>
         <h1>Display Current Date & Time</h1>
      </center>
      <%
         Date dNow = new Date( );
         SimpleDateFormat ft = 
         new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
         out.print( "<h2 align=\"center\">" + ft.format(dNow) + "</h2>");
      %>
   </body>
</html>

再次编译上面的 servlet,然后使用 URL http://localhost:8080/CurrentDate调用这个 servlet 。您将收到以下结果 –

Display Current Date & Time
Mon 2010.06.21 at 10:06:44 PM GMT+04:00

简单的 DateFormat 格式代码

要指定时间格式,请使用时间模式字符串。在此模式中,所有 ASCII 字母都保留为模式字母,定义如下 –

CharacterDescriptionExample
GEra designatorAD
yYear in four digits2001
MMonth in yearJuly or 07
dDay in month0
hHour in A.M./P.M. (1~12)2
HHour in day (0~23)22
mMinute in hour30
sSecond in minute55
SMillisecond234
EDay in weekTuesday
DDay in year360
FDay of week in month2 (second Wed. in July)
wWeek in year40
WWeek in month
aA.M./P.M. markerPM
kHour in day (1~24)24
KHour in A.M./P.M. (0~11)0
zTime zoneEastern Standard Time
Escape for textDelimiter
Single quote`

有关操作日期的常量可用方法的完整列表,您可以参考标准 Java 文档。

JSP – 页面重定向

在本章中,我们将讨论使用 JSP 进行页面重定向。页面重定向一般用在文档移动到一个新位置,我们需要将客户端发送到这个新位置的时候。这可能是因为负载平衡,或者是为了简单的随机化。

将请求重定向到另一个页面的最简单方法是使用响应对象的sendRedirect()方法。以下是此方法的签名 –

public void response.sendRedirect(String location)
throws IOException 

此方法将响应连同状态代码和新页面位置一起发送回浏览器。您还可以一起使用setStatus()setHeader()方法来实现相同的重定向示例 –

....
String site = "http://www.newpage.com" ;
response.setStatus(response.SC_MOVED_TEMPORARILY);
response.setHeader("Location", site); 
....

例子

此示例显示 JSP 如何执行页面重定向到另一个位置 –

<%@ page import = "java.io.*,java.util.*" %>

<html>
   <head>
      <title>Page Redirection</title>
   </head>
   
   <body>
      <center>
         <h1>Page Redirection</h1>
      </center>
      <%
         // New location to be redirected
         String site = new String("http://www.photofuntoos.com");
         response.setStatus(response.SC_MOVED_TEMPORARILY);
         response.setHeader("Location", site); 
      %>
   </body>
</html>

现在让我们将上述代码放入 PageRedirect.jsp 并使用 URL http://localhost:8080/PageRedirect.jsp调用此 JSP 。这会将您带到给定的 URL http://www.photofuntoos.com

JSP——点击计数器

在本章中,我们将讨论 JSP 中的 Hits Counter。点击计数器告诉您网站特定页面的访问次数。通常假设人们首先登陆您的主页,您会在 index.jsp 页面上附加一个点击计数器。

要实现命中计数器,您可以使用 Application Implicit 对象和关联方法getAttribute()setAttribute()

此对象是 JSP 页面在其整个生命周期中的表示。该对象在 JSP 页面初始化时创建,并在通过jspDestroy()方法删除 JSP 页面时删除。

以下是在应用程序级别设置变量的语法 –

application.setAttribute(String Key, Object Value);

您可以使用上述方法设置点击计数器变量并重置同一个变量。以下是读取前面方法设置的变量的方法 –

application.getAttribute(String Key);

每次用户访问您的页面时,您都可以读取点击计数器的当前值并将其加一,然后再次设置它以备将来使用。

例子

此示例说明如何使用 JSP 计算特定页面上的总点击次数。如果您想计算网站的总点击次数,则必须在所有 JSP 页面中包含相同的代码。

<%@ page import = "java.io.*,java.util.*" %>

<html>
   <head>
      <title>Application object in JSP</title>
   </head>
   
   <body>
      <%
         Integer hitsCount = (Integer)application.getAttribute("hitCounter");
         if( hitsCount ==null || hitsCount == 0 ) {
            /* First visit */
            out.println("Welcome to my website!");
            hitsCount = 1;
         } else {
            /* return visit */
            out.println("Welcome back to my website!");
            hitsCount += 1;
         }
         application.setAttribute("hitCounter", hitsCount);
      %>
      <center>
         <p>Total number of visits: <%= hitsCount%></p>
      </center>
   
   </body>
</html>

现在让我们将上面的代码放在main.jsp中,并使用 URL http://localhost:8080/main.jsp调用这个 JSP 。这将显示点击计数器值,该值会随着您刷新页面而增加。您可以尝试使用不同的浏览器访问该页面,您会发现点击计数器会随着每次点击而不断增加,您将收到如下结果 –

Welcome back to my website!
Total number of visits: 12

命中计数器重置

当您重新启动您的应用程序(即 Web 服务器)时,这将重置您的应用程序变量并且您的计数器将重置为零。为避免这种损失,请考虑以下几点 –

  • 定义一个具有单个计数的数据库表,假设为 hitcount。为其分配一个零值。
  • 每次命中时,阅读表格以获取命中计数的值。
  • 将 hitcount 的值增加 1 并使用新值更新表。
  • 将 hitcount 的新值显示为总页面点击数。
  • 如果要计算所有页面的点击次数,请为所有页面实现上述逻辑。

JSP——自动刷新

在本章中,我们将讨论 JSP 中的自动刷新。考虑一个显示实时游戏比分或股票市场状态或货币汇率的网页。对于所有此类页面,您需要使用浏览器的刷新或重新加载按钮定期刷新您的网页。

JSP 通过为您提供一种机制使这项工作变得简单,您可以在该机制中以在给定时间间隔后自动刷新的方式制作网页。

刷新网页的最简单方法是使用响应对象的setIntHeader()方法。以下是此方法的签名 –

public void setIntHeader(String header, int headerValue)

此方法将标头“Refresh”连同指示时间间隔(以秒为单位)的整数值发送回浏览器。

自动页面刷新示例

在下面的示例中,我们将使用setIntHeader()方法来设置刷新标头。这将有助于模拟数字时钟 –

<%@ page import = "java.io.*,java.util.*" %>

<html>
   <head>
      <title>Auto Refresh Header Example</title>
   </head>
   
   <body>
      <center>
         <h2>Auto Refresh Header Example</h2>
         <%
            // Set refresh, autoload time as 5 seconds
            response.setIntHeader("Refresh", 5);
            
            // Get current time
            Calendar calendar = new GregorianCalendar();
            String am_pm;
            
            int hour = calendar.get(Calendar.HOUR);
            int minute = calendar.get(Calendar.MINUTE);
            int second = calendar.get(Calendar.SECOND);
            
            if(calendar.get(Calendar.AM_PM) == 0)
               am_pm = "AM";
            else
               am_pm = "PM";
            String CT = hour+":"+ minute +":"+ second +" "+ am_pm;
            out.println("Crrent Time: " + CT + "\n");
         %>
      </center>
   
   </body>
</html>

现在将上面的代码放到main.jsp中,尝试访问它。这将每隔 5 秒显示一次当前系统时间,如下所示。只需运行 JSP 并等待查看结果 –

Auto Refresh Header Example
Current Time is: 9:44:50 PM

JSP – 发送电子邮件

在本章中,我们将讨论如何使用 JSP 发送电子邮件。要使用 JSP 发送电子邮件,您应该在计算机上安装JavaMail APIJava Activation Framework (JAF)

在新创建的顶级目录中下载并解压缩这些文件。您会发现这两个应用程序的许多 jar 文件。您需要在 CLASSPATH中添加mail.jaractivation.jar文件。

发送简单的电子邮件

这是一个从您的机器发送简单电子邮件的示例。假定您的localhost已连接到 Internet,并且它有足够的能力发送电子邮件。确保来自 Java Email API 包和 JAF 包的所有 jar 文件在 CLASSPATH 中可用。

<%@ page import = "java.io.*,java.util.*,javax.mail.*"%>
<%@ page import = "javax.mail.internet.*,javax.activation.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>

<%
   String result;
   
   // Recipient's email ID needs to be mentioned.
   String to = "abcd@gmail.com";

   // Sender's email ID needs to be mentioned
   String from = "mcmohd@gmail.com";

   // Assuming you are sending email from localhost
   String host = "localhost";

   // Get system properties object
   Properties properties = System.getProperties();

   // Setup mail server
   properties.setProperty("mail.smtp.host", host);

   // Get the default Session object.
   Session mailSession = Session.getDefaultInstance(properties);

   try {
      // Create a default MimeMessage object.
      MimeMessage message = new MimeMessage(mailSession);
      
      // Set From: header field of the header.
      message.setFrom(new InternetAddress(from));
      
      // Set To: header field of the header.
      message.addRecipient(Message.RecipientType.TO,
                               new InternetAddress(to));
      // Set Subject: header field
      message.setSubject("This is the Subject Line!");
      
      // Now set the actual message
      message.setText("This is actual message");
      
      // Send message
      Transport.send(message);
      result = "Sent message successfully....";
   } catch (MessagingException mex) {
      mex.printStackTrace();
      result = "Error: unable to send message....";
   }
%>

<html>
   <head>
      <title>Send Email using JSP</title>
   </head>
   
   <body>
      <center>
         <h1>Send Email using JSP</h1>
      </center>
      
      <p align = "center">
         <% 
            out.println("Result: " + result + "\n");
         %>
      </p>
   </body>
</html>

现在让我们将上面的代码放在SendEmail.jsp文件中,并使用 URL http://localhost:8080/SendEmail.jsp调用这个 JSP 。这将有助于向给定的电子邮件 ID abcd@gmail.com发送电子邮件。您将收到以下回复 –

Send Email using JSP
Result: Sent message successfully....

如果您想向多个收件人发送电子邮件,请使用以下方法指定多个电子邮件 ID –

void addRecipients(Message.RecipientType type, Address[] addresses)
throws MessagingException

这是参数的描述 –

  • type – 这将设置为 TO、CC 或 BCC。这里的 CC 代表 Carbon Copy,BCC 代表 Black Carbon Copy。示例Message.RecipientType.TO
  • 地址– 这是电子邮件 ID 的数组。在指定电子邮件 ID 时,您需要使用 InternetAddress() 方法

发送 HTML 电子邮件

以下是从您的机器发送 HTML 电子邮件的示例。假定您的localhost已连接到 Internet,并且它有足够的能力发送电子邮件。确保来自Java Email API 包JAF 包的所有 jar 文件在 CLASSPATH 中可用。

这个例子与上一个例子非常相似,只是这里我们使用setContent()方法来设置第二个参数为“text/html”的内容,以指定消息中包含 HTML 内容。

使用此示例,您可以根据需要发送尽可能大的 HTML 内容。

<%@ page import = "java.io.*,java.util.*,javax.mail.*"%>
<%@ page import = "javax.mail.internet.*,javax.activation.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>

<%
   String result;
   
   // Recipient's email ID needs to be mentioned.
   String to = "abcd@gmail.com";

   // Sender's email ID needs to be mentioned
   String from = "mcmohd@gmail.com";

   // Assuming you are sending email from localhost
   String host = "localhost";

   // Get system properties object
   Properties properties = System.getProperties();

   // Setup mail server
   properties.setProperty("mail.smtp.host", host);

   // Get the default Session object.
   Session mailSession = Session.getDefaultInstance(properties);

   try {
      // Create a default MimeMessage object.
      MimeMessage message = new MimeMessage(mailSession);
      
      // Set From: header field of the header.
      message.setFrom(new InternetAddress(from));
      
      // Set To: header field of the header.
      message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
      
      // Set Subject: header field
      message.setSubject("This is the Subject Line!");
     
      // Send the actual HTML message, as big as you like
      message.setContent("<h1>This is actual message</h1>", "text/html" );
      
      // Send message
      Transport.send(message);
      result = "Sent message successfully....";
   } catch (MessagingException mex) {
      mex.printStackTrace();
      result = "Error: unable to send message....";
   }
%>

<html>
   <head>
      <title>Send HTML Email using JSP</title>
   </head>

   <body>
      <center>
         <h1>Send Email using JSP</h1>
      </center>
      
      <p align = "center">
         <% 
            out.println("Result: " + result + "\n");
         %>
      </p>
   </body>
</html>

现在让我们使用上面的 JSP 在给定的电子邮件 ID 上发送 HTML 消息。

在电子邮件中发送附件

以下是从您的机器发送带有附件的电子邮件的示例 –

<%@ page import = "java.io.*,java.util.*,javax.mail.*"%>
<%@ page import = "javax.mail.internet.*,javax.activation.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>

<%
   String result;
   
   // Recipient's email ID needs to be mentioned.
   String to = "abcd@gmail.com";

   // Sender's email ID needs to be mentioned
   String from = "mcmohd@gmail.com";

   // Assuming you are sending email from localhost
   String host = "localhost";

   // Get system properties object
   Properties properties = System.getProperties();

   // Setup mail server
   properties.setProperty("mail.smtp.host", host);

   // Get the default Session object.
   Session mailSession = Session.getDefaultInstance(properties);

   try {
      // Create a default MimeMessage object.
      MimeMessage message = new MimeMessage(mailSession);

      // Set From: header field of the header.
      message.setFrom(new InternetAddress(from));

      // Set To: header field of the header.
      message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

      // Set Subject: header field
      message.setSubject("This is the Subject Line!");

      // Create the message part 
      BodyPart messageBodyPart = new MimeBodyPart();

      // Fill the message
      messageBodyPart.setText("This is message body");
      
      // Create a multipart message
      Multipart multipart = new MimeMultipart();

      // Set text message part
      multipart.addBodyPart(messageBodyPart);

      // Part two is attachment
      messageBodyPart = new MimeBodyPart();
      
      String filename = "file.txt";
      DataSource source = new FileDataSource(filename);
      messageBodyPart.setDataHandler(new DataHandler(source));
      messageBodyPart.setFileName(filename);
      multipart.addBodyPart(messageBodyPart);

      // Send the complete message parts
      message.setContent(multipart );

      // Send message
      Transport.send(message);
      String title = "Send Email";
      result = "Sent message successfully....";
   } catch (MessagingException mex) {
      mex.printStackTrace();
      result = "Error: unable to send message....";
   }
%>

<html>
   <head>
      <title>Send Attachment Email using JSP</title>
   </head>
   
   <body>
      <center>
         <h1>Send Attachment Email using JSP</h1>
      </center>
      
      <p align = "center">
         <%out.println("Result: " + result + "\n");%>
      </p>
   </body>
</html>

现在让我们运行上面的 JSP,以将文件作为附件连同给定电子邮件 ID 上的消息一起发送。

用户认证部分

如果需要向电子邮件服务器提供用户 ID 和密码以进行身份​​验证,则可以按如下方式设置这些属性 –

props.setProperty("mail.user", "myuser");
props.setProperty("mail.password", "mypwd");

其余的电子邮件发送机制将保持如上所述。

使用表单发送电子邮件

您可以使用 HTML 表单接受电子邮件参数,然后您可以使用请求对象获取所有信息,如下所示 –

String to = request.getParameter("to");
String from = request.getParameter("from");
String subject = request.getParameter("subject");
String messageText = request.getParameter("body");

获得所有信息后,您可以使用上述程序发送电子邮件。

JSP – 标准标签库 (JSTL) 教程

在本章中,我们将了解 JSP 中的不同标记。JavaServer Pages 标准标记库 (JSTL) 是一组有用的 JSP 标记,它封装了许多 JSP 应用程序共有的核心功能。

JSTL 支持常见的结构化任务,例如迭代和条件、用于操作 XML 文档的标签、国际化标签和 SQL 标签。它还提供了一个框架,用于将现有的自定义标记与 JSTL 标记集成。

安装 JSTL 库

要开始使用 JSP 标签,您需要先安装 JSTL 库。如果您使用的是 Apache Tomcat 容器,请执行以下两个步骤 –

第 1 步- 从Apache Standard Taglib下载二进制发行版并解压缩压缩文件。

第 2 步– 要使用Jakarta Taglibs 发行版中的标准 Taglib ,只需将发行版“lib”目录中的 JAR 文件复制到应用程序的webapps\ROOT\WEB-INF\lib目录。

要使用任何库,您必须在使用该库的每个 JSP 的顶部包含一个 <taglib> 指令。

JSTL标签的分类

JSTL 标签可以根据它们的功能分为以下 JSTL 标签库组,这些标签库组可以在创建 JSP 页面时使用:

  • 核心标签
  • 格式化标签
  • SQL标签
  • XML标签
  • JSTL函数

核心标签

核心标签组是最常用的 JSTL 标签。以下是在您的 JSP 中包含 JSTL 核心库的语法 –

<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>

下表列出了核心 JSTL 标签 –

格式化标签

JSTL 格式化标签用于格式化和显示国际化网站的文本、日期、时间和数字。以下是在您的 JSP 中包含格式化库的语法 –

<%@ taglib prefix = "fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %>

下表列出了格式化 JSTL 标签 –

编号标签和描述
1个<fmt:格式编号>以特定精度或格式呈现数值。
2个<fmt:parseNumber>解析数字、货币或百分比的字符串表示形式。
3个<fmt:格式日期>使用提供的样式和模式格式化日期和/或时间。
4个<fmt:解析日期>解析日期和/或时间的字符串表示
5个<调频:捆绑>加载要由其标记主体使用的资源包。
6个<fmt:setLocale>将给定的语言环境存储在语言环境配置变量中。
7<fmt:setBundle>加载资源包并将其存储在命名范围变量或包配置变量中。
8个<调频:时区>指定嵌套在其正文中的任何时间格式化或解析操作的时区。
9<fmt:setTimeZone>将给定的时区存储在时区配置变量中
10<调频:消息>显示国际化消息。
11<fmt:请求编码>设置请求字符编码

SQL 标签

JSTL SQL 标记库提供用于与关系数据库 (RDBMS) 交互的标记,例如Oracle、mySQLMicrosoft SQL Server

以下是在 JSP 中包含 JSTL SQL 库的语法 –

<%@ taglib prefix = "sql" uri = "http://java.sun.com/jsp/jstl/sql" %>

下表列出了 SQL JSTL 标签 –

编号标签和描述
1个<sql:设置数据源>创建一个仅适用于原型制作的简单数据源
2个<sql:查询>执行在其正文中或通过 sql 属性定义的 SQL 查询。
3个<sql:更新>执行在其主体中或通过 sql 属性定义的 SQL 更新。
4个<sql:参数>将 SQL 语句中的参数设置为指定值。
5个<sql:日期参数>将 SQL 语句中的参数设置为指定的 java.util.Date 值。
6个<sql:交易>提供具有共享连接的嵌套数据库操作元素,设置为将所有语句作为一个事务执行。

XML标签

JSTL XML 标记提供了一种以 JSP 为中心的方式来创建和操作 XML 文档。以下是在 JSP 中包含 JSTL XML 库的语法。

JSTL XML 标记库具有用于与 XML 数据交互的自定义​​标记。这包括解析 XML、转换 XML 数据以及基于 XPath 表达式的流控制。

<%@ taglib prefix = "x" 
   uri = "http://java.sun.com/jsp/jstl/xml" %>

在继续这些示例之前,您需要将以下两个 XML 和 XPath 相关库复制到您的<Tomcat 安装目录>\lib –

以下是 XML JSTL 标签列表 –

编号标签和描述
1个<x:out>类似于 <%= … >,但用于 XPath 表达式。
2个
<x:parse>
用于解析通过属性或标记主体指定的 XML 数据。
3个
<x:set >
将变量设置为 XPath 表达式的值。
4个<x:if >评估测试 XPath 表达式,如果为真,则处理其主体。如果测试条件为假,主体将被忽略。
5个<x:forEach>遍历 XML 文档中的节点。
6个
<x:choose>
为互斥条件操作建立上下文的简单条件标记,由<when><otherwise>标记标记。
7
<x:when >
<choose>
的子标签,如果其表达式评估为“真”,则包含其主体。
8个
<x:otherwise >
<choose>
的子标签跟在<when>标签之后,仅当所有先验条件的计算结果为“false”时才运行。
9
<x:transform >
对 XML 文档应用 XSL 转换
10
<x:param >
转换标记一起使用以在 XSLT 样式表中设置参数

JSTL函数

JSTL 包括许多标准函数,其中大部分是常见的字符串操作函数。以下是在您的 JSP 中包含 JSTL 函数库的语法 –

<%@ taglib prefix = "fn" 
   uri = "http://java.sun.com/jsp/jstl/functions" %>

下表列出了各种 JSTL 函数 –

编号功能说明
1个fn:contains()测试输入字符串是否包含指定的子字符串。
2个fn:containsIgnoreCase()以不区分大小写的方式测试输入字符串是否包含指定的子字符串。
3个fn:endsWith()测试输入字符串是否以指定的后缀结尾。
4个fn:escapeXml()转义可解释为 XML 标记的字符。
5个fn:indexOf()返回包含指定子字符串第一次出现的字符串的索引。
6个fn:join()将数组的所有元素连接成一个字符串。
7fn:length()返回集合中的项目数,或字符串中的字符数。
8个fn:replace()返回用给定字符串替换输入字符串中所有出现的结果的字符串。
9fn:split()将字符串拆分为子字符串数组。
10fn:startsWith()测试输入字符串是否以指定前缀开头。
11fn:substring()返回字符串的子集。
12fn:substringAfter()返回特定子字符串之后的字符串子集。
13fn:substringBefore()返回特定子字符串之前的字符串子集。
14fn:toLowerCase()将字符串的所有字符转换为小写。
15fn:toUpperCase()将字符串的所有字符转换为大写。
16fn:trim()删除字符串两端的空格。

JSP——数据库访问

在本章中,我们将讨论如何使用 JSP 访问数据库。我们假设您对 JDBC 应用程序的工作原理有很好的理解。在开始通过 JSP 访问数据库之前,请确保您已正确设置 JDBC 环境以及数据库。

有关如何使用 JDBC 访问数据库及其环境设置的更多详细信息,您可以阅读我们的JDBC 教程。

从基本概念开始,让我们创建一个表并在该表中创建一些记录,如下所示 –

创建表

要在 EMP 数据库中创建Employees表,请使用以下步骤 –

步骤1

打开命令提示符并更改为安装目录,如下所示 –

C:\>
C:\>cd Program Files\MySQL\bin
C:\Program Files\MySQL\bin>

第2步

登录数据库如下 –

C:\Program Files\MySQL\bin>mysql -u root -p
Enter password: ********
mysql>

步骤 3

在TEST数据库中创建Employee表如下 – –

mysql> use TEST;
mysql> create table Employees
   (
      id int not null,
      age int not null,
      first varchar (255),
      last varchar (255)
   );
Query OK, 0 rows affected (0.08 sec)
mysql>

创建数据记录

现在让我们在Employee表中创建一些记录如下 – –

mysql> INSERT INTO Employees VALUES (100, 18, 'Zara', 'Ali');
Query OK, 1 row affected (0.05 sec)
 
mysql> INSERT INTO Employees VALUES (101, 25, 'Mahnaz', 'Fatma');
Query OK, 1 row affected (0.00 sec)
 
mysql> INSERT INTO Employees VALUES (102, 30, 'Zaid', 'Khan');
Query OK, 1 row affected (0.00 sec)
 
mysql> INSERT INTO Employees VALUES (103, 28, 'Sumit', 'Mittal');
Query OK, 1 row affected (0.00 sec)
 
mysql>

选择操作

以下示例显示了我们如何在 JSP 编程中使用 JTSL执行SQL SELECT语句 –

<%@ page import = "java.io.*,java.util.*,java.sql.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix = "c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix = "sql"%>
 
<html>
   <head>
      <title>SELECT Operation</title>
   </head>

   <body>
      <sql:setDataSource var = "snapshot" driver = "com.mysql.jdbc.Driver"
         url = "jdbc:mysql://localhost/TEST"
         user = "root"  password = "pass123"/>
 
      <sql:query dataSource = "${snapshot}" var = "result">
         SELECT * from Employees;
      </sql:query>
 
      <table border = "1" width = "100%">
         <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
         </tr>
         
         <c:forEach var = "row" items = "${result.rows}">
            <tr>
               <td><c:out value = "${row.id}"/></td>
               <td><c:out value = "${row.first}"/></td>
               <td><c:out value = "${row.last}"/></td>
               <td><c:out value = "${row.age}"/></td>
            </tr>
         </c:forEach>
      </table>
 
   </body>
</html>

访问上面的 JSP,将显示以下结果 –

Emp IDFirst NameLast NameAge100ZaraAli18101MahnazFatma25102ZaidKhan30103SumitMittal28

插入操作

以下示例显示了我们如何在 JSP 编程中使用 JTSL 执行 SQL INSERT 语句 –

<%@ page import = "java.io.*,java.util.*,java.sql.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix = "c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix = "sql"%>
 
<html>
   <head>
      <title>JINSERT Operation</title>
   </head>
   
   <body>
      <sql:setDataSource var = "snapshot" driver = "com.mysql.jdbc.Driver"
         url = "jdbc:mysql://localhost/TEST"
         user = "root"  password = "pass123"/>
         <sql:update dataSource = "${snapshot}" var = "result">
         INSERT INTO Employees VALUES (104, 2, 'Nuha', 'Ali');
      </sql:update>
 
      <sql:query dataSource = "${snapshot}" var = "result">
         SELECT * from Employees;
      </sql:query>
 
      <table border = "1" width = "100%">
         <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
         </tr>
         
         <c:forEach var = "row" items = "${result.rows}">
            <tr>
               <td><c:out value = "${row.id}"/></td>
               <td><c:out value = "${row.first}"/></td>
               <td><c:out value = "${row.last}"/></td>
               <td><c:out value = "${row.age}"/></td>
            </tr>
         </c:forEach>
      </table>
 
   </body>
</html>

访问上面的 JSP,将显示以下结果 –

Emp IDFirst NameLast NameAge100ZaraAli18101MahnazFatma25102ZaidKhan30103SumitMittal28104NuhaAli2

删除操作

以下示例显示了我们如何在 JSP 编程中使用 JTSL执行SQL DELETE语句 –

<%@ page import = "java.io.*,java.util.*,java.sql.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix = "c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix = "sql"%>
 
<html>
   <head>
      <title>DELETE Operation</title>
   </head>
   
   <body>
      <sql:setDataSource var = "snapshot" driver = "com.mysql.jdbc.Driver"
         url = "jdbc:mysql://localhost/TEST"
         user = "root" password = "pass123"/>
 
      <c:set var = "empId" value = "103"/>
 
      <sql:update dataSource = "${snapshot}" var = "count">
         DELETE FROM Employees WHERE Id = ?
         <sql:param value = "${empId}" />
      </sql:update>
 
      <sql:query dataSource = "${snapshot}" var = "result">
         SELECT * from Employees;
      </sql:query>
 
      <table border = "1" width = "100%">
         <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
         </tr>
            
         <c:forEach var = "row" items = "${result.rows}">
            <tr>
               <td><c:out value = "${row.id}"/></td>
               <td><c:out value = "${row.first}"/></td>
               <td><c:out value = "${row.last}"/></td>
               <td><c:out value = "${row.age}"/></td>
            </tr>
         </c:forEach>
      </table>
 
   </body>
</html>

访问上面的 JSP,将显示以下结果 –

Emp IDFirst NameLast NameAge100ZaraAli18101MahnazFatma25102ZaidKhan30

更新操作

以下示例显示了我们如何在 JSP 编程中使用 JTSL执行SQL UPDATE语句 –

<%@ page import = "java.io.*,java.util.*,java.sql.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c"%>
<%@ taglib uri = "http://java.sun.com/jsp/jstl/sql" prefix = "sql"%>
 
<html>
   <head>
      <title>DELETE Operation</title>
   </head>
   
   <body>
      <sql:setDataSource var = "snapshot" driver = "com.mysql.jdbc.Driver"
         url = "jdbc:mysql://localhost/TEST"
         user = "root" password = "pass123"/>
 
      <c:set var = "empId" value = "102"/>
 
      <sql:update dataSource = "${snapshot}" var = "count">
         UPDATE Employees SET WHERE last = 'Ali'
         <sql:param value = "${empId}" />
      </sql:update>
 
      <sql:query dataSource = "${snapshot}" var = "result">
         SELECT * from Employees;
      </sql:query>
 
      <table border = "1" width = "100%">
         <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
         </tr>
            
         <c:forEach var = "row" items = "${result.rows}">
            <tr>
               <td><c:out value = "${row.id}"/></td>
               <td><c:out value = "${row.first}"/></td>
               <td><c:out value = "${row.last}"/></td>
               <td><c:out value = "${row.age}"/></td>
            </tr>
         </c:forEach>
      </table>
 
   </body>
</html>

访问上面的 JSP,将显示以下结果 –

Emp IDFirst NameLast NameAge100ZaraAli18101MahnazFatma25102ZaidAli30

JSP-XML 数据

当您通过 HTTP 发送 XML 数据时,使用 JSP 处理传入和传出的 XML 文档是有意义的;例如,RSS 文档。由于 XML 文档只是一堆文本,因此通过 JSP 创建一个文档比创建 HTML 文档要容易得多。

从 JSP 发送 XML

您可以像发送 HTML 一样使用 JSP 发送 XML 内容。唯一的区别是您必须将页面的内容类型设置为文本/xml。要设置内容类型,请使用<%@page%>标签,如下所示 –

<%@ page contentType = "text/xml" %>

以下示例将展示如何将 XML 内容发送到浏览器 –

<%@ page contentType = "text/xml" %>

<books>
   <book>
      <name>Padam History</name>
      <author>ZARA</author>
      <price>100</price>
   </book>
</books>

使用不同的浏览器访问上面的XML,可以看到上面XML的文档树展示。

在 JSP 中处理 XML

在使用 JSP 继续进行 XML 处理之前,您需要将以下两个 XML 和 XPath 相关库复制到您的<Tomcat 安装目录>\lib –

让我们将以下内容放入 books.xml 文件中 –

<books>
   <book>
      <name>Padam History</name>
      <author>ZARA</author>
      <price>100</price>
   </book>
   
   <book>
      <name>Great Mistry</name>
      <author>NUHA</author>
      <price>2000</price>
   </book>
</books>

尝试以下main.jsp,保持在同一目录中 –

<%@ taglib prefix = "c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix = "x" uri="http://java.sun.com/jsp/jstl/xml" %>
 
<html>
   <head>
      <title>JSTL x:parse Tags</title>
   </head>

   <body>
      <h3>Books Info:</h3>
      <c:import var = "bookInfo" url="http://localhost:8080/books.xml"/>
 
      <x:parse xml = "${bookInfo}" var = "output"/>
      <b>The title of the first book is</b>: 
      <x:out select = "$output/books/book[1]/name" />
      <br>
      
      <b>The price of the second book</b>: 
      <x:out select = "$output/books/book[2]/price" />
   </body>
</html>

使用http://localhost:8080/main.jsp访问上述 JSP ,将显示以下结果 –

Books Info:
The title of the first book is:Padam History

The price of the second book: 2000

使用 JSP 格式化 XML

考虑以下 XSLT 样式表style.xsl –

<?xml version = "1.0"?>
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" 
   version = "1.0">
 
   <xsl:output method = "html" indent = "yes"/>
   <xsl:template match = "/">
      <html>
         <body>
            <xsl:apply-templates/>
         </body>
      </html>
   </xsl:template>
    
   <xsl:template match = "books">
      <table border = "1" width = "100%">
         <xsl:for-each select = "book">
            <tr>
               <td>
                  <i><xsl:value-of select = "name"/></i>
               </td>
               
               <td>
                  <xsl:value-of select = "author"/>
               </td>
               
               <td>
                  <xsl:value-of select = "price"/>
               </td>
            </tr>
         </xsl:for-each>
      </table>
   
   </xsl:template>
</xsl:stylesheet>

现在考虑以下 JSP 文件 –

<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix = "x" uri = "http://java.sun.com/jsp/jstl/xml" %>
 
<html>
   <head>
      <title>JSTL x:transform Tags</title>
   </head>
   
   <body>
      <h3>Books Info:</h3>
      <c:set var = "xmltext">
         <books>
            <book>
               <name>Padam History</name>
               <author>ZARA</author>
               <price>100</price>
            </book>
            
            <book>
               <name>Great Mistry</name>
               <author>NUHA</author>
               <price>2000</price>
            </book>
         </books>
      </c:set>
 
      <c:import url = "http://localhost:8080/style.xsl" var = "xslt"/>
      <x:transform xml = "${xmltext}" xslt = "${xslt}"/>
   </body>
</html>

将显示以下结果 –

Books Info:
Padam HistoryZARA100Great MistryNUHA2000

要了解有关使用 JSTL 进行 XML 处理的更多信息,您可以查看JSP Standard Tag Library。

JSP——JavaBeans

JavaBean 是用 Java 编写并根据 JavaBeans API 规范编码的特殊构造的 Java 类。

以下是将 JavaBean 与其他 Java 类区分开来的独特特征 –

  • 它提供了一个默认的、无参数的构造函数。
  • 它应该是可序列化的,并且可以实现Serializable接口。
  • 它可能具有许多可以读取或写入的属性。
  • 它可能有许多属性的“ getter ”和“ setter ”方法。

JavaBeans 属性

JavaBean 属性是对象的用户可以访问的命名属性。该属性可以是任何 Java 数据类型,包括您定义的类。

JavaBean 属性可以是读、写、只读只写。通过 JavaBean 实现类中的两种方法访问 JavaBean 属性 –

编号方法及说明
1个getPropertyName()
例如,如果属性名称是firstName,您的方法名称将是getFirstName()以读取该属性。此方法称为访问器。
2个setPropertyName()
例如,如果属性名称是firstName,则您的方法名称将是setFirstName()以写入该属性。这种方法称为增变器。

只读属性只有getPropertyName()方法,而只写属性只有setPropertyName()方法。

JavaBeans 示例

考虑一个几乎没有属性的学生班级 –

package com.tutorialspoint;

public class StudentsBean implements java.io.Serializable {
   private String firstName = null;
   private String lastName = null;
   private int age = 0;

   public StudentsBean() {
   }
   public String getFirstName(){
      return firstName;
   }
   public String getLastName(){
      return lastName;
   }
   public int getAge(){
      return age;
   }
   public void setFirstName(String firstName){
      this.firstName = firstName;
   }
   public void setLastName(String lastName){
      this.lastName = lastName;
   }
   public void setAge(Integer age){
      this.age = age;
   }
}

访问 JavaBean

useBean操作声明一个 JavaBean 以在 JSP 中使用。一旦声明,bean 就成为一个脚本变量,它可以被 JSP 中使用的脚本元素和其他自定义标记访问。useBean 标签的完整语法如下:

<jsp:useBean id = "bean's name" scope = "bean's scope" typeSpec/>

根据您的要求,范围属性的值可以是页面、请求、会话应用程序id属性的值可以是任何值,只要它是同一 JSP中其他useBean 声明中的唯一名称即可。

以下示例显示了如何使用 useBean 操作 –

<html>
   <head>
      <title>useBean Example</title>
   </head>
   
   <body>
      <jsp:useBean id = "date" class = "java.util.Date" /> 
      <p>The date/time is <%= date %>
   </body>
</html>

您将收到以下结果 – –

The date/time is Thu Sep 30 11:18:11 GST 2010 

访问 JavaBeans 属性

<jsp:useBean…>操作一起,您可以使用<jsp:getProperty/>操作来访问 get 方法,使用<jsp:setProperty/>操作来访问 set 方法。这是完整的语法 –

<jsp:useBean id = "id" class = "bean's class" scope = "bean's scope">
   <jsp:setProperty name = "bean's id" property = "property name"  
      value = "value"/>
   <jsp:getProperty name = "bean's id" property = "property name"/>
   ...........
</jsp:useBean>

name 属性引用先前由 useBean 操作引入到 JSP 的 JavaBean 的 id。property 属性是应该调用的getset方法的名称。

以下示例显示了如何使用上述语法访问数据 –

<html>
   <head>
      <title>get and set properties Example</title>
   </head>
   
   <body>
      <jsp:useBean id = "students" class = "com.tutorialspoint.StudentsBean"> 
         <jsp:setProperty name = "students" property = "firstName" value = "Zara"/>
         <jsp:setProperty name = "students" property = "lastName" value = "Ali"/>
         <jsp:setProperty name = "students" property = "age" value = "10"/>
      </jsp:useBean>

      <p>Student First Name: 
         <jsp:getProperty name = "students" property = "firstName"/>
      </p>
      
      <p>Student Last Name: 
         <jsp:getProperty name = "students" property = "lastName"/>
      </p>
      
      <p>Student Age: 
         <jsp:getProperty name = "students" property = "age"/>
      </p>

   </body>
</html>

让我们在 CLASSPATH 中提供StudentsBean.class 。访问上面的 JSP。将显示以下结果 –

Student First Name: Zara 

Student Last Name: Ali 

Student Age: 10 

JSP – 自定义标记

在本章中,我们将讨论 JSP 中的自定义标签。自定义标记是用户定义的 JSP 语言元素。当包含自定义标记的 JSP 页面被转换为 servlet 时,标记被转换为对称为标记处理程序的对象的操作。然后,当 JSP 页面的 servlet 被执行时,Web 容器调用这些操作。

JSP 标记扩展允许您创建可以直接插入到 JavaServer Page 中的新标记。JSP 2.0 规范引入了用于编写这些自定义标记的简单标记处理程序。

要编写自定义标签,您可以简单地扩展SimpleTagSupport类并覆盖doTag()方法,您可以在其中放置代码来为标签生成内容。

创建“Hello”标签

假设您想定义一个名为 <ex:Hello> 的自定义标签,并且您希望在没有主体的情况下以下列方式使用它 –

<ex:Hello />

要创建自定义 JSP 标记,您必须首先创建一个用作标记处理程序的 Java 类。现在让我们创建HelloTag类如下:

package com.tutorialspoint;

import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.*;

public class HelloTag extends SimpleTagSupport {
   public void doTag() throws JspException, IOException {
      JspWriter out = getJspContext().getOut();
      out.println("Hello Custom Tag!");
   }
}

上面的代码具有简单的编码,其中doTag()方法使用getJspContext()方法获取当前 JspContext 对象,并使用它发送“Hello Custom Tag!” 到当前的JspWriter对象

让我们编译上面的类并将其复制到环境变量 CLASSPATH 中可用的目录中。最后,创建以下标记库文件:<Tomcat-Installation-Directory>webapps\ROOT\WEB-INF\custom.tld

<taglib>
   <tlib-version>1.0</tlib-version>
   <jsp-version>2.0</jsp-version>
   <short-name>Example TLD</short-name>
   
   <tag>
      <name>Hello</name>
      <tag-class>com.tutorialspoint.HelloTag</tag-class>
      <body-content>empty</body-content>
   </tag>
</taglib>

现在让我们在我们的 JSP 程序中使用上面定义的自定义标签Hello,如下所示 –

<%@ taglib prefix = "ex" uri = "WEB-INF/custom.tld"%>

<html>
   <head>
      <title>A sample custom tag</title>
   </head>
   
   <body>
      <ex:Hello/>
   </body>
</html>

调用上面的 JSP,这应该会产生以下结果 –

Hello Custom Tag!

访问标签体

您可以像在标准标签中看到的那样在标签正文中包含一条消息。假设您想定义一个名为<ex:Hello>的自定义标签,并且您希望以以下方式将其与正文一起使用 –

<ex:Hello>
   This is message body
</ex:Hello>

让我们对上述标签代码进行以下更改以处理标签的主体 –

package com.tutorialspoint;

import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.*;

public class HelloTag extends SimpleTagSupport {
   StringWriter sw = new StringWriter();
   public void doTag()
   
   throws JspException, IOException {
      getJspBody().invoke(sw);
      getJspContext().getOut().println(sw.toString());
   }
}

在这里,调用产生的输出首先被捕获到StringWriter中,然后再写入与标记关联的 JspWriter。我们需要按如下方式更改 TLD 文件 –

<taglib>
   <tlib-version>1.0</tlib-version>
   <jsp-version>2.0</jsp-version>
   <short-name>Example TLD with Body</short-name>
   
   <tag>
      <name>Hello</name>
      <tag-class>com.tutorialspoint.HelloTag</tag-class>
      <body-content>scriptless</body-content>
   </tag>
</taglib>

现在让我们用适当的主体调用上面的标签如下 –

<%@ taglib prefix = "ex" uri = "WEB-INF/custom.tld"%>

<html>
   <head>
      <title>A sample custom tag</title>
   </head>
   
   <body>
      <ex:Hello>
         This is message body
      </ex:Hello>
   </body>
</html>

您将收到以下结果 –

This is message body

自定义标签属性

您可以将各种属性与自定义标签一起使用。要接受属性值,自定义标记类需要实现setter方法,与 JavaBean setter 方法相同,如下所示 –

package com.tutorialspoint;

import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.*;

public class HelloTag extends SimpleTagSupport {
   private String message;

   public void setMessage(String msg) {
      this.message = msg;
   }
   StringWriter sw = new StringWriter();
   public void doTag()
   
   throws JspException, IOException {
      if (message != null) {
         /* Use message from attribute */
         JspWriter out = getJspContext().getOut();
         out.println( message );
      } else {
         /* use message from the body */
         getJspBody().invoke(sw);
         getJspContext().getOut().println(sw.toString());
      }
   }
}

属性的名称是“message”,所以 setter 方法是setMessage()现在让我们使用<attribute>元素在 TLD 文件中添加这个属性,如下所示 –

<taglib>
   <tlib-version>1.0</tlib-version>
   <jsp-version>2.0</jsp-version>
   <short-name>Example TLD with Body</short-name>
   
   <tag>
      <name>Hello</name>
      <tag-class>com.tutorialspoint.HelloTag</tag-class>
      <body-content>scriptless</body-content>
      
      <attribute>
         <name>message</name>
      </attribute>
   
   </tag>
</taglib>

让我们跟随带有消息属性的 JSP 如下 –

<%@ taglib prefix = "ex" uri = "WEB-INF/custom.tld"%>

<html>
   <head>
      <title>A sample custom tag</title>
   </head>
   
   <body>
      <ex:Hello message = "This is custom tag" />
   </body>
</html>

这将产生以下结果 –

This is custom tag

考虑为属性包括以下属性 –

编号财产及用途
1个name
name 元素定义属性的名称。每个属性名称对于特定标记必须是唯一的。
2个required
这指定此属性是必需的还是可选的。对于可选的,这将是错误的。
3个rtexprvalue
声明标记属性的运行时表达式值是否有效
4个type定义此属性的 Java 类类型。默认情况下,它被假定为String
5个description
可以提供信息描述。
6个fragment
声明此属性值是否应被视为JspFragment

以下是指定与属性相关的属性的示例 –

.....
   <attribute>
      <name>attribute_name</name>
      <required>false</required>
      <type>java.util.Date</type>
      <fragment>false</fragment>
   </attribute>
.....

如果您使用两个属性,那么您可以按如下方式修改您的 TLD –

.....
   <attribute>
      <name>attribute_name1</name>
      <required>false</required>
      <type>java.util.Boolean</type>
      <fragment>false</fragment>
   </attribute>
   
   <attribute>
      <name>attribute_name2</name>
      <required>true</required>
      <type>java.util.Date</type>
   </attribute>
.....

JSP – 表达语言 (EL)

JSP 表达式语言 (EL) 使访问存储在 JavaBeans 组件中的应用程序数据成为可能。JSP EL 允许您创建(a)算术和(b)逻辑表达式。在 JSP EL 表达式中,您可以使用整数、浮点数、字符串、用于布尔值的内置常量 true 和 false,以及 null。

语法简单

通常,当您在 JSP 标记中指定一个属性值时,您只需使用一个字符串。例如 –

<jsp:setProperty name = "box" property = "perimeter" value = "100"/>

JSP EL 允许您为这些属性值中的任何一个指定一个表达式。JSP EL 的简单语法如下:

${expr}

这里expr指定表达式本身。JSP EL 中最常见的运算符是[]。这两个运算符允许您访问 Java Beans 和内置 JSP 对象的各种属性。

例如,上面的语法<jsp:setProperty>标签可以写成这样的表达式 –

<jsp:setProperty name = "box" property = "perimeter" 
   value = "${2*box.width+2*box.height}"/>

当 JSP 编译器在属性中看到${}形式时,它会生成代码来评估表达式并替换 expresson 的值。

您还可以在标记的模板文本中使用 JSP EL 表达式。例如,<jsp:text>标记只是将其内容插入到 JSP 主体中。以下<jsp:text>声明将<h1>Hello JSP!</h1>插入到 JSP 输出中 –

<jsp:text>
   <h1>Hello JSP!</h1>
</jsp:text>

您现在可以在<jsp:text>标记(或任何其他标记)的主体中包含一个 JSP EL 表达式,其语法与用于属性的${}语法相同。例如 –

<jsp:text>
   Box Perimeter is: ${2*box.width + 2*box.height}
</jsp:text>

EL 表达式可以使用括号来对子表达式进行分组。例如,${(1 + 2) * 3} 等于 9,但 ${1 + (2 * 3)} 等于 7

要停用 EL 表达式的评估,我们指定页面指令的isELIgnored属性如下 –

<%@ page isELIgnored = "true|false" %>

此属性的有效值为 true 和 false。如果为真,则 EL 表达式出现在静态文本或标记属性中时将被忽略。如果为 false,则 EL 表达式由容器求值。

EL 中的基本运算符

JSP 表达式语言 (EL) 支持 Java 支持的大多数算术和逻辑运算符。下表列出了最常用的运算符 –

编号运算符和描述
1个.
访问 bean 属性或 Map 条目
2个[]
访问数组或列表元素
3个( )
对子表达式进行分组以更改求值顺序
4个+
添加
5个
一个值的减法或取反
6个*
乘法
7/ or div
分配
8个% or mod
模(余数)
9== or eq
平等测试
10!= or ne
测试不平等
11< or lt
测试小于
12> or gt
测试大于
13<= or le
测试小于或等于
14>= or ge
测试大于或等于
15&& or and
测试逻辑与
16|| or or
测试逻辑或
17! or not
一元布尔补码
18empty
测试空变量值

JSP EL 中的函数

JSP EL 还允许您在表达式中使用函数。这些函数必须在自定义标签库中定义。函数用法具有以下语法 –

${ns:func(param1, param2, ...)}

其中ns是函数的命名空间,func是函数的名称,param1是第一个参数值。例如,函数fn:length,它是 JSTL 库的一部分。这个函数可以按如下方式使用来获取字符串的长度。

${fn:length("Get my length")}

要使用来自任何标记库(标准或自定义)的函数,您必须在服务器上安装该库,并且必须使用<taglib>指令将库包含在 JSP 中,如 JSTL 章节中所述。

JSP EL 隐式对象

JSP 表达式语言支持以下隐式对象 –

S.号隐式对象和描述
1个pageScope
页面范围内的范围变量
2个requestScope
来自请求范围的范围变量
3个sessionScope
会话范围内的范围变量
4个applicationScope
来自应用程序范围的范围变量
5个param
以字符串形式请求参数
6个paramValues
作为字符串集合的请求参数
7header
HTTP 请求标头作为字符串
8个headerValues
作为字符串集合的 HTTP 请求标头
9initParam
上下文初始化参数
10cookie
饼干值
11pageContext
当前页面的 JSP PageContext 对象

您可以在表达式中使用这些对象,就好像它们是变量一样。以下示例将帮助您理解这些概念 –

pageContext 对象

pageContext 对象使您可以访问 pageContext JSP 对象。通过 pageContext 对象,您可以访问请求对象。例如,要访问请求的传入查询字符串,您可以使用以下表达式 –

${pageContext.request.queryString}

范围对象

pageScope 、requestScope、sessionScopeapplicationScope变量提供对存储在每个范围级别的变量的访问。

例如,如果您需要在应用程序范围内显式访问 box 变量,则可以通过 applicationScope 变量访问它作为applicationScope.box

param 和 paramValues 对象

param 和 paramValues 对象使您可以访问通常可通过request.getParameterrequest.getParameterValues方法获得的参数值。

例如,要访问名为 order 的参数,请使用表达式${param.order}${param[“order”]}

以下是访问名为用户名的请求参数的示例 –

<%@ page import = "java.io.*,java.util.*" %>
<%String title = "Accessing Request Param";%>

<html>
   <head>
      <title><% out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><% out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>${param["username"]}</p>
      </div>
   </body>
</html>

param 对象返回单个字符串值,而 paramValues 对象返回字符串数组。

header 和 headerValues 对象

header 和 headerValues 对象使您可以访问通常可通过request.getHeaderrequest.getHeaders方法获得的标头值。

例如,要访问名为 user-agent 的标头,请使用表达式${header.user-agent}${header[“user-agent”]}

以下是访问名为 user-agent 的标头参数的示例 –

<%@ page import = "java.io.*,java.util.*" %>
<%String title = "User Agent Example";%>

<html>
   <head>
      <title><% out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><% out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>${header["user-agent"]}</p>
      </div>
   </body>
</html>

输出将有点像以下 –

User Agent Example
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; 
   SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; 
   Media Center PC 6.0; HPNTDF; .NET4.0C; InfoPath.2)

header 对象返回单个字符串值,而 headerValues 对象返回字符串数组。

JSP——异常处理

在这一章当中。我们将讨论如何在 JSP 中处理异常。在编写 JSP 代码时,您可能会在代码的任何部分出现编码错误。您的 JSP 代码中可能会出现以下类型的错误 –

检查异常

检查异常是一种异常,通常是用户错误或程序员无法预见的问题。比如要打开一个文件,但是找不到文件,就会出现异常。在编译时不能简单地忽略这些异常。

运行时异常

运行时异常是程序员可能已经避免的异常。与检查异常相反,运行时异常在编译时被忽略。

错误

这些根本不是异常,而是用户或程序员无法控制的问题。代码中的错误通常会被忽略,因为您很少能对错误做任何事情。例如,如果发生堆栈溢出,就会出现错误。它们在编译时也会被忽略。

我们将进一步讨论处理 JSP 代码中发生的运行时异常/错误的方法。

使用异常对象

异常对象是 Throwable 子类的一个实例(例如,java.lang.NullPointerException),并且仅在错误页面中可用。下表列出了 Throwable 类中可用的重要方法。

编号方法与说明
1个public String getMessage()
返回有关已发生异常的详细消息。此消息在 Throwable 构造函数中初始化。
2个public Throwable getCause()
返回由 Throwable 对象表示的异常原因。
3个public String toString()
返回与getMessage()结果连接的类的名称。
4个public void printStackTrace()
将toString()的结果与堆栈跟踪一起打印到错误输出流System.err
5个public StackTraceElement [] getStackTrace()
返回一个数组,其中包含堆栈跟踪中的每个元素。索引 0 处的元素表示调用堆栈的顶部,数组中的最后一个元素表示调用堆栈底部的方法。
6个public Throwable fillInStackTrace()
使用当前堆栈跟踪填充此 Throwable 对象的堆栈跟踪,添加到堆栈跟踪中的任何先前信息。

JSP 为您提供了为每个 JSP指定错误页面的选项。每当页面抛出异常时,JSP 容器都会自动调用错误页面。

以下是为main.jsp指定错误页面的示例。要设置错误页面,请使用<%@ page errorPage = “xxx” %>指令。

<%@ page errorPage = "ShowError.jsp" %>

<html>
   <head>
      <title>Error Handling Example</title>
   </head>
   
   <body>
      <%
         // Throw an exception to invoke the error page
         int x = 1;
         
         if (x == 1) {
            throw new RuntimeException("Error condition!!!");
         }
      %>
   </body>
</html>

我们现在将编写一个错误处理 JSP ShowError.jsp,如下所示。请注意,错误处理页面包含指令<%@ page isErrorPage = “true” %>。该指令使 JSP 编译器生成异常实例变量。

<%@ page isErrorPage = "true" %>

<html>
   <head>
      <title>Show Error Page</title>
   </head>
   
   <body>
      <h1>Opps...</h1>
      <p>Sorry, an error occurred.</p>
      <p>Here is the exception stack trace: </p>
      <pre><% exception.printStackTrace(response.getWriter()); %></pre>
   </body>
</html>

访问main.jsp,您将收到类似于以下内容的输出 –

java.lang.RuntimeException: Error condition!!!
......

Opps...
Sorry, an error occurred.

Here is the exception stack trace:

为错误页面使用 JSTL 标签

您可以使用 JSTL 标记来编写错误页面ShowError.jsp。这个页面的逻辑与上面的例子几乎相同,结构更好,信息更多 –

<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%@page isErrorPage = "true" %>

<html>
   <head>
      <title>Show Error Page</title>
   </head>
   
   <body>
      <h1>Opps...</h1>
      <table width = "100%" border = "1">
         <tr valign = "top">
            <td width = "40%"><b>Error:</b></td>
            <td>${pageContext.exception}</td>
         </tr>
            
         <tr valign = "top">
            <td><b>URI:</b></td>
            <td>${pageContext.errorData.requestURI}</td>
         </tr>
            
         <tr valign = "top">
            <td><b>Status code:</b></td>
            <td>${pageContext.errorData.statusCode}</td>
         </tr>
            
         <tr valign = "top">
            <td><b>Stack trace:</b></td>
            <td>
               <c:forEach var = "trace" 
                  items = "${pageContext.exception.stackTrace}">
                  <p>${trace}</p>
               </c:forEach>
            </td>
         </tr>
      </table>

   </body>
</html>

访问 main.jsp,将生成以下内容 –

Opps...
Error:java.lang.RuntimeException: Error condition!!!URI:/main.jspStatus code:500Stack trace:org.apache.jsp.main_jsp._jspService(main_jsp.java:65)org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:68)javax.servlet.http.HttpServlet.service(HttpServlet.java:722)org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

使用 Try…Catch 块

如果你想在同一个页面中处理错误并想采取一些行动而不是触发错误页面,你可以使用try….catch块。

下面是一个简单的例子,展示了如何使用 try…catch 块。让我们将以下代码放入 main.jsp –

<html>
   <head>
      <title>Try...Catch Example</title>
   </head>
   
   <body>
      <%
         try {
            int i = 1;
            i = i / 0;
            out.println("The answer is " + i);
         }
         catch (Exception e) {
            out.println("An exception occurred: " + e.getMessage());
         }
      %>
   </body>
</html>

访问 main.jsp,它应该生成类似于以下的输出 –

An exception occurred: / by zero 

JSP-调试

在本章中,我们将讨论调试 JSP。测试/调试 JSP 和 servlet 总是很困难。JSP 和 Servlets 往往涉及大量的客户端/服务器交互,这使得错误很可能发生但很难重现。

以下是一些可以帮助您进行调试的提示和建议。

使用 System.out.println()

System.out.println()很容易用作标记来测试某段代码是否正在执行。我们也可以打印出变量值。考虑以下附加点 –

  • 由于 System object 是核心 Java 对象的一部分,因此无需安装任何额外的类就可以在任何地方使用它。这包括Servlet、JSP、RMI、EJB、普通的 Bean,以及独立的应用程序
  • 与在断点处停止相比,写入System.out不会对应用程序的正常执行流程造成太大干扰,这在 iming 至关重要时非常有价值。

以下是使用System.out.println()的语法-

System.out.println("Debugging message");

以下示例显示了如何使用System.out.print() –

<%@taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>

<html>
   <head><title>System.out.println</title></head>
   <body>
      <c:forEach var = "counter" begin = "1" end = "10" step = "1" >
      
         <c:out value = "${counter-5}"/></br>
         <% System.out.println( "counter = " + pageContext.findAttribute("counter") ); %>
      </c:forEach>
      
   </body>
</html>

访问上面的 JSP,浏览器将显示以下结果 –

-4
-3
-2
-1
0
1
2
3
4
5

如果您使用的是 Tomcat,您还会发现这些行附加到日志目录中stdout.log的末尾。

counter = 1
counter = 2
counter = 3
counter = 4
counter = 5
counter = 6
counter = 7
counter = 8
counter = 9
counter = 10

通过这种方式,您可以将变量和其他信息带入系统日志中,可以对其进行分析以找出问题的根本原因或其他各种原因。

使用 JDB 记录器

J2SE日志框架旨在为运行在 JVM 中的任何类提供日志服务。我们可以利用这个框架来记录任何信息。

让我们使用 JDK 记录器 API 重写上面的例子 –

<%@taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%@page import = "java.util.logging.Logger" %>

<html>
   <head><title>Logger.info</title></head>
   
   <body>
      <% Logger logger = Logger.getLogger(this.getClass().getName());%>

      <c:forEach var = "counter" begin = "1" end = "10" step = "1" >
      <c:set var = "myCount" value = "${counter-5}" />
      <c:out value = "${myCount}"/></br>
         <% String message = "counter = "
            + pageContext.findAttribute("counter") + "myCount = "
            + pageContext.findAttribute("myCount");
            logger.info( message );
         %>
      </c:forEach>
      
   </body>
</html>

上面的代码将在浏览器和 stdout.log 中生成类似的结果,但您将在stdout.log中获得更多信息。我们将使用记录器的信息方法,因为记录消息只是为了提供信息。以下是 stdout.log 文件的快照 –

24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 1 myCount = -4
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 2 myCount = -3
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 3 myCount = -2
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 4 myCount = -1
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 5 myCount = 0
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 6 myCount = 1
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 7 myCount = 2
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 8 myCount = 3
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 9 myCount = 4
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 10 myCount = 5

可以使用便利函数severe()、warning()、info()、config()、fine()、finer()finest()在不同级别发送消息。这里 finest() 方法可以用来记录最好的信息, severe() 方法可以用来记录严重的信息。

您可以使用Log4J 框架根据消息的严重级别和重要性将消息记录在不同的文件中。

调试工具

NetBeans 是一个免费的开源 Java 集成开发环境,它支持开发支持 JSP 和 servlet 规范的独立 Java 应用程序和 Web 应用程序,还包括一个 JSP 调试器。

NetBeans 支持以下基本调试功能 –

  • 断点
  • 单步执行代码
  • 观察点

您可以参考NetBeans 文档来了解上述调试功能。

使用 JDB 调试器

您可以使用与调试 applet 或应用程序相同的jdb命令来调试 JSP 和 servlet 。

要调试 JSP 或 servlet,您可以调试sun.servlet.http.HttpServer,然后观察 HttpServer 执行 JSP/servlet 以响应我们从浏览器发出的 HTTP 请求。这与调试 applet 的方式非常相似。不同之处在于,对于小程序,被调试的实际程序是sun.applet.AppletViewer

大多数调试器通过自动知道如何调试 applet 来隐藏这个细节。在他们为 JSP 做同样的事情之前,您必须通过考虑以下内容来帮助您的调试器 –

  • 设置调试器的类路径。这有助于您找到sun.servlet.http.Http-Server和关联的类。
  • 设置调试器的类路径。这有助于您找到 JSP 和支持类,通常是ROOT\WEB-INF\classes

设置正确的类路径后,开始调试sun.servlet.http.HttpServer。您可以在您有兴趣调试的任何 JSP 中设置断点,然后使用 Web 浏览器向给定 JSP (http://localhost:8080/JSPToDebug)的 HttpServer 发出请求。这里的执行在断点处停止。

使用评论

代码中的注释可以通过多种方式帮助调试过程。注释可以在调试过程中以许多其他方式使用。

JSP 使用 Java 注释,单行 (// …)多行 (/* … */)注释可用于临时删除部分 Java 代码。如果错误消失了,请仔细查看您刚刚注释的代码并找出问题所在。

客户端和服务器标头

有时,当 JSP 未按预期运行时,查看原始 HTTP 请求和响应会很有用。如果您熟悉 HTTP 的结构,您可以阅读请求和响应并查看这些标头的确切含义。

重要调试提示

以下是关于 JSP 调试的更多调试技巧的列表 –

  • 要求浏览器显示它正在显示的页面的原始内容。这有助于识别格式问题。它通常是“查看”菜单下的一个选项。
  • 确保浏览器没有通过强制完全重新加载页面来缓存先前请求的输出。使用Netscape Navigator时,使用Shift-Reload;在Internet Explorer中使用Shift-Refresh

JSP-安全

JavaServer Pages 和 servlet 为 Web 开发人员提供了多种机制来保护应用程序。通过在应用程序部署描述符中识别资源并为其分配角色,以声明方式保护资源。

可以使用多个级别的身份验证,从使用标识符和密码的基本身份验证到使用证书的复杂身份验证。

基于角色的身份验证

servlet 规范中的身份验证机制使用了一种称为基于角色的安全性的技术。这个想法是,不是在用户级别限制资源,而是创建角色并按角色限制资源。

您可以在文件tomcat-users.xml中定义不同的角色,该文件位于 conf 中 Tomcat 的主目录之外。该文件的示例如下所示 –

<?xml version = '1.0' encoding = 'utf-8'?>
<tomcat-users>
   <role rolename = "tomcat"/>
   <role rolename = "role1"/>
   <role rolename = "manager"/>
   <role rolename = "admin"/>
   <user username = "tomcat" password = "tomcat" roles = "tomcat"/>
   <user username = "role1" password = "tomcat" roles = "role1"/>
   <user username = "both" password = "tomcat" roles = "tomcat,role1"/>
   <user username = "admin" password = "secret" roles = "admin,manager"/>
</tomcat-users>

该文件定义了用户名、密码角色之间的简单映射。请注意,给定用户可能具有多个角色;例如,username = “both”在 “tomcat” 角色和 “role1” 角色中。

一旦您识别并定义了不同的角色,就可以使用 WEB-INF 目录中可用的web.xml文件中的<security-constraint>元素对不同的 Web 应用程序资源施加基于角色的安全限制。

以下是 web.xml 中的示例条目 –

<web-app>
   ...
   <security-constraint>
      <web-resource-collection>
         <web-resource-name>SecuredBookSite</web-resource-name>
         <url-pattern>/secured/*</url-pattern>
         <http-method>GET</http-method>
         <http-method>POST</http-method>
      </web-resource-collection>
      
      <auth-constraint>
         <description>
            Let only managers use this app
         </description>
         <role-name>manager</role-name>
      </auth-constraint>
   </security-constraint>
   
   <security-role>
      <role-name>manager</role-name>
   </security-role>
   
   <login-config>
      <auth-method>BASIC</auth-method>
   </login-config>
   ...
</web-app>

以上条目将意味着 –

  • 对与 /secured/* 匹配的 URL 的任何 HTTP GET 或 POST 请求都将受到安全限制。
  • 具有经理角色的人被授予对受保护资源的访问权。
  • login-config元素用于描述身份验证的BASIC形式

如果您尝试浏览任何 URL,包括/security目录,将显示以下对话框,要求输入用户名和密码。如果您提供用户“admin”和密码“secret”,那么您将可以访问与/secured/*匹配的 URL,因为我们已经定义了具有管理员角色的用户 admin 可以访问此资源。

基于表单的身份验证

使用 FORM 身份验证方法时,必须提供登录表单以提示用户输入用户名和密码。以下是login.jsp的简单代码。这有助于为同一目的创建一个表单 –

<html>
   <body bgcolor = "#ffffff">
      
      <form method = "POST" action ="j_security_check">
         <table border = "0">
            <tr>
               <td>Login</td>
               <td><input type = "text" name="j_username"></td>
            </tr>
            <tr>
               <td>Password</td>
               <td><input type = "password" name="j_password"></td>
            </tr>
         </table>
         <input type = "submit" value = "Login!">
      </form>
      
   </body>
</html>

在这里您必须确保登录表单必须包含名为j_usernamej_password的表单元素。<form>标记中的操作必须是j_security_checkPOST必须用作表单方法。同时,您必须修改<login-config>标签以将 auth-method 指定为 FORM –

<web-app>
   ...
   <security-constraint>
      <web-resource-collection>
         <web-resource-name>SecuredBookSite</web-resource-name>
         <url-pattern>/secured/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
      </web-resource-collection>
      
      <auth-constraint>
         <description>Let only managers use this app</description>
         <role-name>manager</role-name>
      </auth-constraint>
   </security-constraint>
   
   <security-role>
      <role-name>manager</role-name>
   </security-role>
   
   <login-config>
      <auth-method>FORM</auth-method>
      <form-login-config>
         <form-login-page>/login.jsp</form-login-page>
         <form-error-page>/error.jsp</form-error-page>
      </form-login-config>
   </login-config>
   ...
</web-app>

现在,当您尝试使用URL /secured/*访问任何资源时,它将显示上面的表单,询问用户 ID 和密码。当容器看到“ j_security_check ”动作时,它使用一些内部机制来验证调用者。

如果登录成功并且调用者被授权访问受保护的资源,则容器使用会话 ID 从那时起为调用者标识登录会话。容器使用包含会话 ID 的 cookie 维护登录会话。服务器将 cookie 发回给客户端,只要调用者在后续请求中出示这个 cookie,容器就会知道调用者是谁。

如果登录失败,则服务器发回由 form-error-page 设置标识的页面

这里,j_security_check是使用基于表单登录的应用程序必须为登录表单指定的操作。在相同的表单中,您还应该有一个名为 j_username 的文本输入控件和一个名为j_password的密码输入控件。当你看到这个时,意味着表单中包含的信息将被提交给服务器,服务器将检查用户名和密码。这是如何完成的是特定于服务器的。

检查标准领域实现以了解j_security_check如何为 Tomcat 容器工作。

Servlet/JSP 中的编程安全性

HttpServletRequest对象提供以下方法,可用于在运行时挖掘安全信息 –

编号方法及说明
1个String getAuthType()
getAuthType ()方法返回一个 String 对象,它表示用于保护 Servlet 的身份验证方案的名称。
2个boolean isUserInRole(java.lang.String role)
isUserInRole ()方法返回一个布尔值:如果用户在给定角色中则为 true,否则为 false。
3个String getProtocol()
getProtocol()方法返回一个 String 对象,表示用于发送请求的协议。可以检查此值以确定是否使用了安全协议。
4个boolean isSecure()
isSecure ()方法返回一个布尔值,表示请求是否使用 HTTPS 发出。值为 true 表示它是并且连接是安全的。值为 false 表示请求不是。
5个Principle getUserPrinciple()
getUserPrinciple()方法返回一个 java.security.Principle 对象,其中包含当前经过身份验证的用户的名称。

例如,对于链接到经理页面的 JavaServer Page,您可能有以下代码 –

<% if (request.isUserInRole("manager")) { %>
   <a href = "managers/mgrreport.jsp">Manager Report</a>
   <a href = "managers/personnel.jsp">Personnel Records</a>
<% } %>

通过检查用户在 JSP 或 servlet 中的角色,您可以自定义网页以仅向用户显示她可以访问的项目。如果您需要在身份验证表单中输入的用户名,您可以调用请求对象中的getRemoteUser方法。

JSP – 国际化| 国际化| l10n

在本章中,我们将讨论 JSP 中国际化的概念。在我们继续之前,让我们了解以下三个重要术语 –

  • 国际化 (i18n) – 这意味着使网站能够提供翻译成访问者语言或国籍的不同版本的内容。
  • 本地化 (l10n) – 这意味着向网站添加资源以使其适应特定的地理或文化区域,例如将印地语翻译到网站。
  • locale – 这是一个特定的文化或地理区域。它通常被称为一个语言符号,后面跟着一个国家符号,它们之间用下划线分隔。例如,“ en_US ”代表美国的英语语言环境。

在建立全球网站时,有许多事项需要注意。本教程不会为您提供这方面的完整细节,但会为您提供一个很好的示例,说明如何通过区分位置(即语言环境)向 Internet 社区提供不同语言的网页。

JSP 可以根据请求者的区域设置选择适当的站点版本,并根据当地语言、文化和要求提供适当的站点版本。以下是返回 Locale 对象的请求对象的方法。

java.util.Locale request.getLocale() 

检测语言环境

以下是重要的 locale 方法,您可以使用它们来检测请求者的位置、语言,当然还有locale。以下所有方法均显示请求者浏览器中设置的国家名称和语言名称。

编号方法及说明
1个String getCountry()
此方法以 ISO 3166 2 字母格式返回此语言环境的大写国家/地区代码。
2个String getDisplayCountry()
此方法返回适合向用户显示的区域设置国家/地区的名称。
3个String getLanguage()
此方法以 ISO 639 格式返回此语言环境的小写语言代码。
4个String getDisplayLanguage()
此方法返回适合向用户显示的区域设置语言的名称。
5个String getISO3Country()
此方法返回此区域设置国家/地区的三个字母的缩写。
6个String getISO3Language()
此方法返回此区域设置语言的三个字母的缩写。

例子

以下示例显示如何在 JSP 中显示请求的语言和相关国家 –

<%@ page import = "java.io.*,java.util.Locale" %>
<%@ page import = "javax.servlet.*,javax.servlet.http.* "%>
<%
   //Get the client's Locale
   Locale locale = request.getLocale();
   String language = locale.getLanguage();
   String country = locale.getCountry();
%>

<html>
   <head>
      <title>Detecting Locale</title>
   </head>

   <body>
      <center>
         <h1>Detecting Locale</h1>
      </center>
      
      <p align = "center">
         <% 
            out.println("Language : " + language  + "<br />");
            out.println("Country  : " + country   + "<br />");
         %>
      </p>
   </body>
</html>

语言设置

JSP 可以输出用西欧语言编写的页面,例如英语、西班牙语、德语、法语、意大利语、荷兰语等。这里重要的是设置 Content-Language 标题以正确显示所有字符。

另一个重点是使用 HTML 实体显示所有特殊字符;例如,“ñ” 代表“ñ”“¡” 代表“¡”如下 –

<%@ page import = "java.io.*,java.util.Locale" %>
<%@ page import = "javax.servlet.*,javax.servlet.http.* "%>

<%
   // Set response content type
   response.setContentType("text/html");
   
   // Set spanish language code.
   response.setHeader("Content-Language", "es");
   String title = "En Español";
%>

<html>
   <head>
      <title><%  out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><%  out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>En Español</p>
         <p>¡Hola Mundo!</p>
      </div>
   </body>
</html>

区域特定日期

您可以使用java.text.DateFormat类及其静态getDateTimeInstance()方法来格式化特定于语言环境的日期和时间。以下是显示如何格式化特定于给定语言环境的日期的示例 –

<%@ page import = "java.io.*,java.util.Locale" %>
<%@ page import = "javax.servlet.*,javax.servlet.http.* "%>
<%@ page import = "java.text.DateFormat,java.util.Date" %>

<%
   String title = "Locale Specific Dates";
   
   //Get the client's Locale
   Locale locale = request.getLocale( );
   
   String date = DateFormat.getDateTimeInstance(
      DateFormat.FULL, 
      DateFormat.SHORT, 
      locale).format(new Date( ));
%>

<html>
   
   <head>
      <title><% out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><% out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>Local Date: <%  out.print(date); %></p>
      </div>
   </body>
</html>

区域特定货币

您可以使用java.txt.NumberFormat类及其静态getCurrencyInstance()方法将数字(例如 long 或 double 类型)格式化为语言环境特定的货币。以下是显示如何格式化特定于给定区域设置的货币的示例 –

<%@ page import = "java.io.*,java.util.Locale" %>
<%@ page import = "javax.servlet.*,javax.servlet.http.* "%>
<%@ page import = "java.text.NumberFormat,java.util.Date" %>

<%
   String title = "Locale Specific Currency";
   
   //Get the client's Locale
   Locale locale = request.getLocale( );
   
   NumberFormat nft = NumberFormat.getCurrencyInstance(locale);
   String formattedCurr = nft.format(1000000);
%>

<html>
   
   <head>
      <title><% out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><% out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>Formatted Currency: <%  out.print(formattedCurr); %></p>
      </div>
   </body>
</html>

区域特定百分比

您可以使用java.txt.NumberFormat类及其静态getPercentInstance()方法来获取特定于语言环境的百分比。以下示例显示了如何格式化特定于给定语言环境的百分比 –

<%@ page import = "java.io.*,java.util.Locale" %>
<%@ page import = "javax.servlet.*,javax.servlet.http.* "%>
<%@ page import = "java.text.NumberFormat,java.util.Date" %>

<%
   String title = "Locale Specific Percentage";
   
   //Get the client's Locale
   Locale locale = request.getLocale( );
   
   NumberFormat nft = NumberFormat.getPercentInstance(locale);
   String formattedPerc = nft.format(0.51);
%>

<html>
   
   <head>
      <title><% out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><% out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>Formatted Percentage: <%  out.print(formattedPerc); %></p>
      </div>
   </body>
</html>