一文带你轻松入门JSP技术

一、JSP 技术概述

JSP(JavaServer Pages)技术在 Java Web 开发领域占据着举足轻重的地位,它是一种基于 Java 语言的服务器端技术,用于创建动态网页。在 Web 开发的早期,静态 HTML 页面难以满足用户与网站之间复杂的交互需求,动态网页技术应运而生,JSP 便是其中的重要一员。

JSP 技术的核心优势在于它允许开发者在 HTML 页面中嵌入 Java 代码片段,从而使网页能够根据不同的条件和用户输入动态地生成内容。例如,一个电商网站的商品展示页面,可能需要根据用户的搜索关键词、浏览历史或者个性化推荐算法来展示不同的商品列表,这就可以通过 JSP 技术在 HTML 中嵌入 Java 代码来实现与数据库的交互以及数据的动态展示。

从技术体系架构来看,JSP 与 Servlet 紧密相连。Servlet 是 Java Web 开发中的基础组件,用于处理客户端的请求并生成响应。JSP 页面在首次被请求时,会被 Web 容器(如 Tomcat、Jetty 等)编译成 Servlet 类,然后由 Servlet 容器来执行。这种编译过程使得 JSP 在运行效率上相较于一些解释型的脚本语言(如 PHP)具有一定优势,因为 Servlet 在内存中是长期驻留的,后续对同一 JSP 页面的请求可以直接由已编译的 Servlet 类来处理,而无需重新解析和编译页面代码。

JSP 的跨平台特性也是其广受欢迎的重要原因之一。由于它基于 Java 语言,而 Java 语言具有 “一次编写,处处运行” 的特性,这使得 JSP 技术开发的 Web 应用可以在不同的操作系统和服务器环境中部署和运行,无需进行大量的代码修改和适配工作,为企业级应用的开发和部署提供了极大的便利,降低了开发成本和维护成本。

总的来说,JSP 技术为 Java Web 开发者提供了一种强大而灵活的方式来创建动态、交互性强且跨平台的 Web 应用程序,无论是小型的企业内部网站还是大型的电子商务平台,JSP 都能发挥其独特的优势,满足多样化的业务需求,是 Java Web 开发人员必须掌握的关键技术之一。

二、JSP 的运行环境搭建

JSP 的运行需要依赖特定的环境,主要包括 JDK(Java Development Kit)和 Web 服务器(如 Tomcat)。以下是详细的搭建步骤:

  1. JDK 的安装与配置
    • 首先,从 Oracle 官网下载适合您操作系统的 JDK 版本。建议选择较为稳定的长期支持版本,例如 JDK 8 或 JDK 11。
    • 下载完成后,双击安装程序,按照安装向导的提示进行安装。在安装过程中,注意选择安装路径,建议不要使用包含中文或空格的路径,以免出现潜在的问题。
    • 安装完成后,需要配置环境变量。以 Windows 系统为例,右键点击 “此电脑”,选择 “属性”,然后在弹出的窗口中点击 “高级系统设置”。在 “系统属性” 窗口的 “高级” 选项卡下,点击 “环境变量” 按钮。
    • 在 “系统变量” 区域,点击 “新建” 按钮,创建一个名为 “JAVA_HOME” 的变量,其值为 JDK 的安装目录(例如:C:\Program Files\Java\jdk1.8.0_271)。
    • 接着,找到 “Path” 变量,点击 “编辑” 按钮,在变量值的末尾添加 “;% JAVA_HOME%\bin;% JAVA_HOME%\jre\bin”(注意分号不要遗漏)。这一步是为了让系统能够在任何目录下找到 Java 的执行文件。
    • 最后,再新建一个名为 “CLASSPATH” 的系统变量,其值为 “.;% JAVA_HOME%\lib;% JAVA_HOME%\lib\tools.jar”(注意最前面的点和分号)。这个变量用于指定 Java 类的搜索路径。
    • 配置完成后,打开命令提示符(Win + R,输入 “cmd” 回车),输入 “java -version” 命令,如果能够正确显示 Java 的版本信息,则说明 JDK 安装和配置成功。
  2. Tomcat 的安装与配置
    • 前往 Apache Tomcat 官网下载适合您系统的 Tomcat 版本。通常,选择 Tomcat 8 或 Tomcat 9 即可满足大多数 JSP 开发的需求。
    • 下载完成后,将压缩包解压到您选择的目录(同样建议避免使用中文和空格)。例如,解压到 “C:\apache-tomcat-9.0.41”。
    • 配置 Tomcat 的环境变量。在系统变量中新建一个名为 “CATALINA_HOME” 的变量,其值为 Tomcat 的解压目录(如:C:\apache-tomcat-9.0.41)。
    • 然后,找到 “Path” 变量,编辑并在末尾添加 “;% CATALINA_HOME%\bin”,这样就可以在命令行中直接使用 Tomcat 的相关命令。
    • 为了方便启动和停止 Tomcat 服务,还可以在命令提示符中进入 Tomcat 的 “bin” 目录(例如:cd C:\apache-tomcat-9.0.41\bin),然后执行 “service.bat install” 命令,将 Tomcat 安装为 Windows 服务。这样,就可以在 “服务” 管理窗口中找到 “Apache Tomcat” 服务,方便地进行启动、停止和重启操作。
    • 启动 Tomcat 服务器。在命令提示符中进入 Tomcat 的 “bin” 目录,执行 “startup.bat” 命令。如果看到命令行中输出一系列启动信息,并且没有出现错误提示,说明 Tomcat 启动成功。此时,打开浏览器,在地址栏输入 “http://localhost:8080”,如果能够看到 Tomcat 的默认欢迎页面,则表示 Tomcat 安装和配置成功,并且可以正常对外提供 Web 服务。

通过以上步骤,我们就成功搭建了 JSP 的运行环境,为后续的 JSP 开发工作奠定了基础。在实际开发中,可能还会根据项目的需求安装一些其他的工具和库,但 JDK 和 Tomcat 是 JSP 开发的基础环境,务必确保它们的正确安装和配置。

三、JSP 的基本语法

(一)JSP 代码块

在 JSP 页面中,我们可以使用代码块(<% java语句 %>)来嵌入 Java 代码,实现各种操作,比如定义局部变量、编写流程控制语句等。例如,下面的代码定义了一个局部变量 i 并赋值为 10:

<% int i = 10; %>

我们还可以在代码块中编写条件判断语句,像下面这样判断一个数是否大于 5:

<% int num = 8;

if (num > 5) {

    out.println("这个数大于5");

} %>

