IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 【Java学习路线之JavaWeb】JSP教程 -> 正文阅读

[Java知识库]【Java学习路线之JavaWeb】JSP教程

转载于:http://c.biancheng.net/jsp2/

JSP 是 Java Server Pages 的缩写,是一种动态网页开发技术。动态网页是指跟静态网页相对的一种网页编程技术。静态网页,随着 HTML 代码的生成,页面的内容和显示基本上不会发生变化,除非修改页面代码。动态网页显示的内容可以随着时间、环境或者数据库操作的结果而发生改变。

JSP 本质是一个 Java 类(Servlet),我们可以在 JSP 页面中嵌入 Java 代码,即:JSP = HTML + Java。

请求 JSP 时,服务器内部会经历一次动态资源(JSP)到静态资源(HTML)的转化。服务器会自动把 JSP 中的 HTML 片段和数据拼接成静态资源响应给浏览器。也就是说,JSP 运行在服务器端,但最终发给客户端的是已经转换好的 HTML 静态页面。

为什么要学习JSP?

JSP 的功能与 CGI 相似,但相对于 CGI 来说,JSP 具有很多优势。

  • JSP 性能更加优越。因为 JSP 可以直接在 HTML 页面中嵌入动态元素,而不需要单独的引入 CGI 文件。
  • JSP 会在服务器调用之前进行编译,而不是像 CGI/Perl 必须先加载解释器和目标脚本。
  • JSP 基于 Java Servlet API,因此,JSP 可以使用各种强大的企业级 Java API,包括 JDBC、JNDI、EJB 和 JAXP 等。
  • JSP 页面可以和处理业务逻辑的 Servlet 一起使用。

JSP 是 Java EE 不可或缺的一部分,是一个完整的企业级应用平台。这意味着 JSP 可以用最简单的方式来实现最复杂的应用。

读者

本 JSP 教程适合初学者阅读,可以帮助读者了解 JSP 的基本功能以及如何开发动态网页。学习完本教程后,您将具有 JSP 方面的中等靠上的专业知识。

阅读条件

在学习本教程之前,您应当至少具备 HTML、CSS Java 和 Servlet 基础。

JSP到底是什么

JSP(Java Server Pages)是一种动态网页开发技术。JSP 文件就是在传统的 HTML 文件中插入 Java 代码和 JSP 标签,后缀名为.jsp

JSP 与 PHP、ASP、ASP.NET 等语言类似,都运行在服务端。通常返回给客户端的就是一个 HTML 文件,因此只要有浏览器就能查看 JSP 页面。

JSP 使用 JSP 标签在 HTML 网页中插入 Java 代码,标签通常以<%开头,以%>结束。JSP 标签有多种功能,比如访问数据库和 JavaBean 组件等,还可以在不同的网页之间传递和共享信息。

JSP 是 Servlet 的扩展,我们可以在 JSP 中使用 Servlet 的所有功能。另外,JSP 还提供了一些其他功能,例如 EL 表达式、自定义标签等。

JSP 依赖于 Servlet,用户访问 JSP 页面时,JSP 代码会被翻译成 Servlet 代码,最终,以字符串的形式向外输出 HTML 代码。所以,JSP 只是在 Servlet 的基础上做了进一步封装。

JSP 通过表单获取用户输入的数据、访问数据库或其它数据源生成动态的 Web 内容。

JSP 具有以下特点:

  • JSP 具有 Servlet 的所有优点,例如 JSP 文件跨平台,即一次编写,处处运行。
  • JSP 比 CGI 性能更加优越,因为 JSP 可以直接在 HTML 中嵌入标签,而 CGI 需要单独引用 CGI 文件。
  • JSP 比 Servlet 更易于维护,JSP 将业务逻辑与网页设计分离,使其更加灵活。
  • 使用 JSP,Web 开发人员可以更注重于网页设计,Java 开发人员可以更注重于逻辑处理。

JSP的由来

1997 年,Sun 公司推出了 Servlet。

由于当时的 Java Web 层体系结构中只有 Servlet,所以接收用户请求、处理业务逻辑、生成 HTML 代码等都在 Servlet 中完成。Servlet 不能像 PHP、ASP 等语言镶嵌 HTML 代码,因此输出 HTML 比较困难,且部署过程复杂。

为了克服 Servlet 的这些弱点,1999 年初,Sun 公司推出了 JSP。在生成 HTML 代码方面 JSP 比 Servlet 方便许多,而且不需要特殊部署,只需要复制到服务器下面即可运行。简而言之,JSP 就是为了简化 Servlet 工作而出现的替代品。

JSP 包括很多技术,包括 Java Bean、自定义标签(Custom Tags)、EL 表达式(Expression Language)、JSTL 标准标签类库(Java Standard Tag Library)等。这些强大成熟的技术使得 JSP 在视图层(View)具有很大的优势。

Servlet与JSP异同点

相同点:与 Servlet 一样,JSP 也用于生成动态网页。

不同点如下:

序号ServletJSP
1Servlet 在 Java 内添加 HTML 代码JSP 在 HTML 内添加 Java 代码
2Servlet 是一个 Java 程序,支持 HTML 标签JSP 是一种 HTML 代码,支持 Java 语句
3Servlet 一般用于开发程序的业务层(做一些复杂的逻辑处理)JSP 一般用于开发程序的表示层(显示数据)
4Servlet 由 Java 开发人员创建和维护JSP 常用于页面设计,由 Web 开发人员使用

JSP相对于Servlet的优点

1)易于维护

相对于 Servlet 来说,JSP 更易于管理。在 JSP 中,我们可以轻松地将业务逻辑与网页设计分开,而在 Servlet 技术中,它们是混合在一起的。

2)快速开发:无需重新编译和部署

JSP 页面被修改后,不需要重新编译和部署项目。而 Servlet 被修改后,需要重新编译和部署。

3)代码简洁

在 JSP 中,我们可以使用 EL、JSTL、自定义标签、隐式对象等,能够有效的减少代码。

JSP生命周期(图解)

JSP 生命周期定义了 JSP 从创建到销毁的整个过程。这类似于 Servlet 生命周期,不同的是,JSP 需要先被编译成 Servlet。

JSP 生命周期阶段如下:

  1. 编译
  2. 初始化(容器调用 jspInit() 方法)
  3. 执行(容器调用 _jspService() 方法)
  4. 销毁(容器调用 jspDestroy() 方法)

JSP生命周期

1. JSP编译

当浏览器请求 JSP 时,JSP 容器会首先检查是否需要编译页面。如果该页面从未被编译过,或者自上次编译以来对其进行了修改,则编译该页面。

JSP 本质是 Servlet,因此 JSP 容器就是 Servlet 容器

编译过程包括 3 个步骤:

  • 解析 JSP:JSP 容器解析 JSP 文件,查看是否有语法错误
  • 翻译 JSP:JSP 容器把 JSP 文件翻译为 Servlet 类
  • 编译 Servlet

2. JSP初始化

当容器加载 JSP 时,它将在处理任何请求之前调用 jspInit() 方法。如果您需要自定义 JSP 的初始化内容,可以重写 jspInit() 方法。

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

一般情况下,程序只初始化一次。与 Servlet init 方法一样,我们通常在 jspInit() 方法中初始化数据库连接、打开文件。

3. JSP执行

