初识JSP

JSP概念

JSP全名为Java Server Pages(Java服务器页面),其根本是一个简化的Servlet设计,它是由Sun公司倡导、多家公司参与一起建立的一种动态网页技术标准。
JSP技术有些类似ASP技术,它是在传统的网页HTML(标准通用标记语言的子集)文件(.htm,.html)中插入Java程序段(Scriptlet)和JSP标记(tag)。形成的JSP文件,后缀名为“.jsp”。用JSP开发的Web应用是跨平台的,既能在Linux下运行,又能在其他操作系统上运行。
JSP将网页逻辑与网页设计的显示分离,支持可重用的基于组件的设计,使基于Web的应用程序的开发变得迅速和容易。JSP是一种动态页面技术,它的主要目的是将表示逻辑从Servlet中分离出来

JSP页面组成

1.组成

img

2.示例

img

然后,关于环境配置啥的就省略掉了(此处省略1k字)

JSP注释

代码缺少不了注释声明,注释是为了能让他人看懂代码,方便项目的更新和维护。

在 JSP 页面中可以使用多种注释,如 HTML 中的注释、Java 中的注释和在严格意义上说属于 JSP 页面自己的注释——带有 JSP 表达式和隐藏的注释。在 JSP 规范中,它们都属于 JSP 中的注释,并且它们的语法规则和运行的效果有所不同。接下来我们将介绍 JSP 中的各种注释。

HTML中的注释

JSP 文件是由 HTML 标记和嵌入的 Java 程序段组成的,所以在 HTML 中的注释同样可以在 JSP 文件中使用。注释格式如下:

<!--注释内容-->

值得注意的是这里的注释文本虽然不会直接显示到网页上,但可以通过查看网页源代码来看到。

带有JSP表达式的注释

在 HTML 注释中可以嵌入 JSP 表达式,注释格式如下:

<!--comment<%=expression %>-->

包含该注释语句的 JSP 页面被请求后,服务器能够识别注释中的 JSP 表达式,从而来执行该表达式,而对注释中的其他内容不做任何操作。

当服务器将执行结果返回给客户端后,客户端浏览器会识别该注释语句,所以被注释的内容不会显示在浏览器中。

如何隐藏注释

前面已经介绍了如何使用 HTML 中的注释,这种注释虽然在客户端浏览页面时不会看见,但它却存在于源代码中,可通过在客户端查看源代码看到被注释的内容。所以这种注释并不安全。下面介绍一种隐藏注释,注释格式如下:

<%--注释内容--%>

用该方法注释的内容,不仅在客户端浏览时看不到,而且即使在客户端查看 HTML 源代码,也不会看到,所以安全性较高。

脚本程序中的注释

脚本程序指的是被"<% %>"包裹的Java代码,因为本质上还是Java程序,所以在脚本程序中的注释与在 Java 中的注释是相同的,非常容易上手。

1.单行注释

//注释内容

2.多行注释

/*
注释内容1
注释内容1
*/

3.文档注释

文档注释会被JavaDoc在生成文档时读取,格式如下

/**
文档内容1
文档内容2
*/

JSP声明:变量、方法和类的声明

在JSP页面中可以声明变量、方法和类,其声明格式如下:

<%!声明变量、方法和类的代码%>

声明变量

在“<%!”和“%>”标记之间声明变量,即在“<%!”和“%>”之间放置 Java 的变量声明语句。变量的类型可以是 Java 语言允许的任何数据类型。我们将这些变量称为 JSP 页面的成员变量。

示例代码:

<%!
    int x,y=100,z;
    String tom=null,cat="JSP";
    Date date;
%>

声明方法

在“<%!”和“%>”标记之间声明的方法,在整个 JSP 页面有效,但是,方法内定义的变量只在方法内有效。

示例代码:

<%@ page contentType="text/html; charset=utf-8" %>
<%!
    int num = 0;                    //声明一个计数变量
    synchronized void add()
    {
        //该方法实现访问次数的累加操作
        num++;
    }
%>
<%--    该页面每打开一次,下面这段代码就会运行一遍--%>
<% add(); %>
<html>
    <body><center>您是第<%=num%>位访问该页面的游客!</center></body>
</html>

运行效果:

页面每刷新一次,这个代码就会执行一次

img

声明类

可以在“<%!”和“%>”之间声明一个类。该类在 JSP 页面内生效,即在 JSP 页面的 Java 程序段部分可以使用该类创建对象。下例中,定义了一个 Circle 类,该类的对象负责求圆的面积。当客户向服务器提交圆的半径后,该对象计算圆的面积。

<%--
  Created by IntelliJ IDEA.
  User: hash070
  Date: 2022/3/7
  Time: 7:41 PM
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>面积求和测试</title>
</head>
<body>
<p>
    <font size="4">请输入圆的半径:<br></font>
</p>
<form action="" method="get" name="form" id="form">
    <input type="text" name="radius" value="1">
    <input type="submit" value="提交" name="submit">
</form>
<%!
    public class Circle {
        double r;

        Circle(double r) {
            this.r = r;
        }

        double getAcreage() {
            return Math.PI * r * r;
        }
    }
%>
<%
    String str = request.getParameter("radius");
    double r;
    if (str != null) {
        r = Double.parseDouble(str);
    } else {
        r = 1;
    }
    Circle circle = new Circle(r);
%>
<p>
    圆的面积是:<%=circle.getAcreage()%>
</p>

</body>
</html>

运行效果:

img

JSP嵌入Java代码

Scriptlet的作用
Scriptlet可以实现**在JSP页面中嵌入一段有效的Java程序段,此程序段可以是变量的声明、方法的调用。**例如,根据从客户端传递过来的用户名和密码信息判断该用户的合法性,从数据库获取用户信息,再传递到客户端进行展示输出等这些业务逻辑功能,均可以通过Java程序段(也称脚本代码段)实现。
Scriptlet的语法格式