代码块中的 Java 代码在 JSP 页面被翻译成 Servlet 后,会存在于_jspService()方法中,所以在这里定义的变量是局部变量,其生命周期从创建开始到页面关闭结束。需要注意的是,在代码块中不能定义方法哦,它主要是用于处理页面中的一些逻辑以及借助 JSP 的内置对象来完成诸如输出内容、处理请求、响应以及访问会话等操作呢。

(二)JSP 声明

JSP 声明(<%! java代码 %>)有着重要的作用,它可以用来定义全局变量、方法以及类等,这些定义在整个 JSP 页面中都是可以访问的哦。例如,我们定义一个全局变量 count 来记录页面的访问次数:

<%! int count = 0; %>

再比如定义一个方法来计算两个数的乘积:

<%!

    int multiply(int a, int b) {

        return a * b;

    }

%>

当服务器执行 JSP 页面并将其转换为 Servlet 类时,声明部分的内容会相应地翻译到 Servlet 中,也就是这里定义的是 Servlet 的类变量、类方法呢。不过在实际开发中,要谨慎使用 JSP 声明哦,因为过多或不合理地使用全局变量等可能会导致代码的可维护性变差等问题呢。

(三)JSP 输出指令

JSP 输出指令(<%= 表达式 %>)能够方便地将变量或者表达式的值输出到页面上,它不需要像使用 out.print() 这样的方式就能输出数据啦。比如说,我们有一个变量 name ,想要把它显示在页面中,可以这样写:

<% String name = "张三"; %>

<%= name %>

需要注意的是,表达式的值会被自动转化成 String 类型,所以可以在一个文本行中直接使用表达式,不用去考虑它是不是 HTML 标签哦。并且在 JSP 表达式中不能用分号来结束表达式,也不能在里面写多条语句呢,它主要就是用于向页面输出一些信息,让页面能够动态地展示数据呀。

(四)JSP 处理指令

JSP 处理指令是以 <%@ 开始,以 %> 结束,它可以对 JSP 页面进行各种属性设置呢。常见的处理指令有 page 指令、include 指令、taglib 指令等。

  • page 指令:用来定义当前页面的相关属性,通常放在 JSP 页面的顶部哦。比如可以设置页面的字符编码、内容类型以及导入需要的 Java 类等。示例如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.ArrayList" %>

这里设置了页面的内容类型为 text/html ,字符编码是 UTF-8 ,并且导入了 ArrayList 类呀。它还有像 errorPage 属性可以指定当前页面运行出现异常时跳转到的错误处理页面,isErrorPage 属性设置当前页面是否为错误处理页面等不同的属性可以按需配置呢。

  • include 指令:用于在 JSP 页面引入其它内容,像 JSP 文件、html 文件和文本文件等,语法是 <%@ include file="URL" %> 。例如,我们有一个公共的头部文件 header.jsp ,想要在多个 JSP 页面中都引入它,可以这样写:

<%@ include file="header.jsp" %>

这样在编译时,就会把指定文件的内容原封不动地拷贝到出现 include 指令的页面所在位置啦,使得代码可以复用,方便页面的模块化开发呢。

  • taglib 指令:主要是用来引入标签库的哦,其语法为 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> ,引入标签库后,就可以在页面中使用相应的标签来简化开发,将 Java 代码和 HTML 代码更好地分离,增强页面的可读性和可维护性呀。

通过合理地运用这些处理指令,我们就能更好地配置和组织 JSP 页面,实现丰富的功能啦。

四、JSP 的核心指令

(一)page 指令

page 指令在 JSP 开发中起着十分重要的作用,它可以定义当前页面的诸多相关属性,并且这些属性对整个页面都有效,与其书写的位置并无关联,不过习惯上会把它写在 JSP 页面的顶部。下面我们来深入分析指令的各个属性:

  • 导入包(import):在 JSP 页面中,使用 Java 类时往往需要导入相应的包,通过 page 指令的 import 属性就能实现这一操作。例如,当我们需要使用java.util.ArrayList类时,可以这样写:

<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.ArrayList" %>

它允许在同一文档中多次出现,我们既可以把它放在文档顶部附近,也可以放在相应的包首次使用之前。默认情况下,JSP 页面转换后的 Servlet 会自动导入java.lang.*javax.servlet.*javax.servlet.jsp.*javax.servlet.http.*等包,以及一些服务器特有的包,但编写代码时,不要依赖自动导入的服务器特有类,以免代码不可移植。

  • 设置错误页面(errorPage):在实际应用中,页面运行可能出现异常情况,这时就可以利用 errorPage 属性指定当前页面运行出现异常时跳转到的错误处理页面。比如:

<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="errorPage.jsp" %>

前提是对应的错误处理页面(如上述示例中的errorPage.jsp)需要设置isErrorPage="true"属性,来表明它是用于处理错误的页面。

  • 标识错误页面(isErrorPage):这个属性用于设置当前页面是否为错误处理页面,默认值为false,当设置为true时,页面可以获取异常信息并进行相应处理。示例如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>

这样在页面代码出现异常时,就可以通过内置的exception对象来获取异常相关信息并展示合适的提示内容等。

下面通过一个简单案例帮助大家理解其应用场景和实际效果。假设有一个用户登录页面login.jsp,在验证用户输入信息时可能出现数据库连接异常等情况,我们就可以在login.jsp中设置errorPage属性指向一个专门处理错误的errorPage.jsp页面,在errorPage.jsp中设置isErrorPage="true",然后通过exception对象输出错误提示信息给用户,告知登录出现了什么问题,方便用户知晓并采取相应措施。

(二)include 指令

include 指令用于在 JSP 页面引入其它内容,主要分为静态包含和动态包含这两种形式,它们各有特点并且适用于不同的应用场景。

  • 静态包含

语法格式为<%@ include file="URL" %>,例如<%@ include file="header.jsp" %>,它表示在 JSP 编译时将指定文件(如header.jsp)的内容原封不动地拷贝到出现include指令的页面所在位置。被引入的文件可以使用任意的扩展名,即便扩展名是.html,JSP 引擎也会按照处理 JSP 页面的方式处理其里面的内容,不过为了便于区分管理,一般使用.jspf作为静态引入文件的扩展名。其优势在于处理速度快,由于页面不需要变化,静态化,不容易出错,常用于公共资源设置,像页面的公共头部、底部等部分。但需要注意的是,除了importpageEncoding属性之外,page指令的其他属性不能在这两个页面(包含页面和被包含页面)中有不同的设置值;插入文件的路径一般不以 “/” 开头,而是使用相对路径,这里的相对路径是相对于当前文件,并且被引入文件的元素除了指令元素之外,都会被转换成 Java 源代码并插入当前 JSP 页面所翻译的 Servlet 源文件中,插入位置与include指令在当前 JSP 页面中的位置保持一致。

  • 动态包含