此阶段表示了 JSP 生命周期中所有与请求相关的交互行为,直到被销毁。

JSP 页面完成初始化后,JSP 将会调用 _jspService() 方法。

_jspService() 以 HttpServletRequest 对象和 HttpServletResponse 对象作为方法参数,如下所示:

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

JSP 的 _jspService() 方法根据 request 来生成相应的 response,并且它还负责生成对 HTTP 方法的响应,即 GET、POST、DELETE 等。

4. JSP销毁

JSP 生命周期的销毁阶段表示从容器中删除 JSP。

jspDestroy() 方法等效于 Servlet 中的 destroy() 方法。如果您需要自定义 JSP 的销毁内容,可以重写 jspDestroy() 方法。

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

public void jspDestroy() {
   ...
}

通常我们在 jspDestroy() 方法中释放数据库连接、关闭打开的文件。

第一个JSP程序

本节我们来简单创建一个 JSP 程序。

新建文件,编写以下代码,并将该文件存为 index.jsp,并放在文件夹 jspDemo 中,然后将该文件夹粘贴到 tomcat 的 webapps 目录下,运行 JSP 页面。

1. 编写代码

index.jsp 代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title></title>
</head>
<body>
    <%out.print("Hello,编程帮!网址是:http://www.biancheng.net");%>
</body>
</html>

2. 运行

运行步骤:

  1. 把 JSP 文件放在文件夹内,部署到服务器中
  2. 启动服务器
  3. 通过 URL 访问,例如:http://localhost:8080/jspDemo/index.jsp

访问结果如下:

访问结果

3. 代码解释

<% @ page%> 用来指定该页面的配置信息,contentType="text/html; charset=UTF-8"指定该网页类型为 html,网页字符编码为 UTF-8;language="java" 指定该网页编程语言为 Java。

和 都是 HTML 标签,用于静态网页,他们包含的内容都将直接传递给客户端,也就是 Web 浏览器。

<%out.print("Hello,编程帮");%> 是 JSP 中的输出语句,<% %> 中的代码是 Java 语句,因此以;结尾,out.print("Hello,编程帮")输出信息为“Hello,编程帮”。

Eclipse创建JSP项目(图解)

本节我们在 Eclipse 中创建一个简单的 JSP 文件。

使用 Eclipse 创建 JSP 文件分为 3 个步骤:

  1. 创建动态 Web 项目
  2. 创建 JSP 文件
  3. 启动 Tomcat 服务器,部署项目

1. 创建动态Web项目

打开 Eclipse,单击 File -> New -> Project -> Dynamic Web Project,如下图所示:

img

img

输入项目名称,配置服务器,点击完成。

img

2. 创建JSP文件

在项目的 WebContent 目录单击鼠标右键,按顺序依次单击 New -> Other -> JSP File -> Next,输入文件名 index.jsp,如下图所示。

img

index.jsp 代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
    <title></title>
</head>
<body>
    <%out.print("Hello,编程帮");%>
</body>
</html>

3. 启动服务器并部署项目

运行 JSP,在您的 JSP 页面中单击鼠标右键,单击 Run As -> Run on Server,如下图所示。

img

选择 Tomcat 服务器,点击Next -> 选中项目 -> Add(也可双击项目直接部署到Tomcat上)-> Finish。

img

img

启动 Tomcat 服务器,在浏览器输入相应的 URL,例如:http://localhost:8080/jspDemo/index.jsp,页面如下。

img

JSP脚本

在 JSP 中,可以使用 JSP 脚本写入 Java 代码。

JSP 脚本可以包含任意数量的 Java 语句,变量、方法和表达式。JSP 脚本会把包含的内容插入到 Servlet 的 service() 方法中。

JSP 脚本语法如下:

<% Java语句 %>

等效于

<jsp:scriptlet>
    Java语句
</jsp:scriptlet>

任何文本、HTML 标签和 JSP 元素(声明,表达式等)都必须在脚本程序之外。

示例

大家可先参考《第一个JSP程序》中使用 JSP 脚本的一个简单实例。

下面创建 login.html 和 welcome.jsp 两个文件,login.html 提供表单供用户输入用户名,welcome.jsp 获取用户输入用户名并显示欢迎消息。

login.html 代码如下:

<!DOCTYPE html>
<html>
<body>
    <form action="welcome.jsp" method="post">
        <input type="text" name="uname"><br/>
        <input type="text" name="url"><br/>
        <input type="submit" value="go">
    </form>
</body>
</html>

welcome.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<body>
    <%
        String name = request.getParameter("uname");
        String url= request.getParameter("url");
        out.print("欢迎" + name + ",我们的网址是:" + url);
    %>
</body>
</html>

运行结果如下:

login.html运行页面
login.html运行页面

welcome.jsp运行页面
welcome.jsp运行页面

JSP声明语句

JSP 声明语句用于声明一个或多个变量、方法,以供后面的 Java 代码使用。您必须先对变量和方法进行声明,才能使用它们。

JSP 声明语法如下:

<%! 声明语句 %>

等效于

<jsp:declaration>
    声明语句
</jsp:declaration>

示例

<%! int num = 0; %>
<%! Circle a = new Circle(2.0); %>
<%!
    public void show () {
    }
%>

JSP脚本和声明的区别

JSP 脚本只能声明变量,不能声明方法。JSP 声明语句可以声明变量和方法。

JSP 脚本会把包含的内容转译插入到 Servlet 的 service() 方法中,也就是 <% %> 中定义的变量是局部变量。这也是 JSP 脚本不能声明方法的原因,因为 Java 不允许方法中嵌套方法。

JSP 声明会把包含的内容添加到 Servlet 类中(在任何方法之外),也就是 <%! %> 中定义的变量是成员变量,方法是成员方法。

JSP表达式

JSP 表达式可以把变量或者表达式输出到网页上,不需要 out.print() 就能输出数据。通常用于打印变量和方法的值。

JSP 表达式语法如下:

<%= 表达式 %>

等效于

<jsp:expression>
    表达式
</jsp:expression>

可以将 <%=表达式 %> 理解为 <% out.println(表达式) %> 的简写方式。这里需要注意,JSP 表达式不能以分号结尾。

例 1

使用 JSP 表达式显示欢迎消息,代码如下:

<html> 
<body> 
    <%="欢迎来到编程帮(http://www.biancheng.net)!"%> 
</body> 
</html>  

浏览器输出信息为:

欢迎来到编程帮(http://www.biancheng.net)!

例 2

下面使用 JSP 表达式显示当前时间,代码如下:

<html>
<body>
    当前时间: <%= java.util.Calendar.getInstance().getTime() %> 
</body>
</html>

浏览器输出信息为:

当前时间: Mon Dec 07 15:11:33 CST 2020

JSP指令

JSP 指令(directive)用来告诉 Web 服务器如何处理 JSP 页面的请求和响应。

服务器会根据 JSP 指令来编译 JSP,生成 Java 文件。JSP 指令不产生任何可见输出,在生成的 Java 文件中,不存在 JSP 指令。

JSP 指令以<%@开始,以%>结束,语法如下:

<%@ directive attribute = “value” [attribute2 = “value2” …]%>

注意:[ ]中的内容是可选的,@ 符号和指令名称之间,以及最后一个属性和结束%>之间的空格是可选的。

指令分为以下 3 种类型。

指 令说 明
<%@ page … %>定义与页面相关的属性,例如脚本语言、错误页面和缓冲要求
<%@ include … %>引入其它 JSP 文件
<%@ taglib … %>声明并导入标签库

在以下章节中,我们详细介绍了这几种指令。

JSP page指令

JSP page 指令用来定义当前页面的相关属性。page 指令可以在 JSP 页面的任意位置编写,通常放在 JSP 页面的顶部。

page 指令的语法如下:

<%@ page attribute = “value” %>

下表是与 page 指令相关的属性。

属 性取 值说 明举 例
buffernone、缓冲区大小(默认值为 8kb)指定输出流是否有缓冲区<%@ page buffer=“16kb” %>
autoFlushtrue(默认值)、false指定缓冲区是否自动清除<%@ page autoFlush=“true” %>
contentTypetext/html; charset = ISO-8859-1、 text/xml;charset = UTF-8 等指定 MIME 类型和字符编码<%@ page contentType=“text/html;charset=UTF-8” %>
errorpage页面路径指定当前 JSP 页面发生异常时,需要重定向的错误页面<%@ page errorpage=“myerrorpage.jsp” %> 注意:myerrorpage.jsp 的 isErrorpage 值必须为 true
isErrorpagetrue、false(默认值)指定当前页面为错误页面<%@ page isErrorpage=“true” %>
extends包名.类名指定当前页面继承的父类,一般很少使用<%@ page extends=“mypackage.SampleClass”%>
import类名、接口名、包名导入类、接口、包,类似于 Java 的 import 关键字<%@ page import = " java.util.Date" %> <%@ page import=“java.io., java.lang.”%>
info页面的描述信息定义 JSP 页面的描述信息,可以使用 getServletInfo() 方法获取<%@ page info=“这里是编程帮的页面信息”%>
isThreadSafetrue(默认值)、false是否允许多线程使用<%@ page isThreadSafe=“false” %>
language脚本语言指定页面中使用的脚本语言<%@ page language= “java” %>
sessiontrue(默认值)、false指定页面是否使用 session<%@ page session=“false” %>
isELIgnoredtrue(默认值)、false指定页面是否忽略 JSP 中的 EL<%@ page isELIgnored=“false” %>

以上属性除了 import 可以声明多个外,其它属性都只能出现一次。

例 1

下面通过 page 指令的 import 属性导入 java.util.Date 类,显示欢迎信息和用户登录的日期时间。login.jsp 代码如下:

<%@ page import="java.util.Date" language="java"
    contentType="text/html;charset=utf-8"%>
<html>
<body>
    您好,欢迎登录编程帮!
    <br /> 您登录的时间是<%=new Date()%>
</body>
</html>

运行结果如下:

img

例 2

下面通过 page 指令的 errorpage 和 isErrorPage 属性定义以及重定向到错误页面。index.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<body>
    <%@page errorPage="errorpage.jsp"%>
    <%=100/0 %>
</body>
</html>

errorpage.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<body>
    <%@page isErrorPage="true"%>
    抱歉,发生了异常!
    <br /> 异常为<%= exception%>
</body>
</html>

注意:exception 只能在错误页面使用。

访问 index.jsp 页面,结果如下:

index.jsp访问结果

JSP include指令

include 指令用于在 JSP 页面引入其它内容,可以是 JSP 文件、html 文件和文本文件等,相当于把文件的内容复制到 JSP 页面。引入的文件和 JSP 页面同时编译运行。

使用 include 指令有以下优点:

  • 增加代码的可重用性
  • 使 JSP 页面的代码结构清晰易懂
  • 维护简单

include 的语法如下:

<%@ include file=“URL” %>

其中,file 指定需要引入文件的相对路径。

可以在页面的任何位置编写 include 指令。

例 1

在 index.jsp 页面使用 include 指令引入 head.jsp。head.jsp 代码如下:

<p>header内容</p>

index.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<body>
    <%@ include file="head.jsp" %>
    <p>编程帮(http://www.biancheng.net)</p>
</body>
</html>

此示例中,head.jsp 和 index.jsp 在同一目录中,如果不在同一目录,引入 head.jsp 文件时需要指定完整路径。运行结果如下:

img

JSP taglib指令

在 JSP 中,我们可以使用 taglib 指令声明并引入标签库。Java API 允许在页面中自定义标签,标签库就是自定义标签的集合。

taglib 指令的语法如下:

<%@ taglib uri=“tagliburl” prefix=“tagPre” %>

其中,uri 指定自定义标签库的存放位置;prefix 指定标签库的前缀。为了区分不同的标签库,在页面中使用标签库以对应的 prefix 开头。

例 1

下面我们使用 currentDate 标签,首先使用 taglib 指令指定标签库存放位置和使用前缀。示例代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.biancheng.net/tags" prefix="mytag"%>
<!DOCTYPE html>
<html>
<body>
    <mytag:currentDate />
</body>
</html>

以上代码会出现找不到标签库路径错误,这里只演示 taglib 指令的用法,具体应用会在教程后面进行详细说明。

JSP动作

JSP 动作使用 XML 语法格式的标签来控制服务器的行为。利用 JSP 动作可以动态地插入文件、重用 JavaBean 组件、把用户重定向到另一个页面、为 Java 插件生成 HTML 代码等。

JSP 动作与 JSP 指令的不同之处如下:

  • JSP 指令在翻译阶段执行,从而设置整个 JSP 页面的属性。JSP 页面被执行时首先进入翻译阶段,程序会先查找页面中的 JSP 指令,并将它们转换成 Servlet。所以,JSP 指令是在页面转换时期被编译执行的,且编译一次。
  • JSP 动作在请求处理阶段执行,它们只有执行时才实现自己的功能。通常用户每请求一次,动作标识就会执行一次。

JSP 动作语法如下:

<jsp:action_name attribute = "value" />

<jsp:action_name attribute="value"></jsp:action_name>

action_name 表示 JSP 动作名称,attribute 表示相应 JSP 动作的属性名称。常用的 JSP 动作如下表所示:

动作说明
jsp:include页面被请求时引入一个文件
jsp:userBean实例化JavaBean
jsp:setProperty设置 JavaBean 的属性
jsp:getProperty获取 JavaBean 的属性
jsp:forward将请求转发到另一个页面
jsp:plugin根据浏览器类型替换成 或者 标签
jsp:element定义动态 XML 元素
jsp:attribute设置动态 XML 元素的属性
jsp:body设置动态 XML 元素的内容

在以下章节中,我们详细介绍了几种常用的动作:

JSP九大内置对象一览表

为了简化页面的开发过程,JSP 提供了一些内置对象。

JSP 内置对象又称为隐式对象,它们由容器实现和管理。在 JSP 页面中,这些内置对象不需要预先声明,也不需要进行实例化,我们可以直接在脚本和表达式中使用。

注意:JSP 内置对象只能在脚本和表达式中使用,在声明中不能使用。

九大内置对象

JSP 中定义了 9 个内置对象,它们分别是:request、response、session、application、out、pagecontext、config、page 和 exception,这些对象在客户端和服务器端交互的过程中分别完成不同的功能。

对 象类型说 明
requestjavax.servlet.http.HttpServletRequest获取用户请求信息
responsejavax.servlet.http.HttpServletResponse响应客户端请求,并将处理信息返回到客户端
outjavax.servlet.jsp.JspWriter输出内容到 HTML 中
sessionjavax.servlet.http.HttpSession用来保存用户信息
applicationjavax.servlet.ServletContext所有用户共享信息
configjavax.servlet.ServletConfig这是一个 Servlet 配置对象,用于 Servlet 和页面的初始化参数
pageContextjavax.servlet.jsp.PageContextJSP 的页面容器,用于访问 page、request、application 和 session 的属性
pagejavax.servlet.jsp.HttpJspPage类似于 Java 类的 this 关键字,表示当前 JSP 页面
exceptionjava.lang.Throwable该对象用于处理 JSP 文件执行时发生的错误和异常;只有在 JSP 页面的 page 指令中指定 isErrorPage 的取值 true 时,才可以在本页面使用 exception 对象。

JSP 的内置对象主要有以下特点:

  • 由 JSP 规范提供,不用编写者实例化;
  • 通过 Web 容器实现和管理;
  • 所有 JSP 页面均可使用;
  • 只有在脚本元素的表达式或代码段中才能使用。

四大域对象

在 JSP 九大内置对象中,包含四个域对象,它们分别是:pageContext(page 域对象)、request(request 域对象)、session(session 域对象)、以及 application(application 域对象)。

JSP 中的 4 个域对象都能通过以下 3 个方法,对属性进行保存、获取和移除操作。

返回值类型方法作用
voidsetAttribute(String name, Object o)将属性保存到域对象中
ObjectgetAttribute(String name)获取域对象中的属性值
voidremoveAttribute(String name)将属性从域对象中移除

JSP 中的 4 个域对象的作用域各不相同,如下表。

作用域描述作用范围
page如果把属性保存到 pageContext 中,则它的作用域是 page。该作用域中的属性只在当前 JSP 页面有效,跳转页面后失效。
request如果把属性保存到 request 中,则它的作用域是 request。该作用域中的属性只在当前请求范围内有效。服务器跳转页面后有效,例如jsp:forward;客户端跳转页面后无效,例如超链接。
session如果把属性保存到 session 中,则它的作用域是 session。该作用域中的属性只在当前会话范围内有效,网页关闭后失效。
application如果把属性保存到 application 中,则它的作用域是 application。该作用域中的属性在整个应用范围内有效,服务器重启后失效。

JSP request对象

JSP request 是 javax.servlet.http.HttpServletRequest 的实例对象,主要用来获取客户端提交的数据。

request 对象提供了一系列方法,可以获取请求参数信息、表单数据、HTTP 头信息、cookie 和 HTTP 请求方法等。request 对象常用方法如下表所示。

方法说明
String getParameter(String name)获取请求参数 name 的值
Enumeration getParameterNames()获取所有参数名称
String[] getParameterValues(String name)获取请求参数 name 的所有值
Object getAttribute(String name)获取 name 属性的值
Enumeration getAttributeNames()返回所有属性的名称集合
void setAttribute(String key, Object value)给 key 对象赋 value 值
void removeAttribute(String name)删除指定的 name 属性
cookie[] getCookies()获取所有的 cookie 对象
HttpSession getSession()返回 request 对应的 session 对象,如果没有则创建一个 session 对象
HttpSession getSession(boolean create)返回 request 对应的 session 对象,如果没有,且 create 值为 true,则创建一个 session 对象
Enumeration getHeaderNames()返回 HTTP 头信息的名称集合
String getHeader(String name)获取 name 指定的 HTTP 头信息
String getMethod()获取 HTTP 请求方法/客户提交信息方式

示例

在 index.jsp 页面使用 getHeaderNames() 方法获取 HTTP 头信息,并遍历输出参数名称和对应值。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <h2>获取HTTP请求头信息</h2>
    <table width="100%" border="1" align="center">
        <tr bgcolor="#949494">
            <th>参数名称</th>
            <th>参数值</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>
</body>
</html>

运行结果如下:

index.jsp运行结果

头信息介绍如下:

参数名称说明
host表示服务器的主机名和端口号
connection判断客户端是否可以持续性的连接 HTTP
cache-control网页缓存控制,默认值为 no-cache,表明每次访问都从服务器中获取页面
upgrade-insecure-requestsChrome(谷歌浏览器)会在 HTTP 请求中加入Upgrade-Insecure-Requests: 1 ,服务器收到请求后会返回 Content-Security-Policy: upgrade-insecure-requests头来告诉浏览器,可以把本站的所有 http 连接升级为 https 连接。使用其它浏览器没有该参数
user-agent客户端程序的相关信息,例如:浏览器版本、操作系统类型等
accept客户端能接收的 MIME 类型
sec-fetch-*网络请求的元数据描述,也是 Chrome 特有的参数
accept-encoding指明客户端能够处理的编码类型有哪些
accept-language浏览器的首选语言
cookie会话信息,每个会话都有一个对应的会话 ID 或其他信息

JSP response对象

JSP response 是 javax.servlet.http.HttpServletResponse 的实例对象。response 对象和 request 对象相对应,主要用于响应客户端请求,将处理信息返回到客户端。

response 对象的常用方法如下:

方 法说 明
void addHeader(String name, String value)添加头信息(参数名称和对应值)
void addCookie(Cookie cookie)添加 cookie 信息
void sendRedirect(String location)实现页面重定向
void setStatus(int sc)实现页面的响应状态代码
void setContentType(String type)设置页面的 MIME 类型和字符集
void setCharacterEncoding(String charset)设定页面响应的编码类型

示例

下面在 login.jsp 新建表单,在 checkdetails.jsp 接收 login.jsp 提交的用户名和密码,与指定的用户名和密码相比,相同则登录成功,重定向到 success.jsp;反之登录失败,重定向到 failed.jsp。

login.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <h2>用户登录</h2>
    <form action="checkdetails.jsp">
        用户名: <input type="text" name="username" /> <br> <br> 
        密码: <input type="text" name="pass" /> <br> <br> 
        <input type="submit" value="登录" />
    </form>
</body>
</html>

checkdetails.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        String username = request.getParameter("username");
        String password = request.getParameter("pass");
        if (username.equals("biancheng") && password.equals("bianchengbang")) {
            response.sendRedirect("success.jsp");
        } else {
            response.sendRedirect("failed.jsp");
        }
    %>
</body>
</html>

success.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <h2>登录成功!</h2>
</body>
</html>

failed.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <h2>登录失败,用户名或密码错误!</h2>
</body>
</html>

运行结果如下所示:

登录页面(输入正确的用户名和密码)
登录页面(输入正确的用户名和密码)

登录成功页面
登录成功页面

登录页面(输入错误的用户名)
登录页面(输入错误的用户名)

登录失败页面
登录失败页面

JSP out对象

JSP out 是 javax.servlet.jsp.JspWriter 的实例对象。out 对象包含了很多 IO 流中的方法和特性,最常用的就是输出内容到 HTML 中。

out 对象的常用方法如下:

方法说明
void print()将内容直接打印在 HTML 标签中
void println()类似于 print,唯一区别是 println 方法添加了换行符
void newLine()输出换行字符
void clear()清除页面缓冲区
boolean isAutoFlush()检查页面是否自动清除缓冲区

示例

out 对象的方法相对比较简单,一般情况下很少使用。下面我们使用 out 对象的 print、println 和 newLine 方法将内容输出到 HTML 中。index.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        out.print("欢迎来到编程帮,");
        out.newLine();
        out.println("我们的网址是:");
        out.print("www.biancheng.net");
    %>
</body>
</html>

运行结果如下:

index.jsp运行结果
index.jsp运行结果

注意:这里的 println 与 newLine 换行指的是 HTML 代码换行,并不是页面显示的换行。页面显示换行需要在代码后面加
标签。

JSP session对象

JSP session 是 javax.servlet.http.HttpSession 的实例对象,主要用来访问用户数据,记录客户的连接信息。

HTTP 协议是一种无状态的协议(即不保存连接状态的协议)。每次用户向服务器发出请求,且服务器接收请求并返回响应后,该连接就被关闭了,服务器端与客户端的连接被断开。此时,服务器端不保留连接的有关信息,要想记住客户的连接信息,就用到了 session 对象。

session 对象的常用方法如下:

方法说明
void setAttribute(String name, Object value)将参数名和参数值存放在 session 对象中
Object getAttribute(String name)通过 name 返回获取相应的 value 值,如果 name 没有相应的 value 值,则返回 null
void removeAttribute(String name)删除指定的 name 参数
Enumeration getAttributeNames()获取 session 对象中存储的所有参数
long getCreationTime()返回 session 对象创建的时间
String getId()获取 session 对象的 ID 值
boolean isNew()用于检查 session 对象是不是新对象,如果客户端禁用了 cookie ,则 session.isNew() 始终返回 true
void invalidate()终止 session,即指定 session 对象失效
void setMaxInactiveInterval()设置 session 对象的有效时间,单位:秒
int getMaxInactiveInterval()获取 session 对象的有效时间,单位:秒
long getLastAccessedTime()获取上次访问 session 对象的时间

示例

在 login.jsp 页面登录,并跳转到 index.jsp。login.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <h2>用户登录</h2>
    <form action="index.jsp">
        用户名: <input type="text" name="username" /> <br> <br>
        密码: <input type="text" name="pass" /> <br> <br>
        <input type="submit" value="登录" />
    </form>
</body>
</html>

在 index.jsp 中,使用 session.setAttribute() 方法将用户名存储到 session 对象中,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        String username = request.getParameter("username");
        out.print("欢迎" + username + "登录");
        session.setAttribute("sessname", username);
    %>
    <a href="success.jsp">跳转成功页面</a>
</body>
</html>

在 success.jsp 中,使用 session.getAttribute() 方法获取 session 对象中的用户名,并显示。success.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        String name = (String) session.getAttribute("sessname");
        out.print("您好,您的用户名为:" + name);
    %>
</body>
</html>

运行结果如下图所示:

login.jsp
login.jsp运行结果

index.jsp运行结果
index.jsp运行结果

success.jsp运行结果
index.jsp运行结果

拓展

如果使用的是 Tomcat 服务器,可以在 web.xml 文件中添加以下内容来设置 session 的有效时间:

<session-config>
    <session-timeout>15</session-timeout>
</session-config>

这里单位是分钟,即表示 session 对象的有效时间为 15 分钟,Tomcat 默认有效时间为 30 分钟。

如果在 web.xml 中配置的是15分钟,则 getMaxInactiveInterval( ) 方法返回 900。

JSP application对象

JSP application 是 javax.servlet.ServletContext 的实例对象。在服务器部署应用和项目时,Web 容器仅创建一次 ServletContext 实例,也就是说 application 设置的任何属性和值可以用于整个应用(所有 JSP 页面)。可以将 application 对象看作 Web 应用的全局变量。一般用于保存应用程序的公用数据。

application 对象在 Web 应用运行时一直存在于服务器中,非常占用资源,因此在实际开发中不推荐使用,否则容易造成内存不足等情况。

application 对象常用方法如下:

方 法说 明
Object getAttribute(String attributeName)获取 attributeName(属性名称)对应的 object
void setAttribute(String attributeName, Object object)设置 attributeName 对应的属性值
Enumeration getAttributeNames()返回 application 对象中所有的 attributeName
void removeAttribute(String objectName)删除 application 对象中指定 attributeName 的属性
String getServerInfo()获取当前 Servlet 的版本信息
String getRealPath(String value)获取指定文件的实际路径

示例

可以使用 application 对象来保存 JSP 页面的访问人数,也就是我们常说的网站计数器,下面通过一个例子来演示。index.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        Integer count = (Integer) application.getAttribute("count");
        if (count == null) {
            count = 1;
        } else {
            count++;
        }
        application.setAttribute("count", count);
    %>
    <h2>编程帮网站计数器</h2>
    欢迎访问编程帮,您是第<%=count%>位访问客户!
</body>
</html>

运行结果如下:

首次访问count为1
首次访问count为1

连续刷新页面count增加
连续刷新页面count增加

JSP config对象

JSP config 是 javax.servlet.ServletConfig 的实例对象,一般用于获取页面和 Servlet 的初始化参数。

config 对象的常用方法如下:

方法说明
String getInitParameter(String paramname)获取指定的初始化参数值
Enumeration getInitParameterNames()获取当前页面所有的初始化参数值
ServletContext getServletContext()获取当前执行 Servlet 的 servletContext(Servlet 上下文)的值
String getServletName()获取当前执行 Servlet 的名称

示例

在 web.xml 文件中定义 Servlet 名称和映射,然后使用 config 对象获取信息。web.xml 代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    <servlet>
        <servlet-name>BianChengBangServlet</servlet-name>
        <jsp-file>/index.jsp</jsp-file>
        <init-param>
            <param-name>url</param-name>
            <param-value>http://www.biancheng.net</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>BianChengBangServlet</servlet-name>
        <url-pattern>/index</url-pattern>
    </servlet-mapping>
</web-app>

在 index.jsp 页面获取 Servlet 名称以及初始化参数,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        String sname = config.getServletName();
        String url = config.getInitParameter("url");
        out.print("Servlet名称为:" + sname + "<br>");
        out.print("初始化参数为:" + url + "<br>");
    %>
</body>
</html>

运行结果如下:

index.jsp运行结果

注意:因为 JSP 页面的实质是 Servlet,所以一般很少在 JSP 页面中使用 config 对象。

JSP pageContext对象

pageContext 是 javax.servlet.jsp.PageContext 的实例对象。pageContext 对象表示整个 JSP 页面,可以获取或删除以下对象的任意属性:

  • page
  • request
  • session
  • application

pageContext 常用的方法如下:

方 法说 明
Object findAttribute (String AttributeName)按 page、request、session、application 的顺序查找指定的属性,并返回对应的属性值。如果没有相应的属性,则返回 NULL
Object getAttribute (String AttributeName, int Scope)在指定范围内获取属性值。与 findAttribute 不同的是,getAttribute 需要指定查找范围
void removeAttribute(String AttributeName, int Scope)在指定范围内删除某属性
void setAttribute(String AttributeName, Object AttributeValue, int Scope)在指定范围内设置属性和属性值
Exception getException()返回当前页的 Exception 对象
ServletRequest getRequest()返回当前页的 request 对象
ServletResponse getResponse()返回当前页的 response 对象
ServletConfig getServletConfig()返回当前页的 ServletConfig 对象
HttpSession getSession()返回当前页的 session 对象
Object getPage()返回当前页的 page 对象
ServletContext getServletContext()返回当前页的 application 对象

示例

使用 PageContext 对象取得不同范围的属性值。index.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        request.setAttribute("info", "request范围的值");
        session.setAttribute("info", "session范围的值");
        application.setAttribute("info", "application范围的值");
    %>
    利用 pageContext 取出以下范围内各值(方法一):
    <br> request 设定的值:<%=pageContext.getRequest().getAttribute("info")%>
    <br> session 设定的值:<%=pageContext.getSession().getAttribute("info")%>
    <br> application 设的值:<%=pageContext.getServletContext().getAttribute("info")%>
    <hr>
    利用pageContext取出以下范围内各值(方法二):
    <br> 范围1(page)内的值:<%=pageContext.getAttribute("info", 1)%>
    <br> 范围2(request)内的值:<%=pageContext.getAttribute("info", 2)%>
    <br> 范围3(session)内的值:<%=pageContext.getAttribute("info", 3)%>
    <br> 范围4(application)内的值:<%=pageContext.getAttribute("info", 4)%>
    <hr>
    利用 pageContext 修改或删除某个范围内的值:
    <%
        pageContext.setAttribute("info", "修改request范围的值", 2);
    %>
    <br> 修改 request 设定的值:
    <br>
    <%=pageContext.getRequest().getAttribute("info")%>
    <br>
    <%
        pageContext.removeAttribute("info");
    %>
    删除 session 设定的值:<%=session.getAttribute("info")%>
</body>
</html>

运行结果如下:

index.jsp运行结果
index.jsp运行结果

JSP page对象

JSP page 的实质是 java.lang.Object 对象,相当于 Java 中的 this 关键字。page 对象是指当前的 JSP 页面本身,在实际开发中并不常用。

page 对象的常用方法如下:

方 法说 明
class getClass()返回当前页面所在类
int hashCode()返回当前页面的 hash 代码
String toString()将当前页面所在类转换成字符串
boolean equals(Object obj)比较对象和指定的对象是否相等
void copy (Object obj)把对象复制到指定的对象中
Object clone()复制对象

示例

下面通过一个简单的例子来演示 page 中的方法。index.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        Object obj;
        obj = null;
    %>
    返回当前页面所在类:<%=page.getClass()%>
    <br> 返回当前页面的 hash 代码:<%=page.hashCode()%>
    <br> 转换成 String 类的对象:<%=page.toString()%>
    <br> page和obj比较:<%=page.equals(obj)%>
    <br> page和this比较:<%=page.equals(this)%>
</body>
</html>

运行结果如下:

index.jsp运行结果

JSP Cookie的使用

Cookie 不是 JSP 内置对象,而是由 Netscape 公司发明,用来跟踪用户会话(session)的方式。

Cookie 由服务器生成并发送给浏览器(客户端),浏览器会将其以文本文件的形式存储在某个目录下。

例如,IE 浏览器把 cookie 信息保存在类似于 C://windows//cookies 的目录下,当用户再次访问某个网站时,服务器就会要求浏览器查找并返回之前发送的 cookie 信息,来识别此用户。

识别用户通常有以下步骤:

  1. 服务器把 cookie 信息发送到浏览器,例如:用户 ID、用户名称等信息。
  2. 浏览器在本地存储这些信息。
  3. 浏览器再次向服务器发送请求时,它会同时将本地存储的 cookie 信息一同发送给服务器,然后服务器使用这些信息来识别用户或其它。

cookie 的作用表现在以下方面:

  • 对特定对象的追踪,如用户的访问次数、最后访问时间等。
  • 统计网页的浏览次数。
  • 在 cookie 有效期内,记录用户的登录信息,简化下一次的登录过程。
  • 实现各种个性化服务,如”最近浏览过的商品“。

注意:由于 cookie 会将用户的个人信息保存在客户端,如用户名、计算机名、以及浏览和登录的网站等。这些信息可能会包含一些比较敏感的内容,所以从安全角度来说,使用 cookie 存在着一定的风险,因此不建议在 cookie 中保存比较重要或隐私的内容。

cookie方法

cookie 常用方法如下:

方法说明
public void setDomain(String pattern)设置 cookie 的域名,如 biancheng.net
public String getDomain()获取 cookie 的域名
public void setMaxAge(int expiry)设置 cookie 有效期,单位:秒 默认仅在当前会话中存在
public int getMaxAge()获取 cookie 有效期,单位:秒 默认为 -1,表示 cookie 保存到浏览器关闭为止
public String getName()返回 cookie 的名称,名称创建后将不能被修改
public void setValue(String newValue)设置 cookie 的值
public String getValue()获取 cookie 的值
public void setPath(String uri)设置 cookie 的路径 默认为当前页面目录以及子目录下的所有 URL
public String getPath()获取 cookie 的路径
public void setSecure(boolean flag)设置 cookie 是否要加密传输
public void setComment(String purpose)设置 cookie 注释
public String getComment()返回 cookie 注释,如果 cookie 没有注释,则返回 null

JSP使用cookie

JSP 使用 cookie 主要分为以下几个步骤。

1)创建 cookie 对象

创建 cookie 对象,name 代表 cookie 的名称,value 表示该名称对应的值,语法如下:

cookie cookie = new cookie(String name,String value);

注意:name 和 value 中不能包含空格和以下字符:

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

2)写入 cookie