<%Java代码 %>

具体说明如下。
“<%”和“%>”是一个完整的符号,符号中间不可有空格。
<% %>中除了不能定义类和方法不能用import引入类外,可以包含任何有效的Java代码、可以定义变量、调用方法和进行各种表达式运算。
在Scriptlet中定义的变量在当前的整个页面内都有效,但不会被其他的线程共享。
实例:JSP Scriptlet应用
示例代码

以直角三角形的形式显示数字

    <h1>以直角三角形的形式显示数字</h1>
    <%
        for(int i=1;i<10;i++) {for(int j=1;j<=i;j++) {
      %>
       <%=j%>
    <%}%>
       <%="</br>" %>
    <%}%>

输出结果

img

JSP表达式

表达式的作用
表达式的作用是**计算Java表达式的值,得到的结果转换成字符串,并在JSP页面中表达式所在位置进行显示。**Java表达式是指由操作数和运算符组成的,且符合Java语法规则的公式。其中,操作数可以是变量、常量、方法等,运算符包括算术运算符、逻辑运算符、比较运算符、移位运算符等。此部分知识点的详细介绍可以参见 Java编程语言相关教程资料。
表达式的计算在运行时进行(即JSP页面被请求时),因此在表达式中可以访问与请求有关的全部信息,其中,请求相关的信息都封装在request隐式对象中。
表达式的语法格式

<%=Java表达式 %>

具体说明如下。
“<%=”和“%>”是一个完整的符号,符号中间不可有空格。
不可以插入语句。
表达式必须能求值。
示例代码

    <h1>JSP表达式的案例演示</h1>
    <%=3+3 %><br>
    <%=3>4 %><br>
    <%=Math.PI %><br>
    <%=Math.abs(-0.23) %>

输出结果

img

JSP指令

JSP 指令是为 JSP 引擎(比如 Tomcat)而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理 JSP 页面中的其余部分。

JSP 引擎会根据 JSP 的指令信息来编译 JSP,生成 Java 文件。在生成的 Java 文件中,指令就不存在了。

一般都会把 JSP 指令放到 JSP 文件的最上方,但这不是必须的。

指令通常以<%@标记开始,以%>标记结束,它的具体语法如下:

<%@  指令名称  属性1="属性值1"  属性2="属性值2" ... 属性n="属性值n" %>

JSP 中有三大指令,它们分别是 page、include 和 taglib,它们的说明如下

指 明 说 明
page page 指令用于定义 JSP 页面的各种属性。page 是最复杂的一个指令,它的属性很多,常用的属性有 import、language、pageEncoding 等。
include 静态包含指令,用于引入其它 JSP 文件。使用 include 指令引入的其它 JSP 文件,JSP 引擎将把这两个 JSP 文件翻译成一个 servlet,所以将 include 称为静态包含。
taglib 用于在 JSP 页面中导入标签库(JSP 标准标签库、第三方标签库、自定义标签库)。

page指令

JSP page 指令是页面指令,可以定义在整个 JSP 页面范围有效的属性和相关的功能。利用 page 指令,可以指定脚本语言,导入需要的类,指明输出内容的类型,指定处理异常的错误页面,以及指定页面输出缓存的大小,还可以一次设置多个属性。

page的常用指令如下

<%@ page
[language="java"]
[contentType="mimeType[ ;charset=CHARSET ]"]
[import="{package.class|package.*},..."]
[info="text"]
[extends="package.class"]
[session="true|false"]
[errorPage="relativeURL"]
[isThreadSafe="true|false"]
[buffer="none|8kb|size kb"]
[autoFlush="true|false"]
[isThreadSafe="true|false"]
[isELIgnored="true|false"]
[page Encoding="CHARSET"]
%>

值得注意的是

  1. 语法格式说明中的“[”和“]”符号括起来的内容表示可选项。
  2. 可以在一个页面上使用多个 page 指令,但其中的属性只能使用一次(import 属性除外)。

include指令

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

使用 include 指令有以下优点:

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

include命令的语法如下

<%@ include file="URL" %>  

示例代码:

<p>
    这是一个引入测试,下面是被引入的页面
</p>
<%@include file="intest2.jsp"%>

intest2.jspBody部分的代码:

<p>这是一段被引入的页面</p>

运行结果:

img

taglib命令

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

taglib命令的语法规则如下

<%@ taglib uri="taglibUrl" prefix="tagPre" %>

JSP动作

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

这么一看,好像和JSP指令有点相似之处。确实,就代码的运行效果而言,它们是相同的,但它们之间是有区别的。

JSP 动作与 JSP 指令的区别如下:

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

JSP动作语法如下:

<jsp:action_name attribute = "value" />
OR
<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 元素的内容

include动作

jsp:include 动作用来在页面中引入文件,文件可以是 HTML、JSP 页面和文本文件等。通过 include 动作,我们可以多次使用同一个页面,增加了代码可重用性。例如,在页面中使用 include 动作引入头部和底部页面。

jsp:include动作的语法如下:

<jsp:include page="relativeURL | <%=expression%>" flush="true" />  

page 指定引入页面的路径,flush 表示在引入文件前是否刷新缓冲区,默认为 false。

示例代码:

<p>
    这是一个引入测试,下面是被引入的页面
</p>
<jsp:include page="intest2.jsp"/>

intest2.jspBody部分的代码:

<p>这是一段被引入的页面</p>

运行结果:

img

forward动作

jsp:forward 动作用来将请求转发到另一个页面中,请求的参数数据会被一起转发到目标页面。

jsp:forward 的语法规则如下

<jsp:forward page="url"/>

代码示例:

从forwardTest1.jsp中跳转到forwardTest2.jsp

forwardTest1.jsp代码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Forward动作测试1</title>
</head>
<body>
<jsp:forward page="forwardTest2.jsp.jsp"/>
</body>
</html>

forwardTest2.jsp代码