语法格式为<jsp:include file="test.jsp" flush="true"/>,它是在页面请求处理阶段进行包含操作,支持动态内容生成,还可以向被包含页面传递参数,功能模块细化好,灵活性佳,易于管理和编码,适用于需要包含的内容会随请求变化,或需要向被包含页面传递参数的场景,比如根据用户权限不同动态加载不同的菜单页面等。不过它也有不足,动态的引入时需要频繁的变化和页面信息的更新和交互,要占用大量的资源开销,会降低页面的访问速度。使用动态包含时,要注意jsp:include动作的flush属性必须要定义,且设置的flush必须要为true,同时在jsp:include动作中指定的页面必须是同一 web 应用程序的一部分,否则将导致请求时错误。

在实际项目需求中,如果是引入一些基本固定不变的公共部分,如网站的通用头部导航栏、版权声明等内容,选择静态包含会更合适;而要是需要根据不同用户操作、不同业务逻辑动态加载不同的模块内容,像电商网站根据用户不同的浏览历史推荐不同的商品展示模块等情况,那动态包含就是更好的选择了。同时,使用过程中也要特别留意上述提到的一些注意事项,比如变量命名冲突问题,避免在包含的不同页面中出现同名变量导致逻辑混乱等情况出现。

(三)taglib 指令

taglib 指令主要的作用是用来引入标签库,其基本语法为<%@ taglib prefix="自定义标签的前缀" uri="标签库URl" %>,比如常见的<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>,这里的prefix是指定标签的前缀,uri用于指定标签库文件的存放位置。

引入标签库后,就能在 JSP 页面中使用相应的标签来简化开发,将 Java 代码和 HTML 代码更好地分离,增强页面的可读性和可维护性,为后续学习 JSTL 标签库打下良好基础。例如在使用 JSTL 标签库时,引入了上述的core标签库后,就可以使用像<c:forEach>标签来遍历集合数据,<c:if>标签进行条件判断等操作,让页面的代码结构更加清晰简洁,不再是把大量的 Java 逻辑代码都嵌套在 HTML 代码中,极大地提升了代码的可维护性和开发效率。

在实际使用时,需要注意定义标签时,不能使用jspjspxjavajavaxservletsunsunw作为前缀,因为这些前缀是 JSP 保留的。并且如果使用自定义的uri,还需要在该工程的web.xml下加入相应的配置信息来让编译器能够找到对应的标签功能支持类,确保标签可以正常工作;要是使用标准定义的uri(像引入 JSTL 核心标签库的标准uri),则不用在web.xml下额外添加配置,直接就能使用相应的标签库功能了。

五、JSP 的动作标签

(一)转发与重定向