创建 cookie 对象后,调用 response.addCookie() 方法写入 cookie,代码如下:

response.addcookie(cookie);

3)设置 cookie 有效期

调用 setMaxAge() 方法设置 cookie 的有效期(单位:秒),如将 cookie 有效期设置为 24 小时,代码如下:

cookie.setMaxAge(60*60*24); 

4)读取cookie

调用 request.getCookies() 方法读取 cookie,该方法返回 HTTP 请求中的 cookie 对象数组,需要通过遍历进行访问。

示例

通过 HTML 表单将客户端数据提交到 index.jsp 中,并设置 cookie。login.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <form action="index.jsp" method="get">
        站点名: <input type="text" name="name"> <br />
        网址: <input type="text" name="url" />
        <input type="submit" value="提交" />
    </form>
</body>
</html>

index.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.net.*"%>
<%
    // 解决中文乱码  
    String str = URLEncoder.encode(request.getParameter("name"), "utf-8");
    // 创建cookie对象
    cookie name = new cookie("name", str);
    cookie url = new cookie("url", request.getParameter("url"));
    // 设置cookie有效期为24小时。
    name.setMaxAge(60 * 60 * 24);
    url.setMaxAge(60 * 60 * 24);
    // 在响应头部添加cookie
    response.addcookie(name);
    response.addcookie(url);