<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Forward测试2</title>
</head>
<body>
<p>
    欢迎进入登陆界面
</p>
<br /> 您登录的时间是<%=new Date()%>
</body>
</html>

运行结果:

img

我们可以观察到,网页确实是跳转过去了,但是链接还是显示的是第一个jsp文件的链接,所以jsp:forward 与 Servlet 中的转发相似,客户端不会显示转发后的页面地址,有较好的隐蔽性。

param动作

jsp:param 动作用来传递参数信息,经常和其它动作一起使用,例如 jsp:includejsp:forward

jsp:param 的语法如下:

<jsp: param name="param_name" value="param_value" />

代码示例:

在 login.jsp 中传递参数,并转发到 index.jsp 页面。

login.jsp 代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆测试</title>
</head>
<body>
<jsp:forward page="index.jsp">
    <jsp:param name="username" value="hash070"/>
    <jsp:param name="password" value="helloworld"/>
</jsp:forward>
</body>
</html>

index.jsp 代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>跳转界面</title>
</head>
<body>
<%=request.getParameter("username")%>,欢迎登陆!<br>
您请求的密码是<%=request.getParameter("password")%>
</body>
</html>

运行效果:

img

useBean动作

jsp:useBean 用于获取 Bean 对象。jsp:useBean 首先会在指定范围内查找 Bean 对象,如果 Bean 对象不存在,则创建 Bean 对象。

jsp:useBean 的语法规则:

<jsp:useBean id = "name" class = "package.class" scope= "page | request | session | application" />

其中:

1>id

表示 Bean 实例化对象的变量名,可以在指定范围内使用该变量名。

2>class

表示需要实例化 Bean 的类路径,指定的类必须包含 public 且无参数的构造方法。

3>scope

指定 Bean 的作用域,取值为:

  • page:只能在当前页面使用该 Bean 对象;
  • request:只能在一次请求范围内使用该 Bean 对象;
  • session:只能在一次会话范围内使用该 Bean 对象;
  • application:可以在整个应用范围内使用该 Bean 对象。

代码示例:

登录页面代码:

<%--
  Created by IntelliJ IDEA.
  User: hash070
  Date: 2022/3/8
  Time: 3:42 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8"%>
<html>
<head>
    <title>useBean测试1</title>
</head>
<body>
<h1>请登录</h1>
<hr/>
<form action="doLogin.jsp" method="post">
    <label for="username">用户名:</label>
    <input type="text" name="username" id="username" value=""/>
    <br/>

    <label for="password">密码:</label>
    <input type="password" name="password" id="password" value=""/>
    <br/>

    <input type="submit" value="登录"/>
</form>
</body>
</html>

接收页面代码(doLogin.jsp):

<%--
  Created by IntelliJ IDEA.
  User: hash070
  Date: 2022/3/8
  Time: 3:42 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
    <title>useBean测试1</title>
</head>
<body>
<jsp:useBean id="user" class="top.hash070.MyBean1" scope="page"/>
<h2>用户登录信息</h2>
<hr>
<jsp:setProperty property="*" name="user"/>
用户名:
<jsp:getProperty property="username" name="user"/>
<br>
密码:
<jsp:getProperty property="password" name="user"/>
</body>
</html>

JavaBean代码(放在src文件夹下):

package top.hash070;

public class MyBean1 {
    private String username;
    private String password;

    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;
    }
}

运行效果:

img

img

setProperty和getProperty动作

jsp:getProperty用于获取 Bean 的属性值,jsp:setProperty 动作用于设置 Bean 的属性值。

jsp:setProperty

jsp:setProperty 的语法如下:

<jsp:setProperty name = "beanName" property = "attributeName" value = "attributeValue"/>

其中,name 指定需要修改属性的 Bean 的名称;property 指定 Bean 的属性,即 Bean 类中的属性;value 是要设定的属性值。

jsp:setProperty 通常和 jsp:useBean 一起使用,分为两种情况。

\1. 在 jsp:useBean 标签外使用 jsp:setProperty ,例如:

<jsp:useBean id = "User" ... />
...
<jsp:setProperty name = "User" property = "attributeName" value = "attributeValue"/>

以上情况,无论 jsp:useBean 是否实例化了 User 对象,jsp:setProperty 都会执行。

\2. 在 jsp:useBean 标签里使用 jsp:setProperty ,例如:

<jsp:useBean id = "User" ...>
    ...    
<jsp:setProperty name = "User" property = "attributeName" value = "attributeValue"/>
</jsp:useBean>

以上情况,只有 jsp:useBean 实例化了 User 对象,jsp:setProperty 才会执行。

jsp:getProperty

jsp:getProperty 的语法如下:

<jsp:getProperty name = "beanName" property = "attributeName">

其中,name 指定需要获取属性的 Bean 的名称;property 指定 Bean 的属性,即 Bean 类中的属性。

JSP内置对象

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

九大内置对象

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

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

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

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

四大域对象

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

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

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

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

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

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 请求方法/客户提交信息方式

示例:

获取HTTP头信息

<%@ page import="java.util.Enumeration" %><%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2022/3/11
  Time: 下午 5:03
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</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>

运行结果:

img

注:关于头信息的说明:

参数名称 说明
host 表示服务器的主机名和端口号
connection 判断客户端是否可以持续性的连接 HTTP
cache-control 网页缓存控制,默认值为 no-cache,表明每次访问都从服务器中获取页面
upgrade-insecure-requests Chrome(谷歌浏览器)会在 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 或其他信息

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) 设定页面响应的编码类型

代码示例:

利用request对象实现登录验证和跳转

登录表单代码:

<%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2022/3/11
  Time: 下午 5:58
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录测试</title>
</head>
<body>
<h2>用户登录</h2>
<form action="loginFunc.jsp" method="post">
    用户名: <input type="text" name="username" /> <br> <br>
    密码: <input type="text" name="password" /> <br> <br>
    <input type="submit" value="登录" />