在 JSP 开发中,实现页面跳转主要有转发(forward)和重定向(redirect)两种方式,它们有着明显的区别并且适用于不同的应用场景,下面我们来详细了解一下。

  1. 使用方法及跳转范围
    • 转发(forward:通过request.getRequestDispatcher().forward()方法来实现。它只能将请求转发给同一个 WEB 应用中的组件。例如,如果在一个 Web 应用中有多个 JSP 页面或者 Servlet 需要协同处理一个请求,在某个环节就可以使用转发将请求传递给其他的页面或者 Servlet 进行后续处理。
    • 重定向(redirect:利用response.sendRedirect()方法来操作。它不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对 URL 重定向到其他站点的资源。比如,当用户登录成功后,需要跳转到网站的首页(可能首页在另外一个模块或者应用中),就可以采用重定向的方式。
  2. 浏览器地址栏变化情况
    • 转发(forward:转发过程结束后,浏览器地址栏保持初始的 URL 地址不变。这意味着对于用户来说,从视觉上感觉就是在同一个页面进行操作,浏览器并不知道在服务器程序内部发生了转发行为,就好像服务器内部自己协调完成了一系列的工作然后返回了最终结果给浏览器。
    • 重定向(redirect:重定向访问过程结束后,浏览器地址栏中显示的 URL 会发生改变,由初始的 URL 地址变成重定向的目标 URL。用户能够直观地看到地址栏的变化,知道自己跳转到了一个新的页面地址。
  3. 请求响应过程的差异
    • 转发(forward:在服务器端内部将请求转发给另外一个资源,属于同一个访问请求和响应过程,所以调用者与被调用者之间共享相同的request对象和response对象。例如,在前一个页面往request对象中设置了一些属性(比如用户登录时存放了用户的基本信息),转发到下一个页面时,依然可以通过request对象获取到这些属性值来进行后续的业务逻辑处理。
    • 重定向(redirect:它是先由服务器向浏览器返回一个响应,浏览器接受此响应后再发送一个新的http请求到服务器,这属于两次不同的请求,所以调用者与被调用者使用各自的request对象和response对象。也就意味着在重定向之前放在request对象中的属性值,在重定向后的页面是无法获取到的,因为已经是一个全新的请求了。
  4. 性能方面的不同

一般情况下,转发的速度比重定向要快,因为重定向需要浏览器再次发起新的请求,经历建立连接等一系列操作,而转发只是服务器内部的资源调用,相对开销较小。不过在一些特定场景下,还是需要根据实际业务需求来选择合适的方式,不能仅仅考虑性能因素。

  1. 适用场景举例
    • 转发(forward:对于同一个 WEB 应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要使用HttpServletRequest.setAttribute方法传递预处理结果,那就应该使用转发。比如在一个电商网站中,用户在商品列表页面选择了某个商品后,跳转到商品详情页面之前,可能需要在后台先根据商品 ID 查询商品的详细信息并放到request对象中,然后转发到商品详情页面进行展示,这样详情页面就能直接获取到之前存放的商品信息了。
    • 重定向(redirect:不同 WEB 应用程序之间的重定向,特别是要重定向到另外一个 WEB 站点上的资源的情况,都应该使用重定向。例如,在一个网站中点击某个合作方的链接,跳转到合作方的网站页面,就需要通过重定向来实现。还有一种常见的场景是避免在用户重新加载页面时两次调用相同的动作,比如提交产品表单的时候,执行保存的方法将会被调用,并执行相应的动作,如果提交表单后重新加载页面,为了避免保存方法再次被调用(可能导致重复添加数据等问题),可以将用户重定向到一个不同的页面。

以下是简单的代码示例展示它们的使用方式:

转发示例代码(假设在login.jsp中进行登录验证后转发到welcome.jsp

<%

    // 假设这里进行了登录验证逻辑,验证通过后进行转发

    if (/* 登录验证通过的条件判断 */) {

        request.getRequestDispatcher("welcome.jsp").forward(request, response);

    }

%>

重定向示例代码(同样假设登录验证后重定向到index.jsp

<%

    // 假设这里进行了登录验证逻辑,验证通过后进行重定向

    if (/* 登录验证通过的条件判断 */) {

        response.sendRedirect("index.jsp");

    }

%>

通过掌握转发和重定向的这些区别以及适用场景,能够在开发 JSP 应用时更合理地实现页面导航,提升用户体验。

(二)包含其他页面

在 JSP 中,我们可以通过特定的方式在一个 JSP 页面中包含其他页面,常用的有include指令和<jsp:include>动作标签,它们各有特点并且使用场景有所不同,下面为大家详细介绍。

  1. include指令(<%@ include file="URL" %>

<%@ include file="header.jsp" %>

这里file属性指定要引入的文件路径,可以是相对路径(相对于当前文件),也可以是绝对路径。被引入的文件可以使用任意的扩展名,即便扩展名是.html,JSP 引擎也会按照处理 JSP 页面的方式处理其里面的内容,不过为了便于区分管理,一般使用.jspf作为静态引入文件的扩展名。

    • 使用方法:例如,当我们有一个公共的头部文件header.jsp,想要在多个 JSP 页面中都引入它,可以在需要引入的 JSP 页面中这样写:
    • 执行时机与特点:它是在 JSP 编译时将指定文件的内容原封不动地拷贝到出现include指令的页面所在位置,然后 JSP 编译器再对这个合成的文件进行编译,最终编译后的文件只有一个。这意味着它的处理速度比较快,由于页面内容在编译时就固定了,相对不容易出错,常用于公共资源设置,像页面的公共头部、底部等部分。不过需要注意的是,除了importpageEncoding属性之外,page指令的其他属性不能在包含页面和被包含页面中有不同的设置值。
    • 参数传递方面include指令不支持直接传递参数到被包含的页面,如果要共享数据等,更多是依赖page作用域或者其他全局的方式来实现(比如设置为全局变量等,但这种方式要谨慎使用,避免代码可维护性变差)。
  1. <jsp:include>动作标签(<jsp:include page="test.jsp" flush="true"/>

<jsp:include page="content.jsp" flush="true">

    <jsp:param name="paramName" value="paramValue"/>

</jsp:include>

其中page属性指定被包含的文件路径,同样是相对路径或者绝对路径,flush属性必须要定义,且设置的flush必须要为true,表示页面可刷新。而<jsp:param>子标签可以用来传递参数,参数以 “参数名 - 值” 对的形式传递到被包含的页面中。

    • 使用方法:示例代码如下,如果要包含一个名为content.jsp的页面,并且传递一个参数过去,可以这样写:
    • 执行时机与特点:它是在页面请求处理阶段进行包含操作,支持动态内容生成,还可以向被包含页面传递参数,功能模块细化好,灵活性佳,易于管理和编码,适用于需要包含的内容会随请求变化,或需要向被包含页面传递参数的场景,比如根据用户权限不同动态加载不同的菜单页面等。不过它也有不足,动态的引入时需要频繁的变化和页面信息的更新和交互,要占用大量的资源开销,会降低页面的访问速度。同时在jsp:include动作中指定的页面必须是同一 web 应用程序的一部分,否则将导致请求时错误。
    • 参数传递方面:通过<jsp:param>标签传递参数后,在被包含的页面中可以使用request.getParameter("参数名称")来获取相应参数的值,这使得不同页面之间可以根据需求灵活地传递数据,实现更动态、交互性更强的页面组合。

以下是一个简单的实际案例来对比它们的使用:

假设有一个网站页面,包含固定的头部(header.jsp)、根据用户权限动态变化的主体内容(content.jsp,不同用户看到不同的菜单等内容)以及固定的底部(footer.jsp)。

对于固定的头部和底部,我们可以使用include指令来引入,示例代码如下(以引入头部为例,底部同理):

index.jsp页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ include file="header.jsp" %>

<!-- 这里是主体内容部分,可能是其他的HTML标签或者JSP代码等 -->

<%@ include file="footer.jsp" %>

对于动态变化的主体内容部分,使用<jsp:include>动作标签并传递参数(假设根据用户权限不同,传递一个表示权限级别的参数userRole),示例代码如下:

index.jsp页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ include file="header.jsp" %>

<jsp:include page="content.jsp" flush="true">

    <jsp:param name="userRole" value="<%= getUserRole() %>"/> <!-- 这里假设 getUserRole() 方法是获取当前用户权限级别的方法 -->

</jsp:include>

<%@ include file="footer.jsp" %>

content.jsp页面中,就可以通过request.getParameter("userRole")获取传递过来的用户权限参数,然后根据这个参数来动态展示不同的菜单等内容了。

通过合理运用这两种包含其他页面的方式,我们可以在 JSP 开发中更好地实现代码的复用和模块化开发,提升开发效率和代码的可维护性。

(三)使用 JavaBean 对象

在 JSP 页面中,经常会用到 JavaBean 对象来实现数据的封装和处理,从而提高代码的可读性和可维护性,主要通过<jsp:useBean><jsp:setProperty><jsp:getProperty>这三个动作标签来操作 JavaBean 对象,下面结合 JavaBean 的概念为大家详细阐述它们的作用和使用方法。

  1. <jsp:useBean>动作标签
    • 语法格式与作用:其语法格式为<jsp:useBean id="name" class="classname" scope="page|request|session|application"/>。它用于在 JSP 页面中实例化一个或多个 JavaBean 组件,这些被实例化的 JavaBean 对象可以在 JSP 页面中被调用。其中id属性用来声明所创建的 JavaBean 实例的名称,在页面中可以通过这个id的值来引用 JavaBean;class属性指定需要实例化的 JavaBean 的完整路径和类名,例如class="com.example.UserBean"(这里假设UserBean是我们自定义的一个 JavaBean 类);scope属性则指定 JavaBean 实例对象的生命周期,其值可以是pagerequestsessionapplication之一,不同的范围有着不同的作用范围和特点。
    • 不同scope范围的说明
      • page范围page范围的 Bean 仅仅在创建它们的页中才能访问。一个page范围的 Bean 经常用于单一实例计算和事务,而不需要进行跨页计算的情况。比如在一个简单的 JSP 页面中,只是临时计算一些数据并展示,这些数据不需要在其他页面使用,就可以将相关的 JavaBean 设置为page范围。
      • request范围request范围的 JavaBean 在客户端的一次请求响应过程中均有效。在这个请求过程中,并不一定只能处理一个页面,当一个页面提交以后,响应它的过程可以经过一个或者一系列页面,也就是说,可以由响应它的页面再forward(转发)或者include(包含)其他页面进行处理,最后所有页面都处理完返回客户端,整个过程都是在一个request里进行处理的。因此,只要是在一个请求过程中的页面,都可以共享request范围的 JavaBean。例如,用户在一个表单页面提交数据后,经过多个 JSP 页面或者 Servlet 进行数据处理和验证,这些页面间可以通过request范围的 JavaBean 来传递和共享数据。
      • session范围session范围的 JavaBean 在客户端的同一个session过程中均有效,服务器会为新访问的用户创建HttpSession对象,这也是在其中存储session范围的 JavaBean 的地方。比如用户登录后,整个登录会话期间需要保存用户的一些基本信息(用户名、用户权限等),就可以将对应的 JavaBean 设置为session范围,方便在不同的页面操作中随时获取这些信息。
      • application范围application范围内的 JavaBean 一旦建立,除非调用代码将其撤销,或者服务器重新启动,否则此 JavaBean 的实例将一直驻留在服务器内存中。通常用于整个应用程序共享的数据,比如网站的全局配置信息等,可以通过application范围的 JavaBean 来存储和访问。
  2. <jsp:setProperty>动作标签
    • 作用与使用场景:主要用于给 JavaBean 对象的属性赋值,它有几种不同的使用方式。
    • 常用的赋值方式介绍

<jsp:useBean id="user" class="com.example.UserBean" scope="page"/>

<jsp:setProperty name="user" property="*"/>

这里假设UserBean中有与表单提交参数同名的属性(比如表单有usernamepassword字段,UserBean中也有对应的usernamepassword属性),就可以通过property="*"这种方式将表单参数值自动赋给对应的 JavaBean 属性。

<jsp:useBean id="book" class="com.example.BookBean" scope="page"/>

<jsp:setProperty name="book" property="isbn" param="parameterIsbn"/>

这里由于表单参数与 JavaBean 的属性名不一致,这句话表示将表单参数"parameterIsbn"的值赋给名称为"book"的 JavaBean 的属性"isbn"

<jsp:useBean id="product" class="com.example.ProductBean" scope="page"/>

<jsp:setProperty name="product" property="price" value="99.99"/>

上述代码就是将ProductBean中的price属性设置为固定值99.99

      • 同名属性赋值(简便形式):当表单对象中的参数名称与 Bean 的属性名称一致时,可采用如下简便的形式,将表单对象中的参数值赋给 JavaBean 的同名属性。例如:
      • 指定参数赋值(属性名与表单参数名不一致时):当表单对象中的参数名称与 Bean 的属性名称不一致时,则需要逐个设定属性值,而且,还要通过param指明属性值来自表单的哪个参数。具体语法形式如下:
      • 指定固定值赋值:还可以使用<jsp:setProperty>动作指令,用value指定的任意值给 JavaBean 的属性赋值,语句如下:
  1. <jsp:getProperty>动作标签

<jsp:useBean id="student" class="com.example.StudentBean" scope="page"/>

<jsp:setProperty name="student" property="name" value="张三"/>

姓名:<jsp:getProperty name="student" property="name"/>

上述代码先通过<jsp:useBean>实例化了StudentBean对象,然后使用<jsp:setProperty>设置了name属性的值为张三,最后通过<jsp:getProperty>获取并展示了name属性的值。

    • 作用与使用方法:与<jsp:setProperty>相对应,用于从 JavaBean 中获取指定的属性值。这个动作元素相对比较容易,只需要指定name参数和property参数。name即为在<jsp:useBean>动作指令中定义的表示 JavaBean 对象名称的id属性,property属性指定了想要获取的 JavaBean 的属性名。例如:

以下是一个完整的示例,展示如何在 JSP 页面中结合这三个动作标签操作 JavaBean 对象:

假设有一个简单的用户注册功能,涉及到用户输入信息的封装和展示。

首先定义一个UserBean类(这里用 Java 代码简单示意,实际开发中会放在合适的包结构下):

package com.example;

public class UserBean {

    private String username;

    private String password;

    private String email;

    // 生成对应的getter和setter方法

    public String getUsername() {

        return username;

    }

    public void setUsername(String username) {

        this.username = username;

    }

    public String getPassword() {

        return password;

    }

    public void setPassword(String password) {

        this.password = password;

    }

    public String getEmail() {

        return email;

    }

    public void setEmail(String email) {

       

## 六、JSP的内置对象

![need_search_image_by_title]()

### (一)九大内置对象简介

JSP技术的设计者为便于开发人员在编写JSP页面时获得一些常用的web对象的引用,特意定义了9个相应的变量,这些就是JSP的内置对象。它们分别是:`request`、`response`、`session`、`application`、`config`、`out`、`pageContext`、`page`、`exception`。

- **`request`对象**:它是`javax.servlet.http.HttpServletRequest`类型的对象,代表客户端的请求信息。其作用域为一次请求,主要用于获取客户端提交的数据,包括通过GET或POST请求发送的参数、头信息、远程地址、服务器名称、服务器端口、内容类型、字符编码等,还可以用于在请求范围内设置、获取和删除属性,在一个请求的多个处理环节(如多个JSP页面或Servlet之间的转发)中传递数据。

- **`response`对象**:是`javax.servlet.http.HttpServletResponse`类的实例,代表对客户端的响应。它主要用于向客户端发送响应信息,例如设置响应的字符编码、内容类型,将响应重定向到另一个资源、发送错误等,其作用域主要在当前JSP页面内有效,用于处理当前页面的响应逻辑。

- **`session`对象**:属于`javax.servlet.http.HttpSession`类型,由服务器自动创建与用户请求相关的对象,用于保存该用户的信息,跟踪用户的操作状态。服务器为每个用户生成一个`session`对象,在整个会话期间(从用户打开浏览器连接到服务器,直到关闭浏览器离开服务器)有效,可用于存储用户登录后的身份信息、购物车数据等,实现跨页面的数据共享和用户状态跟踪,其内部使用`Map`来保存数据,格式为“Key/value”,`value`可以是复杂的对象类型,而不仅仅局限于字符串类型。

- **`application`对象**:是`javax.servlet.ServletContext`类型的对象,可将信息保存在服务器中,直到服务器关闭,否则`application`对象中保存的信息会在整个应用中都有效。类似于系统的“全局变量”,用于存储整个应用程序共享的数据,如网站的全局配置信息、在线用户数量等,在整个应用程序的多个页面、请求和会话中都可以访问和修改这些共享数据。

- **`config`对象**:是`ServletConfig`类型的隐式对象,主要作用是取得服务器的配置信息。开发者可以在`web.xml`文件中为应用程序环境中的Servlet程序和JSP页面提供初始化参数,通过`pageConext`对象的`getServletConfig()`方法可以获取一个`config`对象,在Servlet初始化时,容器把某些信息通过`config`对象传递给这个Servlet,用于获取特定JSP页面的初始化参数,如数据库连接池的配置参数等。

- **`out`对象**:用于在Web浏览器内输出信息,是`JspWriter`类的实例,负责管理应用服务器上的输出缓冲区。在使用`out`对象输出数据时,可以对数据缓冲区进行操作,如清除缓冲区内容、获取缓冲区大小、判断缓冲区满时的处理方式等,当满足一定条件(如缓冲区满、刷新缓冲区、关闭缓冲区或JSP页面执行完毕)时,缓冲区的内容会被写出到客户端,向客户端发送文本数据,类似于`ServletResponse.getWriter()`方法返回的`PrintWriter`对象,但`JspWriter`相当于一种带缓存功能的`PrintWriter`,通过设置`page`指令的`buffer`属性可以调整它的缓存大小,甚至关闭它的缓存。

- **`pageContext`对象**:是`PageContext`类的隐式对象,作用是取得任何范围的参数,它不仅封装了对其它8大隐式对象的引用,自身还是一个域对象(容器),可以用来保存数据,并且封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。在JSP自定义标签开发中特别重要,如果在编程过程中,把`pageContext`对象传递给一个普通java对象,那么这个java对象将可以获取8大隐式对象,从而可以和浏览器交互,成为一个动态web资源,其常用方法包括`setAttribute`、`getAttribute`、`removeAttribute`、`findAttribute`等,`findAttribute`方法按照查找顺序“page→request→session→application”在这四个对象中去查找属性值,只要找到了就返回属性值,如果四个对象都没有找到要查找的属性,则返回一个`null`。

- **`page`对象**:代表JSP本身,是`java.lang.Object`类的实例化对象,类似于Java编程中的`this`指针,只有在JSP页面内才是合法的,本质上包含当前Servlet接口引用的变量,在实际开发中很少直接使用,了解即可。

- **`exception`对象**:是`java.lang.Throwable`类的对象,作用是显示异常信息,但只能用于错误页面(即`page`指令中设置`isErrorPage="true"`的页面)。当JSP页面出现未捕获的异常时,会生成`exception`对象,并把`exception`对象传送到在`page`指令中设定的错误页面中,然后在错误页面中处理相应的`exception`对象,几乎定义了所有异常情况,在Java程序中,通常使用`try/catch`关键字来处理异常情况,而在JSP页面中,如果出现异常且没有在当前页面进行捕获处理,就会涉及到`exception`对象在错误页面的处理机制。

这些内置对象在JSP开发中起着至关重要的作用,开发者可以直接使用它们来实现各种功能,无需手动实例化,大大提高了开发效率,同时也为JSP页面与服务器、客户端之间的交互提供了便利,使得开发者能够更加专注于业务逻辑的实现,而不是底层对象的创建和管理,是JSP技术的重要组成部分,深入理解和熟练掌握这些内置对象的用法,对于开发高质量的JSP应用程序具有重要意义。

### (二)重点内置对象详解

在JSP的九大内置对象中,`request`、`response`、`session`、`application`和`out`等对象在日常开发中使用频率较高,下面我们将对这些常用的内置对象进行详细讲解,并通过示例代码演示其具体用法。

1. **`request`对象**:

    - **获取客户端信息**:`request`对象可以获取客户端的多种信息,如请求参数、头信息、客户端IP地址等。例如,通过`getParameter()`方法可以获取客户端通过GET或POST方式提交的表单参数值。假设我们有一个登录页面,用户在表单中输入用户名和密码后提交,在处理登录请求的JSP页面中,可以使用以下代码获取用户名和密码:

```jsp

<%

    String username = request.getParameter("username");

    String password = request.getParameter("password");

%>

这里的"username""password"是表单中输入框的name属性值,通过request.getParameter()方法就能获取到用户输入的具体值,从而进行后续的登录验证等操作。

  • 获取请求头信息:使用getHeader()方法可以获取请求头中的特定信息,比如获取用户浏览器的类型:

<%

    String userAgent = request.getHeader("User-Agent");

    out.println("用户浏览器类型:" + userAgent);

%>

这在一些需要根据浏览器类型进行不同处理的场景中非常有用,例如对于某些老旧浏览器,可能需要提供不同的页面布局或者功能限制提示等。

  • 设置请求属性request.setAttribute()方法可以在请求范围内设置属性,以便在同一请求的不同 JSP 页面或 Servlet 之间共享数据。例如,在一个 Servlet 中进行了一些数据的查询和处理后,将结果数据设置到request属性中,然后转发到一个 JSP 页面进行展示:

// 在Servlet中

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // 假设这里查询到了一个用户列表

    List<User> userList = userService.getUsers();

    request.setAttribute("userList", userList);

    request.getRequestDispatcher("userList.jsp").forward(request, response);

}

userList.jsp页面中,可以通过request.getAttribute("userList")获取到这个用户列表数据并进行展示:

<%

    List<User> userList = (List<User>) request.getAttribute("userList");

    if (userList!= null) {

        for (User user : userList) {

            out.println("用户名:" + user.getUsername() + "<br>");

        }

    }

%>

  1. response对象
    • 设置响应头信息:可以使用setHeader()方法设置响应头信息,比如设置页面的缓存过期时间:

<%

    response.setHeader("Cache-Control", "no-cache");

    response.setDateHeader("Expires", 0);

%>

这样设置后,浏览器在访问该页面时将不会缓存页面内容,每次都会向服务器请求最新的页面数据,适用于一些需要实时更新数据的页面,如股票行情页面、实时新闻页面等。

  • 重定向页面:通过sendRedirect()方法可以将客户端的请求重定向到另一个 URL 地址。例如,在用户登录成功后,将其重定向到网站的首页:

<%

    if (/* 登录成功的条件判断 */) {

        response.sendRedirect("index.jsp");

    }

%>

这里的"index.jsp"就是重定向的目标页面地址,注意重定向会使浏览器地址栏发生改变,并且是一个新的请求,原请求中的request属性将无法在重定向后的页面中获取到。

  1. session对象
    • 实现会话跟踪session对象用于在多个请求之间跟踪用户的状态信息。例如,在用户登录成功后,可以将用户的登录信息存储到session中:

<%

    if (/* 登录验证通过的条件判断 */) {

        // 假设这里有一个User对象,包含用户的相关信息

        User user = new User();

        user.setUsername(username);

        user.setPassword(password);

        session.setAttribute("user", user);

    }

%>

在后续的其他页面中,只要用户的session未过期,就可以通过session.getAttribute("user")获取到用户的登录信息,从而判断用户是否已经登录,并根据用户的身份展示不同的内容或者提供不同的操作权限:

<%

    User user = (User) session.getAttribute("user");

    if (user!= null) {

        out.println("欢迎您," + user.getUsername() + "!");

    } else {

        out.println("您尚未登录,请先登录。");

    }

%>

  • 设置会话超时时间:可以使用setMaxInactiveInterval()方法设置session的超时时间(以秒为单位),例如:

<%

    session.setMaxInactiveInterval(1800); // 设置为30分钟

%>

这样,如果用户在 30 分钟内没有任何操作,session将会自动失效,用户需要重新登录,这有助于提高应用程序的安全性和资源利用率,避免长时间占用服务器资源的无效session存在。

  1. application对象
    • 共享全局数据application对象用于在整个应用程序范围内共享数据。例如,可以在应用启动时,将一些全局配置信息存储到application中:

// 在ServletContextListener的contextInitialized方法中

public void contextInitialized(ServletContextEvent sce) {

    ServletContext application = sce.getServletContext();

    // 假设这里有一些全局配置参数

    Map<String, String> configMap = new HashMap<>();

    configMap.put("siteName", "My Web Application");

    configMap.put("dbUrl", "jdbc:mysql://localhost:3306/mydb");

    application.setAttribute("configMap", configMap);

}

在任何 JSP 页面或 Servlet 中,都可以通过application.getAttribute("configMap")获取到这些全局配置信息:

<%

    Map<String, String> configMap = (Map<String, String>) application.getAttribute("configMap");

    if (configMap!= null) {

        String siteName = configMap.get("siteName");

        out.println("网站名称:" + siteName);

    }

%>

  • 统计在线用户数量:可以利用application对象来统计在线用户的数量。在用户登录时,将在线用户数量加 1;在用户退出登录或session超时失效时,将在线用户数量减 1。例如:

// 在用户登录的Servlet中

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    HttpSession session = request.getSession();

    ServletContext application = getServletContext();

    Integer onlineCount = (Integer) application.getAttribute("onlineCount");

    if (onlineCount == null) {

        onlineCount = 0;

    }

    onlineCount++;

    application.setAttribute("onlineCount", onlineCount);

    // 其他登录处理逻辑

}

// 在用户退出登录的Servlet中

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    HttpSession session = request.getSession(false);

    if (session!= null) {

        session.invalidate();

    }

    ServletContext application = getServletContext();

    Integer onlineCount = (Integer) application.getAttribute("onlineCount");

    if (onlineCount!= null && onlineCount > 0) {

        onlineCount--;

    }

    application.setAttribute("onlineCount", onlineCount);

    // 其他退出登录处理逻辑

}

在一个显示在线用户数量的 JSP 页面中,可以通过application.getAttribute("onlineCount")获取并展示当前的在线用户数量:

<%

    Integer onlineCount = (Integer) application.getAttribute("onlineCount");

    if (onlineCount!= null) {

        out.println("当前在线用户数量:" + onlineCount);

    }

%>

  1. out对象
    • 输出数据到页面out对象用于向客户端输出文本数据,例如:

<%

    out.println("这是一段输出到页面的文本信息。");

%>

它还可以输出变量的值、表达式的结果等,是在 JSP 页面中向客户端展示动态内容的重要手段之一。

  • 控制缓冲区:通过getBufferSize()方法可以获取缓冲区的大小,通过flush()方法可以强制将缓冲区中的数据输出到客户端,例如:

<%

    int bufferSize = out.getBufferSize();

    out.println("缓冲区大小:" + bufferSize + " 字节");

    out.flush();

%>

合理地使用缓冲区可以提高页面的输出效率,减少与客户端的交互次数,但在一些需要及时反馈给用户的场景中,如实时显示数据加载进度等,也需要适时地使用flush()方法来确保数据能够及时显示给用户。

通过对这些常用内置对象的详细讲解和示例演示,相信大家对它们的功能和用法有了更深入的理解和掌握。在实际的 JSP 开发中,灵活运用这些内置对象能够更加高效地实现各种复杂的业务需求,提升应用程序的质量和用户体验。同时,需要注意在多用户并发访问的情况下,合理地管理和使用这些对象,避免出现数据不一致、资源竞争等问题,确保应用程序的稳定性和可靠性。

六、JSP 的综合案例实践

以下是一个简单的 JSP 综合案例,涵盖了 JSP 页面的创建、数据的获取与处理、页面的跳转与交互等多个方面,帮助大家巩固前面所学的知识,提高实际开发能力。

用户信息管理案例

功能需求描述

我们要实现一个简单的用户信息管理系统,具备以下功能:

  1. 用户列表展示:能够在页面上展示已有的用户信息列表,包括用户名、年龄、性别等。
  2. 用户信息添加:提供一个表单页面,用于添加新的用户信息,并将信息保存到服务器端(这里暂不涉及数据库,使用简单的集合模拟数据存储)。
  3. 用户信息修改:可以点击用户列表中的某个用户进入修改页面,修改该用户的相关信息后保存更新。
  4. 用户信息删除:在用户列表中能对某个用户执行删除操作,从存储的用户信息中移除相应记录。
具体实现步骤
  1. 创建实体类 User

首先创建一个 User 类来表示用户信息,代码如下:

package com.example.model;

public class User {

    private String username;

    private int age;

    private String gender;

    public User(String username, int age, String gender) {

        this.username = username;

        this.age = age;

        this.gender = gender;

    }

    public String getUsername() {

        return username;

    }

    public void setUsername(String username) {

        this.username = username;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

    public String getGender() {

        return gender;

    }

    public void setGender(String gender) {

        this.gender = gender;

    }

}

  1. 编写 Servlet 类来处理业务逻辑

创建一个名为 UserServlet 的 Servlet,用于处理各种用户相关的请求,比如获取用户列表、添加用户、更新用户、删除用户等操作,代码示例如下:

package com.example.servlet;

import com.example.model.User;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

@WebServlet("/user")

public class UserServlet extends HttpServlet {

    private List<User> userList = new ArrayList<>();

    @Override

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String action = request.getParameter("action");

        if ("list".equals(action)) {

            // 查询用户列表

            request.setAttribute("userList", userList);

            request.getRequestDispatcher("/userList.jsp").forward(request, response);

        } else if ("add".equals(action)) {

            // 跳转到添加用户页面

            request.getRequestDispatcher("/addUser.jsp").forward(request, response);

        } else if ("edit".equals(action)) {

            String username = request.getParameter("username");

            // 根据用户名查找要编辑的用户(这里简单示例,实际可按ID等更准确查找)

            User userToEdit = null;

            for (User user : userList) {

                if (user.getUsername().equals(username)) {

                    userToEdit = user;

                    break;

                }

            }

            if (userToEdit!= null) {

                request.setAttribute("user", userToEdit);

                request.getRequestDispatcher("/editUser.jsp").forward(request, response);

            }

        } else if ("delete".equals(action)) {

            String username = request.getParameter("username");

            // 根据用户名删除用户

            for (int i = 0; i < userList.size(); i++) {

                if (userList.get(i).getUsername().equals(username)) {

                    userList.remove(i);

                    break;

                }

            }

            response.sendRedirect(request.getContextPath() + "/user?action=list");

        }

    }

    @Override

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");

        String action = request.getParameter("action");

        if ("add".equals(action)) {

            String username = request.getParameter("username");

            int age = Integer.parseInt(request.getParameter("age"));

            String gender = request.getParameter("gender");

            User newUser = new User(username, age, gender);

            userList.add(newUser);

            response.sendRedirect(request.getContextPath() + "/user?action=list");

        } else if ("update".equals(action)) {

            String oldUsername = request.getParameter("oldUsername");

            String newUsername = request.getParameter("username");

            int age = Integer.parseInt(request.getParameter("age"));

            String gender = request.getParameter("gender");

            // 找到要更新的用户并修改信息

            for (User user : userList) {

                if (user.getUsername().equals(oldUsername)) {

                    user.setUsername(newUsername);

                    user.setAge(age);

                    user.setGender(gender);

                    break;

                }

            }

            response.sendRedirect(request.getContextPath() + "/user?action=list");

        }

    }

}

  1. 创建相关的 JSP 页面
    • 用户列表页面 userList.jsp:用于展示用户信息列表,并提供操作链接(编辑、删除),代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

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

<html>

<head>

    <title>用户信息列表</title>

</head>

<body>

    <h2>用户信息列表</h2>

    <table border="1">

        <tr>

            <th>用户名</th>

            <th>年龄</th>

            <th>性别</th>

            <th>操作</th>

        </tr>

        <c:forEach items="${userList}" var="user">

            <tr>

                <td>${user.username}</td>

                <td>${user.age}</td>

                <td>${user.gender}</td>

                <td>

                    <a href="user?action=edit&username=${user.username}">编辑</a>

                    <a href="user?action=delete&username=${user.username}">删除</a>

                </td>

            </tr>

        </c:forEach>

    </table>

    <a href="user?action=add">添加用户</a>

</body>

</html>

  • 添加用户页面 addUser.jsp:提供表单让用户输入信息来添加新用户,代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

    <title>添加用户</title>

</head>

<body>

    <h2>添加用户</h2>

    <form action="user?action=add" method="post">

        用户名:<input type="text" name="username" /><br />

        年龄:<input type="text" name="age" /><br />

        性别:<input type="text" name="gender" /><br />

        <input type="submit" value="添加" />

    </form>

</body>

</html>

  • 编辑用户页面 editUser.jsp:根据传入的用户信息展示在表单中,方便修改后提交更新,代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

    <title>编辑用户</title>

</head>

<body>

    <h2>编辑用户</h2>

    <form action="user?action=update" method="post">

        <input type="hidden" name="oldUsername" value="${user.username}" />

        用户名:<input type="text" name="username" value="${user.username}" /><br />

        年龄:<input type="text" name="age" value="${user.age}" /><br />

        性别:<input type="text" name="gender" value="${user.gender}" /><br />

        <input type="submit" value="保存修改" />

    </form>

</body>

</html>

页面跳转与交互说明
  1. 从用户列表页面到添加用户页面:在 userList.jsp 页面点击 “添加用户” 链接,会向 UserServlet 发送一个 action=add 的 GET 请求,UserServlet 接收到请求后,通过转发跳转到 addUser.jsp 页面,此时浏览器地址栏保持 user?action=add 不变(转发特性)。
  2. 添加用户信息提交:在 addUser.jsp 页面填写完用户信息后点击 “添加” 按钮,会向 UserServlet 发送一个 action=add 的 POST 请求,UserServlet 接收到请求后,将新用户信息添加到 userList 集合中,然后重定向到 user?action=list,浏览器地址栏变为新的 user?action=list 地址(重定向特性),此时会重新请求 UserServlet 来获取更新后的用户列表并展示在 userList.jsp 页面。
  3. 从用户列表页面到编辑用户页面:在 userList.jsp 页面点击某个用户的 “编辑” 链接,会向 UserServlet 发送一个包含要编辑用户用户名的 action=edit 的 GET 请求,UserServlet 接收到请求后,查找对应的用户信息,然后转发到 editUser.jsp 页面,浏览器地址栏保持原请求地址不变,在 editUser.jsp 页面可以看到要编辑用户的原有信息展示在表单中。
  4. 编辑用户信息提交:在 editUser.jsp 页面修改完用户信息后点击 “保存修改” 按钮,会向 UserServlet 发送一个 action=update 的 POST 请求,UserServlet 接收到请求后,根据传入的旧用户名找到对应的用户并更新其信息,之后重定向到 user?action=list,浏览器地址栏更新,重新请求 UserServlet 获取最新用户列表展示在 userList.jsp 页面。
  5. 从用户列表页面删除用户:在 userList.jsp 页面点击某个用户的 “删除” 链接,会向 UserServlet 发送一个包含要删除用户用户名的 action=delete 的 GET 请求,UserServlet 接收到请求后,从 userList 集合中移除该用户信息,然后重定向到 user?action=list,浏览器地址栏更新,重新请求 UserServlet 获取更新后的用户列表展示在 userList.jsp 页面。

通过这个综合案例,大家可以体会到如何在 JSP 页面中运用前面所学的语法知识、内置对象以及各种动作标签来实现一个完整的 Web 应用功能,包括页面的创建、数据的处理以及页面之间的跳转与交互等操作,希望能帮助大家更好地掌握 JSP 技术,在实际开发中灵活运用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幽兰的天空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值