%>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <b>网站名:</b>
    <%=request.getParameter("name")%><br>
    <b>网址:</b>
    <%=request.getParameter("url")%>
</body>
</html>

运行结果如下:

login.jsp运行结果
login.jsp页面运行结果

index.jsp
index.jsp页面运行结果

读取cookie

调用 request.getcookies() 方法,在 cookie.jsp 页面中读取 cookie,cookie.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.net.*"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        cookie cookie = null; //创建cookie对象
        cookie[] cookies = null;
        // 获取 cookie 的数据
        cookies = request.getcookies();
        if (cookies != null) {
            out.println("<h2> 获取cookie名称与对应值</h2>");
            for (int i = 0; i < cookies.length; i++) {
                cookie = cookies[i];
                out.print("参数名 : " + cookie.getName());
                out.print("<br>");
                out.print("参数值: " + URLDecoder.decode(cookie.getValue(), "utf-8") + " <br>");
                out.print("------------------------------------<br>");
            }
        } else {
            out.println("<h2>cookie为空</h2>");
        }
    %>
</body>
</html>

运行结果如下:

cookie.jsp运行结果

删除cookie

删除 cookie 步骤如下:

  • 获取 cookie
  • 将要删除的 cookie 有效期设置为 0
  • 调用 response.addCookie() 方法重新写入 cookie