</form>
</body>
</html>

判断代码(loginFunc.jsp):

<%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2022/3/11
  Time: 下午 5:59
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录检查界面</title>
</head>
<body>

<%
    String username=request.getParameter("username");
    String password=request.getParameter("password");
    //下面是登录判断代码
    if (username.equals("un1")&&password.equals("pw1"))
        response.sendRedirect("success.jsp");
    else
        response.sendRedirect("failed.jsp");
%>
</body>
</html>

登录成功页面(failed.jsp):

<%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2022/3/11
  Time: 下午 6:02
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录成功</title>
</head>
<body>
<h2>
    登录成功
</h2>
</body>
</html>

登录失败页面(success.jsp):

<%--
  Created by IntelliJ IDEA.
  User: Admin
  Date: 2022/3/11
  Time: 下午 6:03
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录失败</title>
</head>
<body>
<h2>
    登录失败,用户名或密码错误
</h2>
</body>
</html>

运行效果:

img

img

img

img

out对象

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

out 对象的常用方法如下:

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

代码示例:

<%--
  User: hash070
  Date: 2022/3/12
  Time: 4:46 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Out对象测试</title>
</head>
<body>
<%
  out.print("测试文本1");
  out.print("<br>");
  out.println("测试文本2");
  out.newLine();
  out.print("测试文本3");
%>
</body>
</html>

运行结果:

img

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 对象的时间

示例代码:

登陆表单代码(sessionLogin.jsp)

<%--
  User: hash070
  Date: 2022/3/12
  Time: 4:58 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Session测试</title>
</head>
<body>
<form action="doLogin.jsp" method="post">
    <label for="username">用户名</label>
    <input type="text" id="username" name="name">
    <input type="submit" value="登陆">
</form>
</body>
</html>

登陆信息处理代码(doLogin.jsp)

<%--
  User: hash070
  Date: 2022/3/12
  Time: 4:59 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆测试</title>
</head>
<body>
<%
    session.setAttribute("username",request.getParameter("name"));
%>
<jsp:forward page="success.jsp"/>
</body>
</html>

success.jsp 代码

<%--
  User: hash070
  Date: 2022/3/12
  Time: 5:01 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆成功</title>
</head>
<body>
<%
    out.print("欢迎");
    out.print((String) session.getAttribute("username"));
    out.print("登陆");
%>
</body>
</html>

运行结果:

img

img

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对象来做一个网站计数器

<%--
  User: hash070
  Date: 2022/3/12
  Time: 5:21 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>网站计数器</title>
</head>
<body>
<%
    Integer count = (Integer) application.getAttribute("count");
    if (count!=null)
        count++;
    else
        count=1;
    application.setAttribute("count",count);
    out.print("欢迎来到本鼠鼠的个人小站,您是第"+count+"位访客");
%>
</body>
</html>

运行结果:

img

config对象

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

config 对象的常用方法如下:

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

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() 复制对象

示例代码:

<%--
  User: hash070
  Date: 2022/3/14
  Time: 4:50 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>page对象Demo</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>

运行结果:

img

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 对象

示例代码:

<%--
  User: hash070
  Date: 2022/3/14
  Time: 4:42 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>pageContext对象示例</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>

运行结果:

img

JSP Cookie的使用

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

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

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

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

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

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

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

注意:由于 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

cookie使用

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

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

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

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

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

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

response.addcookie(cookie);

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

cookie.setMaxAge(60*60*24); 

4)读取cookie

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

示例代码

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

<%--
  User: hash070
  Date: 2022/3/14
  Time: 5:21 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>CookieDemo1</title>
</head>
<body>
<form action="cookieDemo1.jsp" method="post">
    站点名: <input type="text" name="name"> <br />
    网址: <input type="text" name="url" />
    <input type="submit" value="提交" />
</form>
</body>
</html>

cookieDemo1.jsp代码如下

<%@ page import="java.net.URLEncoder" %>
<%--
  User: hash070
  Date: 2022/3/14
  Time: 5:22 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    // 解决中文乱码
    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>CookieDemo1</title>
</head>
<body>
<b>网站名:</b>
<%=request.getParameter("name")%><br>
<b>网址:</b>
<%=request.getParameter("url")%>
</body>
</html>

运行结果:

img

img

读取cookie

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

<%@ page import="java.net.URLDecoder" %><%--
  User: hash070
  Date: 2022/3/14
  Time: 5:32 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>获取cookie</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>

运行效果:

img

删除cookie

删除 cookie 步骤如下:

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

示例代码:

删除名为name的cookie

<%@ page import="java.net.URLDecoder" %>
<%--
  User: hash070
  Date: 2022/3/14
  Time: 5:22 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Cookie删除Demo</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>

运行结果:

img

session和cookie的区别

session 和 cookie 的区别如下:

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

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

EL表达式

之前的 JSP 页面中,我们经常使用 JSP 表达式来输出变量或者页面之间传递的参数,大大降低了页面的可读性。

为了简化 JSP 页面,JSP 2.0 新增了 EL(Expression Language)表达式语言。EL 提供了更为简洁、方便的形式来访问变量和参数,不仅可以简化 JSP 页面代码,还会使开发者的逻辑变得更加清晰 。

EL表达式的语法

EL 表达式语法如下:

EL表达式EL表达式语法以"{EL表达式}EL 表达式语法以"{“开头,以”}"结束,中间为合法的表达式。

示例

${param.name} 表示获取参数 name 的值,它等同于 <%=request.getParameter('name') %>。从形式和语法上可以看出,EL 表达式简化了 JSP 原有的表达式。在实际开发中,EL 表达式也是经常使用的方式。

EL 表达式定义了许多运算符,如算术运算符、比较运算符、逻辑运算符等,使用这些运算符,可以使 JSP 页面更加简洁。

EL算术运算符

算术运算符用来进行加、减、乘、除和求余,EL 表达式算术运算符如下:

EL算术运算符 说明 范例 结果
+ $ 7
- $ 3
* $ 10
/ 或 div $ 2
% 或 mod 求余 $ 1

注意:EL 的+运算符与 Java 的+运算符不一样,它无法实现两个字符串的连接运算。如果该运算符连接的两个值不能转换为数值型的字符串,则会拋出异常;反之,EL 会自动将这两个字符转换为数值型数据,再进行运算。

EL 表达式中还可以使用 ( ) 改变优先级,例如:${2+3*2} 等于 8,${(2+3)*2} 等于 10。

EL比较运算符

比较运算符用来实现两个表达式的比较,进行比较的表达式可以是数值型或字符串。EL 表达式比较运算符如下:

EL比较运算符 说明 范例 结果
== 或 eq 等于 ${66} 或 ${6 eq 6} ${“A”“a”} 或 $ true false
!= 或 ne 不等于 ${6!=6} 或 ${6 ne 6} ${“A"!=“a”} 或 $ false true
< 或 lt 小于 ${3<8} 或 ${3 lt 8} ${“A”<“a”} 或 $ true true
> 或 gt 大于 ${3>8} 或 ${3 gt 8} ${“A”>“a”} 或 $ false false
<= 或 le 小于等于 ${3<=8} 或 ${3 le 8} ${“A”<=“a”} 或 $ true true
>= 或 ge 大于等于 ${3>=8} 或 ${3 ge 8} ${“A”>=“a”} 或 $ false false

EL逻辑运算符

逻辑运算符两边的表达式必须是布尔型(Boolean)变量,其返回结果也是布尔型(Boolean)。EL 表达式逻辑运算符如下:

EL逻辑运算符 说明 范例 结果
&& 或 and ${2>1&&3<4 } 或 $ true
|| 或 or ${2<1||3>4} 或 $ false
! 或 not ${!(2>4)} 或 $ true

EL其它运算符

1). 和 [ ]

.[ ]是 EL 中最常用的运算符,用来访问 JavaBean 中的属性和隐式对象的数据。一般情况下,.用来访问 JavaBean 属性或 Map 类型的值,[ ]用来访问数组或者列表的元素。

2)empty

empty 用来判断 EL 表达式中的对象或者变量是否为空。若为空或者 null,返回 true,否则返回 false。

3)条件运算符

EL 表达式中,条件运算符的语法和 Java 的完全一致,如下:

${条件表达式?表达式1:表达式2}

示例:

运算符使用示例:

<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.HashMap" %><%--
  User: hash070
  Date: 2022/3/19
  Time: 18:27
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>EL表达式测试</title>
</head>
<body>
<h4>.运算符</h4>
<%!
    public static class Site {
        String name,url;
        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;
        }
    }
%><%
    Site site = new Site();
    site.setName("麦子尖的学习小站");
    site.setUrl("hash070.top");
    session.setAttribute("website", site);
%>
欢迎来到${website.name},我的网址是:${website.url}
<h4>[]运算符</h4>
<%
    List tutorials = new ArrayList();
    tutorials.add("Java");
    tutorials.add("c++");
    session.setAttribute("tutorials", tutorials);
    HashMap siteMap = new HashMap();
    siteMap.put("one", "咖啡");
    siteMap.put("two", "C艹");
    session.setAttribute("site", siteMap);
%>
tutorials 中的内容:${tutorials[0]},${tutorials[1]}
<br> siteMap 中的内容:${site.one},${site.two}
<h4>empty和条件运算符</h4>
<!-- 当 cart 变量为空时,输出购物车为空,否则输出cart -->
<%
    String cart = null;
%>
${empty cart?"购物车为空":cart}

</body>
</html>

运行效果:

1670037867099.webp

EL内置对象

为了显示方便,EL 表达式语言提供了许多内置对象,可以通过不同的内置对象来输出不同的内容。EL 表达式内置对象如下:

内置对象 说明
pageScope 获取 page 范围的变量
requestScope 获取 request 范围的变量
sessionScope 获取 session 范围的变量
applicationScope 获取 application 范围的变量
param 相当于 request.getParameter(String name),获取单个参数的值
paramValues 相当于 request.getParameterValues(String name),获取参数集合中的变量值
header 相当于 request.getHeader(String name),获取 HTTP 请求头信息
headerValues 相当于 request.getHeaders(String name),获取 HTTP 请求头数组信息
initParam 相当于 application.getInitParameter(String name),获取 web.xml 文件中的参数值
cookie 相当于 request.getCookies(),获取 cookie 中的值
pageContext 表示当前 JSP 页面的 pageContext 对象

从以上方法可以看出,EL 表达式可以输出 4 种属性范围的内容。如果在不同的属性范围中设置了同一个属性名称,则按照 page、request、session、application 的顺序依次查找。我们也可以指定要取出哪一个范围的变量,例如:${pagesScope.name},表示取出 page 范围的 name 变量。

例1:

在EL表达式中获取四种不同范围的属性,代码如下:

<%--
  User: hash070
  Date: 2022/3/20
  Time: 11:09
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>EL内置对象实验</title>
</head>
<body>
<%
    pageContext.setAttribute("info", "page属性范围");
    request.setAttribute("info", "request属性范围");
    session.setAttribute("info", "session属性范围");
    application.setAttribute("info", "application属性范围");
%>
<h2>获取对象中的内容</h2>
<hr/>
不指定范围(默认为page属性的内容):${info}
<br> page 属性内容:${pageScope.info}
<br> request 属性内容:${requestScope.info}
<br>session 属性内容:${sessionScope.info}
<br>application 属性内容:${applicationScope.info}
</body>
</html>

运行结果:

img

例2

演示param、paramValues的使用方法,第一个页面向第二个页面发送参数,使用param和paramValues对象来获取传递过来的参数,第一个页面的代码如下

<%--
  User: hash070
  Date: 2022/3/20
  Time: 11:17
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>param、paramValues使用示例</title>
</head>
<body>
<%
    request.setCharacterEncoding("UTF-8");
%>
<form action="elObjectTest2index.jsp" method="post">
<%--"${pageContext.request.contextPath}/index.jsp"等价于"<%=request.getContextPath()%>/index.jsp"
即当前项目的名称--%>
    网站名称: <input type="text" name="name" value="学习小站" /> <br>
    <input type="text" name="name" value="用户名" /> <br>
    <input type="text" name="name" value="密码" /> <br>

    网址: <input type="text" name="url" value="hash070.top" /> <br>
    <input type="submit" value="提交" />
</form>
</body>
</html>

第二个页面的代码如下(elObjectTest2index.jsp):

<%--
  User: hash070
  Date: 2022/3/20
  Time: 11:20
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>参数接受页面</title>
</head>
<body>
<%
    request.setCharacterEncoding("UTF-8");
%>
用户名:${paramValues.name[0]}
<hr>
密码:${paramValues.name[1]}
<hr>
请求参数值:${param.url}
</body>
</html>

param和paramValues的区别如下:

param对象用于获取请求参数的某个值,它是Map类型,与request.getParamter()方法相同,在使用EL获取参数时,如果参数不存在,返回的是空字符串,而不是null,param语法格式如下:$

如果一个请求参数有多个值,可以使用paramValues对象来获取请求参数的所有值,该对象用于返回请求参数所有值组成的数组,如果要获取某个请求参数的第一个值,则用$

运行结果:

img

img

例3

下面演示Cookie的使用方法,login.jsp代码如下:

<%--
  User: hash070
  Date: 2022/3/20
  Time: 11:44
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Cookie使用示例</title>
</head>
<body>
<%
    response.addCookie(new Cookie("cookieName1", "hash070"));
%>
<a href="elObjectsCookieIndex.jsp">跳转到Cookie读取页面</a>
</body>
</html>

index.jsp代码如下:

<%--
  User: hash070
  Date: 2022/3/20
  Time: 11:45
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Cookie对象使用示例</title>
</head>
<body>
获取到的Cookie值:${cookie.cookieName1.value}
</body>
</html>

运行结果:

img

img

JSP自定义标签

JSP文件上传

JSP使用JDBC访问数据库

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

和Java中的JDBC使用方式几乎是一样的,仅有少许不同。

初级教程

直接使用JDBC的Java代码来访问数据库

引入JDBC驱动

这里我使用的是MySQL+Maven框架,所以直接在pom.xml中添加依赖并同步了。

        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>

值得注意的是,引入依赖后还是要把jar包拖到WEB-INF目录下的lib文件夹里面,否则还是会提示找不到合适的驱动文件。

编写JDBCUtils工具类

使用JDBC工具类来操作数据库中的信息

使用示例:

这里我有一个table1,里面有两行数据,我想把这两行数据查询并输出到网页上的表格里

img

jsp代码

<%--
  User: hash070
  Date: 2022/3/20
  Time: 11:54
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<%@ page import="com.hash070.JDBCUtils" %>
<html>
<head>
    <title>JDBC测试1</title>