删除参数名为“name”的 cookie,cookie.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.net.*"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        cookie cookie = null; //创建cookie对象
        cookie[] cookies = null;
        // 获取 cookie 的数据
        cookies = request.getcookies();
        if (cookies != null) {
            out.println("<h2> 获取cookie名称与对应值</h2>");
            for (int i = 0; i < cookies.length; i++) {
                cookie = cookies[i];
                //删除参数名为name的cookie
                if ((cookie.getName()).compareTo("name") == 0) {
                    cookie.setMaxAge(0);
                    response.addcookie(cookie);
                    out.print("删除 cookie: " + cookie.getName() + "<br/>");
                }
                out.print("参数名 : " + cookie.getName());
                out.print("<br>");
                out.print("参数值: " + URLDecoder.decode(cookie.getValue(), "utf-8") + " <br>");
                out.print("------------------------------------<br>");
            }
        } else {
            out.println("<h2>cookie为空</h2>");
        }
    %>
</body>
</html>

刷新 cookie.jsp 页面,运行结果如下:

cookie.jsp页面运行结果

注:也可以手动在浏览器中删除 cookie。

session和cookie的区别

session 和 cookie 的区别如下:

sessioncookie
将信息保存在服务器将信息保存在客户端
保存的值是 Object 类型保存的值是 String 类型
session 存储的数据随会话的结束而结束cookie 可以长期保存在客户端
安全性高,可以保存重要的信息安全性低,通常用于保存不重要的信息