</head>
<body>
<table border="1" width="100%">
    <tr>
        <th>id</th>
        <th>name</th>
        <th>password</th>
    </tr>
    <%
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        String sql = null;
        try {
            conn = JDBCUtils.getConnection();
            sql = "SELECT * FROM `jsptest`.`table1`";
            pst = conn.prepareStatement(sql);
            rs = pst.executeQuery();
            System.out.println("执行完毕");
            while (rs.next()) {
                out.print("<tr><td>");
                out.print(rs.getInt("id"));
                out.print("</td><td>");
                out.print(rs.getString("name"));
                out.print("</td><td>");
                out.print(rs.getString("password"));
                out.print("</td></tr>");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            JDBCUtils.release(conn, pst, rs);
        }
    %>
</table>
</body>
</html>

运行效果:

img

JSP的四种开发模式

JSP 程序开发模式包括 JSP 编程JSP+JavaBean 编程JSP+JavaBean+Servlet 编程MVC 模式

单JSP编程

在 JSP 编程模式下,通过应用 JSP 中的脚本标识,可以直接在 JSP 页面中实现各种功能。虽然这种模式很容易实现,但是,其缺点也非常明显,那就是前后端代码耦合度太高,后期难以维护。

JSP+JavaBean编程

JSP+JavaBean 编程模式是 JSP 程序开发经典设计模式之一,适合小型或中型网站的开发。利用 JavaBean 技术,可以很容易地完成一些业务逻辑上的操作,例如数据库的连接、用户登录与注销等。

JavaBean 是一个遵循了一定规则的 Java 类,在程序的开发中,将要进行的业务逻辑封装到这个类中,在 JSP 页面中,通过动作标签来调用这个类,从而执行这个业务逻辑。此时的 JSP 除了负责部分流程的控制外,主要用来进行页面的显示,而 JavaBean 则负责业务逻辑的处理。

img

上图表示了该模式对客户端的请求进行处理的过程

  1. 用户通过客户端浏览器请求服务器。
  2. 服务器接收用户请求后调用 JSP 页面。
  3. 在 JSP 页面中调用 JavaBean。
  4. 在 JavaBean 中连接及操作数据库,或实现其他业务逻辑。
  5. JavaBean 将执行的结果返回 JSP+ 页面。
  6. 服务器读取 JSP 页面中的内容(将页面中的静态内容与动态内容相结合)。
  7. 服务器将最终的结果返回给客户端浏览器进行显示。

JSP+JavaBean+Servlet编程

JSP+JavaBean 设计模式虽然已经对网站的业务逻辑和显示页面进行了分离,但这种模式下的 JSP 不但要控制程序中的大部分流程,而且还要负责页面的显示,所以仍然不是一种理想的设计模式。

在 JSP+JavaBean 设计模式的基础上加入 Servlet 来实现程序中的控制层,是一个很好的选择。在这种模式中,由 Servlet 来执行业务逻辑并负责程序的流程控制,JavaBean 组件实现业务逻辑,充当模型的角色,JSP 用于页面的显示。可以看出,这种模式使得程序中的层次关系更明显,各组件的分工也非常明确。下图表示该模式对客户端的请求进行处理的过程。

img

如上图所示,在该的模式中,处理步骤如下

  1. 用户通过客户端浏览器请求服务器。
  2. 服务器接收用户请求后调用 Servlet。
  3. Servlet 根据用户请求调用 JavaBean 处理业务。
  4. 在 JavaBean 中连接及操作数据库,或实现其他业务逻辑。
  5. JavaBean 将结果返回 Servlet,在 Servlet 中将结果保存到请求对象中。
  6. 由 Servlet 转发请求到 JSP 页面。
  7. 服务器读取 JSP 页面中的内容(将页面中的静态内容与动态内容结合)。
  8. 服务器将最终的结果返回给客户端浏览器进行显示。

但 JSP+JavaBean+Servlet 模式同样也存在缺点。该模式遵循了 MVC 设计模式,MVC 只是一个抽象的设计概念,它将待开发的应用程序分解为三个独立的部分:模型(Model)、视图(View)和控制器(Controller)。

虽然用来实现 MVC 设计模式的技术可能都是相同的,但各公司都有自己的 MVC 架构。也就是说,这些公司用来实现自己的 MVC 架构所应用的技术可能都是 JSP、Servlet 与 JavaBean,但它们的流程及设计却是不同的,所以工程师需要花更多的时间去了解。

从项目开发的观点上来说,因为需要设计 MVC 各对象之间的数据交换格式与方法,所以在系统的设计上需要花费更多的时间。

使用 JSP+JavaBean+Servlet 模式进行项目开发时,可以选择一个实现了 MVC 模式的现成的框架,在此框架的基础上进行开发,能够大大节省开发时间,会取得事半功倍的效果。目前,已有很多可以使用的现成的 MVC 框架,例如 Struts 框架。

MVC模式

MVC(Model-View-Controller,模型-视图-控制器)是一种程序设计概念,它同时适用于简单的和复杂的程序。使用该模式,可将待开发的应用程序分解为三个独立的部分:模型、视图和控制器。

提出这种设计模式主要是因为应用程序中用来完成任务的代码(模型,也称为“业务逻辑”)通常是程序中相对稳定的部分,并且会被重复使用,而程序与用户进行交互的页面(视图),却是经常改变的。

如果因需要更新页面而不得不对业务逻辑代码进行改动,或者要在不同的模块中应用相同的功能时重复地编写业务逻辑代码,不仅会降低整体程序开发的进程,而且会使程序变得难以维护。因此,将业务逻辑代码与外观呈现分离,将会更容易地根据需求的改变来改进程序。MVC 模式的模型下图所示。

img

**Model(模型):**MVC 模式中的 Model(模型)指的是业务逻辑的代码,是应用程序中真正用来完成任务的部分。

**View(视图):**视图实际上就是程序与用户进行交互的界面,用户可以看到它的存在。视图可以具备一定的功能,并应遵守对其所做的约束。在视图中,不应包含对数据处理的代码,即业务逻辑代码。

**Controller(控制器):**控制器主要用于控制用户请求并做出响应。它根据用户的请求,选择模型或修改模型,并决定返回什么样的视图。

JSP脚本元素

JSP脚本元素的概念

在JSP中嵌入的服务端(即Web后端)运行的小程序,称为脚本。而JSP支持的服务端脚本语言为Java,所以这些脚本其实就是Java程序。这些脚本程序可以是变量的声明方法的声明完成指定功能的代码块以及方法的调用等,除了类声明之外的所有形式的Java代码都可以作为脚本程序嵌入在JSP页面中,从而完成业务逻辑(用户登录验证、用户信息的增删改查等)、后台数据库操作(创建数据库连接、执行SQL等)等相关服务端(即Web后端)的功能。
其实,JSP脚本元素就是嵌入在JSP页面中的Java程序,这些Java程序将出现在由当前JSP页面生成的Servlet中。按照不同的嵌入方式和不同的作用,脚本元素可分为3种:表达式、Scriptlet、声明,如图所示

img

程序综合案例:利用JSP实现一个登陆页面

这里首先要讲一下JSP request对象,它可以获取客户端的请求信息

客户端可通过 HTML 表单或在网页地址后面提供参数的方法提交数据,然后通过 request 对象的相关方法来获取这些数据。request 对象封装了客户端的请求信息,包括用户提交的信息以及客户端的一些信息,服务端通过 request 对象可以了解到客户端的需求,然后做出响应。

request 对象是 HttpServletRequest(接口)的实例。请求信息的内容包括请求的标题头(Header)信息(如浏览器的版本信息语言和编码方式等),请求的方式(如 HTTP 的 GET 方法、POST 方法等),请求的参数名称、参数值和客户端的主机名称等。

request 对象提供了一些方法,主要用来处理客户端浏览器提交的请求中的各项参数和选项。表 1 列出了 request 对象常用的方法。下面介绍 request 对象的应用。

方法 说明
Object getAttribute(String name) 用于返回由 name 指定的属性值,如果指定的属性值不存在, 则返回一个 null 值
Enumeration getAttributeNames() 用于返回 request 对象的所有属性的名称集合
String getCharacterEncoding() 用于返回一个 String,它包含请求正文中所使用的字符编码
int getContentLength() 用于返回请求正文的长度(字节数),如果不确定,返回 -1
String getContenType() 得到请求体的 MIME 类型
ServletlnputStream getInputStream() 用于返回请求的输入流,用来显示请求中的数据
String getParameter(String name) 用于获取客户端传送给服务器端的参数。主要由 name 指定, 通常是表单中的参数
Enumeration getParameterNames() 用于获取客户端传送的所有参数的名字集合
String getParameterValues(String name) 用于获得指定参数的所有值,由 name 指定
String getProtocol() 用于返回客户端向服务器端传送数据所依据的协议名称
String getMethod() 用于获得客户端向服务器端传送数据的参数方法,主要有两个, 分别是 get() 和 post()
String getServerName() 用于获得服务器端的主机名字
int getServletPath() 用于获得 JSP 文件相对于根地址的地址
String getRemoteAddr() 用于获得客户端的网络地址
String getRemoteHost() 用于获取发送此请求的客户端主机名
String getRealPath(String path) 用于获取一虚拟路径的真实路径
cookie[] get Cookie() 用于获取所有的 Cookie 对象
void setAttribute(String key,Object obj) 设置属性的属性值
boolean isSecure() 返回布尔类型的值,用于确定这个请求是否使用了一个安全协 议,如 HTTP
boolean isRequestedSessionldPromCookie() 返回布尔类型的值,表示会话是否使用了一个 Cookie 来管理 会话 ID
boolean isRequestedSessionIdFromURL() 返回布尔类型的值,表示会话是否使用了一个URL来管理会话 ID
boolean isRequestedSessionldFromVoid() 检查请求的会话 ID 是否合法

如果你使用request对象的相关方法时,编译器出现报错的情况,则你需要将相关的包引入

以IDEA为例:我们需要打开项目结构->项目设置->库,然后点击加号,将tomcat目录下的bin目录添加到模块中就可以了。

img

[示例1]:获取客户信息

request 对象就是利用表 1 列举的那些 get 方法,来获取客户端的信息。

例:应用 request 对象获取客户信息,代码如下:

<%@ page contentType="text/html;charset=utf-8" %>
<html>
<head>
<title>
    request对象获取客户信息
</title>
</head>
<body>
客户提交信息的方式:<%=request.getMethod() %> <br/>
使用的协议:<%=request.getProtocol() %> <br/>
获取提交数据的客户端IP地址:<%=request.getRemoteAddr() %> <br/>
获取服务器端的名称:<%=request.getServerName() %> <br/>
获取服务器端口号:<%=request.getServerPort() %> <br/>
获取客户端的机器名称:<%=request.getRemoteHost() %> <br/>
</body>
</html>

运行结果

img

获取请求参数

用户借助表单向服务器提交数据,完成用户与网站之间的交互,大多数 Web 应用程序都是这样的。表单中包含文本框、列表、按钮等输入标记。当用户在表单中输入信息后,单击提交按钮提交给服务器处理。

用户提交的表单数据存放在 request 对象里,通常在 JSP 代码中用 getParameter() 或者 getParameterValues() 方法来获取表单传送过来的数据

其中getParameter()用于获取单值,如文本框、按钮等。

getParameterValues()用于获取数组,如复选框或者多选列表项。

这两个方法的接口定义如下:

String getParameter(String name);
String[] getParameterValues(String name);

以上两种方法的参数 name 与 HTML 标记的 name 属性对应,如果不存在,则返回 null

另外要注意的是,利用 request 的方法获取表单数据时,默认情况下,字符编码为 ISO-8859-1,所以,当获取客户提交的汉字字符时,会出现乱码问题,必须进行特殊处理。

**方法一:**将获取的字符串用 ISO-8859-1 进行编码,并将编码存放到一个字节数组中,然后再将这个数组转化为字符串对象即可,这种方法仅适用于处理表单提交的单值数据或者查询字符串中所传递的参数。关键代码如下:

String s1=request.getParameter("UserName");
byte tempB[]=s1.getByte("ISO-8859-1");
String s1=new String(tempB);

**方法二(推荐):**下面设置编码格式的语句在获取表单提交的单值或者数组数据时都更为常用:

<%
request.setCharacterEncoding("GBK");    //设置编码格式为中文编码,或者utf-8
%>

**[示例2]:应用 request 对象获取请求参数。**在 3-5.jsp 页面中,利用表单向 3-5-1.jsp 页面提交用户的注册信息,包括用户名、密码和爱好。

前端代码如下:

<%@ page contentType="text/html;charset=utf-8" %>
<html>
<head>
<title>
    request对象获取请求参数
</title>
</head>
<body>
<h2> 个人注册 </h2>
<form name="form1" method="post" action="3-5-1.jsp">
用户名:<input name="username" type="text"/> <br>
密&nbsp;&nbsp;&nbsp;码:<input name="pwd" type="text" /> <br>
<input name="inst" type="checkbox" value="音乐">音乐
<input name="inst" type="checkbox" value="舞蹈">舞蹈
<input name="inst" type="checkbox" value="读书">读书
<input name="inst" type="checkbox" value="游泳">游泳 <br>
<input type="submit" value="提交" />
<input type="reset" value="重置" />
</form>
</body>
</html>

后端代码如下:

<%@ page contentType="text/html;charset=utf-8" %>
<html>
<head>
<title>
    request对象获请求参数
</title>
</head>
<body>
<h2> 获取到的注册信息如下:</h2>
<%
request.setCharacterEncoding("utf-8");
String username=request.getParameter("username");
String pwd=request.getParameter("pwd");
String inst[]=request.getParameterValues("inst");
out.println("用户名为:"+username+"<br>");
out.println("密码为:"+pwd+"<br>");
out.println("爱好为:");
for(int i=0;i<inst.length;i++)
   out.println(inst[i]+" ");
%>
</body>
</html>

通过request对象的getParameter方法可以获取用户提交的请求,从而实现登陆功能

例如

<%
    request.setCharacterEncoding("utf-8");
    String name=request.getParameter("name");
    String pwd=request.getParameter("pwd");
    out.println("用户名为:"+name+"<br>");
    out.println("密码为:"+pwd+"<br>");
%>

然后在浏览器中输入这些

Q.E.D.