实际开发中,需要根据不同的业务需求来选择采用哪种技术,例如,用户的用户名和密码等敏感信息不能使用 cookie 存储,淘宝购物的”最近浏览过的商品“,则可以使用 cookie 存储在客户端。

JSP JavaBean的使用

JavaBean 是可以重复使用的一个组件,是遵守 JavaBean API 规范的 Java 类。

一般情况下,JavaBean 要满足以下要求:

  • JavaBean 是一个公共类,并提供无参公有的构造方法
  • 需要被序列化并且实现了 Serializable 接口
  • 属性私有化
  • 具有公共的访问属性的 getter 和 setter 方法

Java 之父 James Gosling 在设计 Java 语言,为 Java 组件中封装数据的 Java 类进行命名时,看到了桌子上的咖啡豆,于是灵机一动,就把它命名为“JavaBean”,bean 翻译为“豆、豆子”。

在程序中,开发人员所要处理的无非是业务逻辑和数据,而这两种操作都可以封装成 JavaBean,一个应用程序中会使用很多的 JavaBean。由此可见,JavaBean 组件是应用程序的重要组成部分。

JavaBean示例

下面是一个 JavaBean 的简单示例,如下:

package entity;
import java.io.Serializable;
public class User implements Serializable {
   
    private static final long serialVersionUID = 1L;
   
    private int id;
    private String name;
    public User() {
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getId() {
        return id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

JavaBean属性

一个 JavaBean 可以有多个属性,属性应该是可以访问的,属性类型可以是任何合法的 Java 数据类型,包括自定义的类。

JavaBean 的每个属性通常都具有相应的 setter 和 getter 方法,setter 方法称为属性修改器,getter 方法称为属性访问器,如下:

1)getPropertyName( )

属性访问器以小写的 get 作为前缀,后跟属性名,且属性名的第一个字母也要改为大写。例如:属性名称为 name,则方法名称为 getName( ),用来读取该属性值。

2)setPropertyName( )

属性修改器以小写的 set 作为前缀,后跟属性名,且属性名的第一个字母也要改为大写。例如:属性名称为 name,则方法名称为 setName( ),用来设置该属性值。

JavaBean 的某个属性也可以只有 set 方法或 get 方法,这样的属性称之为只写或只读属性。

通过 getter 和 setter 方法访问 JavaBean,如下:

public static void main(String[] args) {
    User u = new User();// 创建对象
    u.setName("编程帮");// 设置对象的值
    System.out.println(u.getName());// 输出“编程帮”
}

JSP JDBC访问数据库

动态网页的主要特点就是能及时更新数据,这些更新的数据来源于数据库。学习本节内容需要您了解 JDBC,可以使用 JDBC 连接 MySQL 数据库。

本节数据库使用 MySQL 5.7,你可以点击 MySQL 官方网站 下载相应的 jar 包。

注意:MySQL 8.0 及之后的版本与之前的数据库连接有所不同:

  • 首先驱动 com.mysql.jdbc.Driver 更换为 com.mysql.cj.jdbc.Driver。
  • MySQL 8.0 及以上版本需要显式关闭 SSL 连接和指定 CST。

MySQL 8.0 及以上版本加载驱动与连接数据库方式如下:

<sql:setDataSource var="snapshot" driver="com.mysql.cj.jdbc.Driver"     url="jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8     user="root"  password="root"/>

下面使用 JSTL 对数据表中的数据进行增删改查。

示例

创建 website 数据表,并插入数据。点击下载 SQL 文件(下载后需要解压)

crud.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ 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"%>
<!DOCTYPE html>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%--
        JDBC驱动名、数据库 URL、数据库的用户名与密码
        useUnicode=true&characterEncoding=utf-8 防止中文乱码
     --%>
    <sql:setDataSource var="snapshot" driver="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8"
        user="root" password="root" />
    <%-- 插入数据
    <sql:update dataSource="${snapshot}" var="result">
        INSERT INTO website (NAME,url,age,country) VALUES ('京东', 'https://www.jd.com/', 15, 'CN');
    </sql:update> --%>
    <%-- 删除website表中id为9数据
    <c:set var="id" value="9" />
    <sql:update dataSource="${snapshot}" var="count">
         DELETE FROM website WHERE id = ?
         <sql:param value="${id}" />
    </sql:update>--%>
    <%-- 修改website表中id为8数据
    <c:set var="id" value="8" />
    <sql:update dataSource="${snapshot}" var="count">
         UPDATE website SET name="biancheng" WHERE id = ?
         <sql:param value="${id}" />
    </sql:update>--%>
    <%-- 查询数据 --%>
    <sql:query dataSource="${snapshot}" var="result">
        SELECT * from website;
    </sql:query>
    <table border="1" width="100%">
        <tr>
            <th>id</th>
            <th>name</th>
            <th>url</th>
            <th>age</th>
            <th>country</th>
        </tr>
        <c:forEach var="row" items="${result.rows}">
            <tr>
                <td><c:out value="${row.id}" /></td>
                <td><c:out value="${row.name}" /></td>
                <td><c:out value="${row.url}" /></td>
                <td><c:out value="${row.age}" /></td>
                <td><c:out value="${row.country}" /></td>
            </tr>
        </c:forEach>
    </table>
</body>
</html>

运行结果如下:

查询数据
查询数据

添加数据
添加数据

修改数据
修改数据

删除数据
删除数据

JSP分页功能

当数据有几万、几十万甚至上百万时,用户必须要拖动页面才能浏览更多的数据,很大程度的影响了用户体验。这时可以使用分页来显示数据,能够使数据更加清晰直观,且不受数量的限制。

分页的方式主要分为两种:

  • 将查询结果以集合等形式保存在内存中,翻页时从中取出一页数据显示。该方法可能导致用户浏览到的是过期数据,且如果数据量非常大,查询一次数据就会耗费很长时间,存储的数据也会占用大量的内存开销。
  • 每次翻页时只从数据库中检索出本页需要的数据。虽然每次翻页都需要查询数据库,但查询的记录数相对较少,总体开销不大,再配以连接池等技术进行优化,可以达到比较高的效率。

实现分页步骤

实现数据的分页显示,需要以下几个关键步骤:

1)确定每页显示的数据数量

确定每页显示的记录条数,即每次从数据库中需要查询出多少条记录用于页面显示。通常这个数量可以在开发时定义好,也可以由用户来选择。

2)计算显示的总页数

根据每页显示的记录条数计算总页数,即会产生多少页数据。显示的记录数量是已知的,而数据库中符合条件的记录总数是未知的,因此想要得到总页数,需要先得到符合条件的记录总数。

3)编写SQL语句

使用相应的 SQL 语句实现分页需求。例如,MySQL 中的 LIMIT 子句,SqlServer 中的 TOP、Oracle 中的 ROWNUM 等。

注意:本节使用的是 MySQL 数据库。不同的数据库厂商实现分页的 SQL 语句会存在差异,因此在实际应用中根据数据库的不同,需要修改相应的 SQL 语句。

示例

创建 website 数据表,并插入数据。点击下载 SQL 文件(下载后需要解压)。

Website 类的代码如下:

package net.biancheng.entity;
public class Website {
    private int id;
    private String name;
    private String url;
    private int age;
    private String country;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getCountry() {
        return country;
    }
    public void setCountry(String country) {
        this.country = country;
    }
}

基于方便代码管理的考虑,将有关分页的数据封装到一个 Page 类中,其中包括每页显示的数据数量、数据的总数量、显示的总页数、当前页码、每页显示的数据集合。Page 代码如下:

package net.biancheng.utils;
import java.util.List;
import net.biancheng.entity.Website;
public class Page {
    // 总页数
    private int totalPageCount = 0;
    // 页面大小,即每页显示记录数
    private int pageSize = 3;
    // 记录总数
    private int totalCount;
    // 当前页码
    private int currPageNo = 1;
    // 每页网站集合
    private List<Website> websiteList;
    public int getTotalPageCount() {
        return totalPageCount;
    }
    public void setTotalPageCount(int totalPageCount) {
        this.totalPageCount = totalPageCount;
    }
    public int getPageSize() {
        return pageSize;
    }
    public void setPageSize(int pageSize) {
        if (pageSize > 0)
            this.pageSize = pageSize;
    }
    public int getTotalCount() {
        return totalCount;
    }
    public void setTotalCount(int totalCount) {
        if (totalCount > 0) {
            this.totalCount = totalCount;
            // 计算总页数
            totalPageCount = this.totalCount % pageSize == 0 ? (this.totalCount / pageSize)
                    : (this.totalCount / pageSize + 1);
        }
    }
    public int getCurrPageNo() {
        if (currPageNo == 0)
            return 0;
        return currPageNo;
    }
    public void setCurrPageNo(int currPageNo) {
        if (currPageNo > 0)
            this.currPageNo = currPageNo;
    }
    public List<Website> getWebsiteList() {
        return websiteList;
    }
    public void setWebsiteList(List<Website> websiteList) {
        this.websiteList = websiteList;
    }
}

在 setTotalCount() 方法中,根据记录总数和每页显示记录数计算出总页数,使用三元运算符?:进行处理。如果记录总数能被每页显示记录数整除,则总页数为两者的商,如果不能被整除,则余出的记录数单独列为一页,总页数为两者的商再加 1。

WebsiteDao 代码如下:

package net.biancheng.dao;
import java.util.List;
import net.biancheng.entity.Website;
public interface WebsiteDao {
    // 查询总条数
    public int getTotcalCount();
    //根据起始下标和每页显示数量查询数据
    public List<Website> getPageWebsiteList(int pageNo, int pagesize);
}

WebsiteDaoImpl 代码如下:

package net.biancheng.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import net.biancheng.entity.Website;
public class WebsiteDaoImpl implements WebsiteDao {
    /**
     * 连接数据库
     */
    public static Connection getConnection() {
        Connection con = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return con;
    }
    /**
     * 查询总条数
     */
    @Override
    public int getTotcalCount() {
        int count = 0;
        try {
            Connection con = getConnection();
            String sql = "SELECT COUNT(id) FROM website";
            PreparedStatement ps = con.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();
            rs.next();
            count = rs.getInt(1);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return count;
    }
    @Override
    public List<Website> getPageWebsiteList(int pageNo, int pagesize) {
        PreparedStatement ps;
        ResultSet rs;
        List<Website> list = new ArrayList<Website>();
        try {
            Connection con = getConnection();
            String sql = "SELECT * FROM website LIMIT" + (pageNo - 1) * pagesize + "," + pagesize;
            ps = con.prepareStatement(sql);
            System.out.println(sql);
            rs = ps.executeQuery();
            while (rs.next()) {
                Website website = new Website();
                website.setId(rs.getInt(1));
                website.setName(rs.getString(2));
                website.setUrl(rs.getString(3));
                website.setAge(rs.getInt(4));
                website.setCountry(rs.getString(5));
                list.add(website);
            }
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
}

view.jsp 页面代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page
    import="java.util.*,net.biancheng.dao.*,net.biancheng.entity.*,net.biancheng.utils.*"%>
<html>
<head>
<title>编程帮(www.biancheng.net)</title>
</head>
<body>
    <%
        WebsiteDao websiteDao = new WebsiteDaoImpl();
        String pageNo = request.getParameter("page") != null ? request.getParameter("page") : "1";
        int currPageNo = Integer.parseInt(pageNo);
        Page p = new Page();
        p.setCurrPageNo(currPageNo);
        p.setPageSize(3);
        p.setTotalCount(websiteDao.getTotcalCount());
        List<Website> websiteList = websiteDao.getPageWebsiteList(p.getCurrPageNo(), p.getPageSize());
        p.setWebsiteList(websiteList);
        out.print("<h1>当前页面: " + currPageNo + "</h1>");
        out.print("<table border='1' cellpadding='4' width='60%'>");
        out.print("<tr><th>id</th><th>name</th><th>url</th><th>age</th><th>country</th></tr>");
        for (Website e : websiteList) {
            out.print("<tr><td>" + e.getId() + "</td><td>" + e.getName() + "</td><td>" + e.getUrl() + "</td><td>"
                    + e.getAge() + "</td><td>" + e.getCountry() + "</td></tr>");
        }
        out.print("</table>");
        for (int i = 1; i <= p.getTotalPageCount(); i++) {
    %>
    <a href="view.jsp?page=<%=i%>"><%=i%></a>
    <%
        }
    %>
</body>
</html>

运行结果如下:

view.jsp运行结果

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-05 21:35:51  更:2022-02-05 21:36:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:14:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码