JAVAWeb(三) | JSP

8. JSP

新建一个 jsp,hello.jsp,内容和 html 几乎一样,但是要处理动态页面,要请求 Servlet 类
在这里插入图片描述

8.1、什么是 JSP

Java Server Pages : Java 服务器端页面,也和 Servlet 一样,用于动态Web技术!

最大的特点:

  • 写JSP就像在写HTML
  • 区别:
    • HTML只给用户提供静态的数据
    • JSP页面中可以嵌入JAVA代码,为用户提供动态数据;

8.2、JSP原理

思路:JSP到底怎么执行的!

  • 代码层面没有任何问题
  • 服务器内部工作

Tomcat 中有一个 work 目录;在安装包下去找
在这里插入图片描述

IDEA 中使用 Tomcat 的会在 IDEA 的 Tomcat 中产生一个 work 目录,进入 IDEA → \to Help → \to Show Log in Explorer,会弹出 IDEA 的安装目录

在这里插入图片描述

点击进入目录下的 tomcat 目录,选择某个项目进入到如下目录:会发现 jsp 的文件就在这里(C:\Users\86182\AppData\Local\JetBrains\IntelliJIdea2023.1\tomcat
在这里插入图片描述

在这里插入图片描述

我的目录如下:

C:\Users\15592\AppData\Local\JetBrains\IntelliJIdea2022.1\tomcat\3e92441c-ce9e-47df-b69e-9b63cc373253\work\Catalina\localhost\request\org\apache\jsp

发现页面转变成了Java 程序!
在这里插入图片描述

浏览器向服务器发送请求,不管访问什么资源,其实都是在访问 Servlet!

JSP最终也会被转换成为一个 Java 类!

记事本点开上面的某个 jsp.java ,看一看源码,看到 index_jsp 继承了 HttpJspBase 这个父类,暂时没看到继承 Servlet
在这里插入图片描述

要查看 HttpJspBase 类,首先要到 maven 仓库找到 Jasper Runtime
在这里插入图片描述
添加 maven 依赖

<!-- https://mvnrepository.com/artifact/tomcat/jasper-runtime -->
<dependency>
    <groupId>tomcat</groupId>
    <artifactId>jasper-runtime</artifactId>
    <version>5.5.23</version>
</dependency>

然后进入到 HttpJspBase 类里面发现继承了 HttpServlet
在这里插入图片描述
JSP 本质上就是一个Servlet!

再看我们在 IDEA 中写的 index.jsp,如下:
在这里插入图片描述

在 index_jsp.java 中有对应的实现,如下:
在这里插入图片描述

因此我们在撰写 index.jsp 的时候只需要简单的撰写(如同 html 一样),内部会转换好,继续看 index_jsp.java 中的实现方法

从下面可以看出,JSP 本质上就是一个Servlet

//初始化
public void _jspInit() {
      
}
//销毁
public void _jspDestroy() {
}

//JSPService
public void _jspService(.HttpServletRequest request,HttpServletResponse response)

下面分析 JSP 执行过程

1. _jspService 中首先执行判断请求

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException

    if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      final java.lang.String _jspx_method = request.getMethod();
      if ("OPTIONS".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        return;
      }
      if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
        return;
      }
  • 该段代码的主要目的是确保只有合法的 HTTP 请求方法(GET, POST, HEAD 或 OPTIONS)能够通过,其他方法将返回 405 错误,提示客户端不支持的请求方法。
  • 它特别适用于处理 JSP 页面请求,并为 OPTIONS 请求提供特别处理,明确指示服务器支持哪些方法。

2. 内置一些对象(很重要,记住!!!)

final javax.servlet.jsp.PageContext pageContext;  //页面上下文
javax.servlet.http.HttpSession session = null;    //session
final javax.servlet.ServletContext application;   //applicationContext
final javax.servlet.ServletConfig config;         //config
javax.servlet.jsp.JspWriter out = null;           //out
final java.lang.Object page = this;               //page:当前页
HttpServletRequest request                        //请求
HttpServletResponse response                      //响应
  • applicationContext 实质上就是 servletContext

3. 输出页面前增加的代码
在这里插入图片描述

response.setContentType("text/html");       //设置文本响应的页面类型为 html
pageContext = _jspxFactory.getPageContext(this, request, response,
       null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext(); // ServletContext
config = pageContext.getServletConfig(); // Servlet 配置
session = pageContext.getSession(); // 获取 Session
out = pageContext.getOut();
_jspx_out = out;

这段代码展示了如何设置响应类型、初始化页面上下文、以及获取与 JSP 页面的执行相关的各个对象。每一行代码都在为 JSP 页面的执行做准备,确保请求被正确处理并生成适当的响应。

1. response.setContentType("text/html");

  • 含义:设置响应的内容类型为 text/html,即告诉浏览器该响应是一个 HTML 页面。这是一个标准的 HTTP 头部,用于指示响应内容的 MIME 类型。在这里,它告诉客户端(如浏览器)返回的数据是 HTML 格式。
  • 如何使用:通常,JSP 页面在生成响应时会自动设置内容类型,但在某些情况下,也可以手动设置此内容类型。它通常在页面的开头部分调用。

2. pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true);

  • 含义_jspxFactory.getPageContext() 方法用于创建一个 PageContext 对象。PageContext 是 JSP 页面中用于存储页面级别的信息和与请求/响应相关的对象的上下文。它是 JSP 页面的执行环境,提供了对页面范围内的各种对象(如 requestresponsesessionapplication 等)的访问。

    • this: 当前的 JSP 页面实例。
    • request: HTTP 请求对象,包含来自客户端的请求信息。
    • response: HTTP 响应对象,用于设置响应信息并返回给客户端。
    • null: 在此处通常表示 errorPage,如果页面没有错误页处理器,则为 null
    • true: 表示是否自动生成错误页面。
    • 8192: 表示缓存的缓冲区大小(字节数)。
    • true: 是否自动刷新输出流。

    getPageContext() 方法会返回一个 PageContext 对象,这个对象会为 JSP 页面提供运行时环境。

3. _jspx_page_context = pageContext;

  • 含义:将刚才获取的 pageContext 对象赋值给 _jspx_page_context(一个内部变量)。这个操作是为了让后续的代码可以使用这个 PageContext 对象来访问 JSP 的上下文信息。

4. application = pageContext.getServletContext();

  • 含义:从 pageContext 中获取 ServletContext 对象,ServletContext 是表示整个 Web 应用的上下文。它用于提供关于 Web 应用的信息,并允许各个组件(如 Servlet 和 JSP)共享数据。

    • 用途:你可以使用 application 对象在整个 Web 应用中存储数据(通过 setAttribute()),并可以通过 getAttribute() 获取共享的数据。

5. config = pageContext.getServletConfig();

  • 含义:从 pageContext 获取 ServletConfig 对象,ServletConfig 是每个 Servlet(包括 JSP 页面)在启动时的配置信息。它提供了与当前 Servlet 相关的初始化参数和其他配置项。

    • 用途config 可以用来获取 JSP 页面或 Servlet 的初始化参数(通过 getInitParameter())。

6. session = pageContext.getSession();

  • 含义:从 pageContext 获取 HttpSession 对象,HttpSession 用于存储与特定用户会话相关的数据。

    • 用途session 对象允许你存储和检索与当前会话相关的数据(例如,用户登录状态、购物车信息等)。你可以使用 session.setAttribute() 来保存会话数据,使用 session.getAttribute() 来访问数据。

7. out = pageContext.getOut();

  • 含义:从 pageContext 获取 JspWriter 对象,JspWriter 是用于输出 HTML 内容的对象。

    • 用途out 用于在 JSP 页面中输出动态生成的内容。你可以使用 out.print()out.println() 方法来输出 HTML 内容或其他文本到客户端浏览器。

8. _jspx_out = out;

  • 含义:将 out 对象赋值给 _jspx_out(一个内部变量)。这个操作确保可以在后续的代码中继续使用 out 对象进行内容输出。

总结

  • 这段代码展示了 JSP 页面底层如何设置响应类型、创建和管理页面上下文、以及获取与页面相关的各类对象(如 ServletContextHttpSessionJspWriter 等)。这些对象在 JSP 页面的执行过程中用于与客户端和服务器进行交互。

4. 以上的这些个对象我们可以在JSP页面中直接使用!

比如页面设置
在这里插入图片描述

请求
在这里插入图片描述

Session 获取与设置
在这里插入图片描述

在这里插入图片描述

同时 JSP 内可以写 java 代码,为什么可以直接用,是因为第 3 步,输出页面前增加的代码部分已经配置好了,写 java 代码时,放入到 <% %>
在这里插入图片描述

在 JSP 页面中,内置对象如 responseapplicationconfigsessionoutrequest 可以用于多种不同的用途。以下是每个对象的多种使用示例:

1. response (HttpServletResponse)
  • 设置内容类型

    <%
      response.setContentType("text/html");
    %>
    
  • 设置响应头

    <%
      response.setHeader("Cache-Control", "no-cache");
    %>
    
  • 重定向到另一个页面

    <%
      response.sendRedirect("https://www.example.com");
    %>
    
  • 发送错误响应

    <%
      response.sendError(HttpServletResponse.SC_NOT_FOUND, "Page not found");
    %>
    
2. application (ServletContext)
  • 设置全局属性

    <%
      application.setAttribute("appVersion", "1.0.0");
    %>
    
  • 获取全局属性

    <%
      String version = (String) application.getAttribute("appVersion");
      out.println("App Version: " + version);
    %>
    
  • 共享数据

    <%
      application.setAttribute("totalVisitors", 1000);
    %>
    
  • 获取应用初始化参数

    <%
      String dbUrl = application.getInitParameter("databaseURL");
      out.println("Database URL: " + dbUrl);
    %>
    
3. config (ServletConfig)
  • 获取初始化参数

    <%
      String param = config.getInitParameter("maxConnections");
      out.println("Max Connections: " + param);
    %>
    
  • 获取当前 Servlet 名称

    <%
      String servletName = config.getServletName();
      out.println("Servlet Name: " + servletName);
    %>
    
4. session (HttpSession)
  • 设置会话属性

    <%
      session.setAttribute("username", "john_doe");
    %>
    
  • 获取会话属性

    <%
      String user = (String) session.getAttribute("username");
      out.println("Welcome, " + user);
    %>
    
  • 获取会话 ID

    <%
      String sessionId = session.getId();
      out.println("Session ID: " + sessionId);
    %>
    
  • 检查会话是否存在

    <%
      if (session.isNew()) {
          out.println("This is a new session.");
      }
    %>
    
5. out (JspWriter)
  • 输出文本

    <%
      out.println("Hello, JSP World!");
    %>
    
  • 输出 HTML 元素

    <%
      out.println("<h1>Welcome to the JSP page!</h1>");
    %>
    
  • 输出 JavaScript 代码

    <%
      out.println("<script>alert('Page Loaded');</script>");
    %>
    
  • 格式化输出

    <%
      out.printf("Current time: %tT", new java.util.Date());
    %>
    
6. request (HttpServletRequest)
  • 获取请求参数

    <%
      String name = request.getParameter("name");
      out.println("Hello, " + name);
    %>
    
  • 获取请求头信息

    <%
      String userAgent = request.getHeader("User-Agent");
      out.println("User-Agent: " + userAgent);
    %>
    
  • 获取客户端 IP 地址

    <%
      String clientIp = request.getRemoteAddr();
      out.println("Client IP: " + clientIp);
    %>
    
  • 获取请求方法

    <%
      String method = request.getMethod();
      out.println("Request Method: " + method);
    %>
    
  • 获取请求中的属性

    <%
      String attribute = (String) request.getAttribute("userRole");
      out.println("User Role: " + attribute);
    %>
    

假设我们现在新建一个 hello.jsp 内容如下,然后重启 tomcat
在这里插入图片描述

在启动 tomcat 还未完成的过程中,找到刚刚 IDEA 中的 tomcat 对应的项目目录下,发现之前的什么都没有了 (本来应该有:C:\Users\15592\AppData\Local\JetBrains\IntelliJIdea2022.1\tomcat\28f4f38f-a9f6-4d87-ad9e-3e377fc1b4d3\work\Catalina\localhost\ROOT\org\apache\jsp)
在这里插入图片描述

启动完成后才出现了 index_jsp.java
在这里插入图片描述
在这里插入图片描述

然后请求 hello.jsp,成功
在这里插入图片描述

刚刚的文件夹产生了 hello_jsp.java !
在这里插入图片描述

进入到 hello_jsp.java ,发现除了下图这里输出部分不一样,其他都一样
在这里插入图片描述

通过上面的流程,我们知道要去访问浏览器才会生成对应 jsp 的 java 代码!

执行流程总结: 程序员通过电脑上网,上网本质是访问服务器,服务器中存在多个 web 容器(tomcat),tomcat 可以存放很多网站,访问到 web 容器,回去判断对应的请求,如果是 JSP,会去找 JSP 的页面,找到 JSP 不能直接使用,首先需要进行转换为 JAVA 文件,这是 web 容器去做得,转换后得到 xxx_jsp.java,然后将 xxx_jsp.java 编译为 class 文件,xxx_jsp.class,xxx_jsp.class 返回给服务器,然后我们得到的就是这个服务器处理完的 xxx_jsp.class ,这个就是 Servlet!访问 JSP 本质还是 Servlet
在这里插入图片描述

下面我们在 hello.jsp 中撰写一段 java 代码,<%=name%> 是把 name 取出
在这里插入图片描述

然后重启 tomcat
在这里插入图片描述

此时文件夹中还没有 hello.jsp
在这里插入图片描述

下面请求 hello.jsp,成功取出数据
在这里插入图片描述
在这里插入图片描述

进入到 hello_jsp.java,发现 java 代码原封不动的放入了进入,并执行了 out.print(name); 输出
在这里插入图片描述

在JSP页面中;只要是 JAVA代码就会原封不动的输出;如果是HTML代码,就会被转换为:

out.write("<html>\r\n");

这样的格式,输出到前端!

8.3、JSP基础语法

先新建一个 JSP 项目
在这里插入图片描述

注意新项目配置 maven 仓库
在这里插入图片描述

pom.xml 中导入依赖,比之前多了一个 jstl-api
在这里插入图片描述

还需要一个 standard
在这里插入图片描述

  <dependencies>


    <!--      servelt 依赖-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
    </dependency>

    <!--      jsp 依赖-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.3</version>
    </dependency>
    
    <!-- jstl 表达式的依赖 -->
    <dependency>
      <groupId>javax.servlet.jsp.jstl</groupId>
      <artifactId>jstl-api</artifactId>
      <version>1.2</version>
    </dependency>

    <!-- jstl 依赖的一些 standard 标签 -->
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>

  </dependencies>

配置好 tomcat。

在这里插入图片描述

最后将原始创建的 index.jsp 删除掉,再新建一个 index.jsp,为什么这样,因为新建的 index.jsp 多了一行

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

这一行可以解决中文乱码问题,否则后续操作就会产生中文乱码现象!

在这里插入图片描述

任何语言都有自己的语法,JAVA 中有。 JSP 作为 java 技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可!),Java所有语法都支持!

8.3.1、JSP表达式

在 index.jsp 中添加如下代码

  <%--JSP表达式
  作用:用来将程序的输出,输出到客户端
  <%= 变量或者表达式%>
  --%>
  <%= new java.util.Date()%>

在这里插入图片描述

在 tomcat 启动的状态下,按下 Ctrl + F10,弹出如下框,选择 Redeploy,实际上是 tomcat 的热部署,就不需要重新启动 tomcat 了

在这里插入图片描述

访问后就成功打印时间了!
在这里插入图片描述

<hr>:分割线

8.3.2、jsp脚本片段


<%--jsp脚本片段--%>
<%
  int sum = 0;
  for (int i = 1; i <=100 ; i++) {
    sum+=i;
  }
  out.println("<h1>Sum="+sum+"</h1>");
%>

在这里插入图片描述

在 tomcat 启动的状态下,按下 Ctrl + F10,弹出如下框,选择 Redeploy,实际上是 tomcat 的热部署,就不需要重新启动 tomcat 了,然后刷新浏览器
在这里插入图片描述


下面这个情况是不被允许的,因为上面那个片段已经产生了 x 这个变量,下面就不能再定义了,但是下面那个片段可以直接使用上面定义好的。
在这里插入图片描述
打印输出

 <%
    int x = 10;
    out.println(x);
  %>
  <p>这是一个JSP文档</p>
  <%
    int y = 2;
    out.println(y);
  %>

  <hr>

在这里插入图片描述

在代码嵌入HTML元素

<%--在代码嵌入HTML元素--%>
<%
    for (int i = 0; i < 5; i++) {
%>
<h5>Hello,World  <%=i%> </h5>
<%
    }
%>

在这里插入图片描述

下面看一下 通过 编译产生的 xxx_ jsp.java 代码,该有的都有

在这里插入图片描述

8.3.3 JSP 声明: <%! %> 定义方法和全局变量

<%!
    static {
        System.out.println("Loading Servlet!");
    }

    private int globalVar = 0;

    public void kuang(){
        System.out.println("进入了方法Kuang!");
    }
%>

在这里插入图片描述

JSP声明: 会被编译到JSP生成Java的类中!其他的,就会被生成到_jspService方法中!

在JSP中嵌入Java代码即可!

除了上述通过 <%=%> 取值外,还可以通过 ${} 的方式取值

<%%> 片段
<%=%> 表达式输出值
<%!%> 定义全局方法变量
<%–注释–%> 注释

JSP 中同样可以用 html 的注释,我们来看下区别

<%--我是 JSP 的注释--%>
<!-- 我是 html 的注释-->

代码中写入
在这里插入图片描述

热部署 tomcat,然后刷新页面,注释没有被显示出来
在这里插入图片描述

右击页面,查看页面源代码,能够看到 html 的注释,而看不到 jsp 的注释
在这里插入图片描述
JSP的注释,不会在客户端显示,HTML就会!

下面新建 jsp2,输入一个除 0 错误,
在这里插入图片描述

热部署 tomcat,并访问 jsp2.jsp,报错异常
在这里插入图片描述

下面有这样一个需求:当发生如下错误时,不弹出如上的页面,而是弹出我们指定的页面

额外tips:JSP 也支持像 java import 那样导包,比如如下
在这里插入图片描述

新建文件夹 error,新建 500.jsp,并放入如下内容:
在这里插入图片描述

然后在 jsp2.jsp 中添加错误跳转操作:<%@ page errorPage="error/500.jsp" %>
在这里插入图片描述

热部署 tomcat,请求 jsp2.jsp,跳转到了我们自定义的界面
在这里插入图片描述

下面不显示字,跳转后显示图片,新建 img,随便放入一张图,更改 jsp2.jsp 的内容:<img src="../img/500.jpg" alt="500">
在这里插入图片描述

热部署 tomcat,请求 jsp2.jsp,跳转到了我们定义好了图片的界面。注意如果代码没有错是不会跳的
在这里插入图片描述

上面是 500 错误,可能还会有 404 错误,erro 文件夹中增加 404.jsp,如下内容
在这里插入图片描述

然后配置 web.xml,配置信息表示出那种错误,对应去找到对应的 jsp

  <error-page>
    <error-code>404</error-code>
    <location>/error/404.jsp</location>
  </error-page>

  <error-page>
    <error-code>500</error-code>
    <location>/error/500.jsp</location>
  </error-page>

在这里插入图片描述

热部署 tomcat,请求 jsp2.jsp,正常显示之前的信息,然后输入一个肯定不存在的页面,回车

在这里插入图片描述

进入了 404 错误页面
在这里插入图片描述


错误跳转:

<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>

<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>

<%@ page errorPage="error/500.jsp" %>

这两种方式都用于处理 JSP 页面中的错误,但它们在应用范围和使用场景上有所不同。下面是两者的对比和详细解释:

1. <error-page> 配置(在 web.xml 中)

这是在 web.xml 配置文件中为 HTTP 错误代码设置错误页面的方式。它是 Web 应用级别的配置,适用于整个应用中的所有请求,而不仅仅是某个特定的 JSP 页面。

示例:
<error-page>
    <error-code>404</error-code>
    <location>/error/404.jsp</location>
</error-page>

<error-page>
    <error-code>500</error-code>
    <location>/error/500.jsp</location>
</error-page>
解释:
  • <error-page> 配置指示当服务器发生特定的 HTTP 错误时(如 404 或 500),应该跳转到哪个错误页面。
  • <error-code>:指定捕获的错误代码(如 404 或 500)。
  • <location>:指定错误页面的 URL,当发生指定的错误时,用户会被重定向到该页面。
使用场景:
  • 全局配置:它适用于整个 Web 应用。当某个特定错误(如 404 或 500)发生时,无论是来自哪个 Servlet 或 JSP 页面,都会跳转到指定的错误页面。
  • 适用 HTTP 错误:此配置捕获的是 HTTP 错误(如 404、500、403 等)并将其重定向到自定义页面。
示例:
  • 当用户访问不存在的页面时(如 /nonexistent.jsp),Web 容器会返回 404 错误并重定向到 /error/404.jsp 页面。
  • 当服务器发生内部错误时(如空指针异常),Web 容器会返回 500 错误并重定向到 /error/500.jsp 页面。

2. <%@ page errorPage="error/500.jsp" %> 配置(JSP 指令)

这是在 JSP 页面中指定错误处理页面的方式。它用于在当前 JSP 页面发生异常时,转向指定的错误页面。

示例:
<%@ page errorPage="error/500.jsp" %>
解释:
  • errorPage 指令用于指定当当前 JSP 页面抛出异常时,转向哪个错误页面。
  • 在当前页面发生未捕获的异常时,JSP 容器会自动将用户重定向到指定的错误页面。
使用场景:
  • 局部配置:它仅适用于当前的 JSP 页面。只有在该页面内部发生异常时,才会跳转到指定的错误页面。
  • 适用 JSP 内部错误:它只捕获 JSP 页面内抛出的异常,而不会捕获 HTTP 错误或其他类型的错误。
示例:
  • 如果在 index.jsp 页面中发生了未处理的异常(如 NullPointerException),并且该页面配置了 errorPage 指令,用户会被重定向到 error/500.jsp 页面。

3. 对比:<error-page> 配置 vs <%@ page errorPage="..." %> 指令
特性<error-page> 配置 (web.xml)<%@ page errorPage="..." %> 指令
作用范围Web 应用级别,全局配置单个 JSP 页面
捕获类型HTTP 错误(如 404、500 等)JSP 页面内抛出的异常(如 NullPointerException 等)
配置位置web.xml 配置文件JSP 页面顶部的指令
错误处理处理所有请求中的 HTTP 错误仅处理当前 JSP 页面中的异常
适用场景用于 HTTP 错误(如 404、500)用于 JSP 页面内的异常处理(如编程错误、空指针等)
错误页面可以为不同的错误代码配置不同的错误页面仅为该 JSP 页面配置一个错误页面
4. 总结
  • <error-page> 配置 是全局配置,适用于整个 Web 应用,捕获 HTTP 错误(如 404、500)并重定向到指定的错误页面。它位于 web.xml 文件中,并且不依赖于单个 JSP 页面。

  • <%@ page errorPage="..." %> 指令 是局部配置,仅在当前 JSP 页面中适用。它捕获该页面内的异常,并跳转到指定的错误页面,通常用于处理编程错误或其他运行时异常。

因此:

  • 如果你需要处理 HTTP 错误(例如页面未找到、服务器内部错误等),可以使用 web.xml 中的 <error-page> 配置。
  • 如果你只需要处理单个 JSP 页面内的异常,应该使用 <%@ page errorPage="..." %> 指令。

8.4、JSP指令(了解即可,重点是上面基础语法部分)

<%@page args.... %>
<%@include file=""%>

<%--@include会将两个页面合二为一--%>

<%@include file="common/header.jsp"%>
<h1>网页主体</h1>

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

<hr>


<%--jSP标签
    jsp:include:拼接页面,本质还是三个
    --%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>

<%@include file=""%>,包含其他的 jsp 文件进来,比如在 common 文件夹下定义 header.jsp 和 footer.jsp,然后最外层文件夹创建一个 jsp3.jsp 为主页面,并调用 header.jsp 和 footer.jsp

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

jsp3.jsp 页面内容如下
在这里插入图片描述

热部署 tomcat,请求 jsp3.jsp
在这里插入图片描述

如何直接访问 header 页面,通过项目下完整的目录:localhost:8080/common/header.jsp
在这里插入图片描述


下面使用 jsp 标签

<%--jSP标签
    jsp:include:拼接页面,本质还是三个
    --%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>

在这里插入图片描述

同样达到了上面的效果
在这里插入图片描述


下面看一下两者的区别,进入到 jsp3_jsp.java 的代码当中。

先看如下代码情况:

<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>

相当于拼接页面,本质还是三个(推荐使用的方式)
在这里插入图片描述

下面这种情况

<%@include file="common/header.jsp"%>
<h1>网页主体</h1>

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

将其他两个 jsp 中的内容一起放入到了 jsp3.jsp 当中!,使其合二为一了
在这里插入图片描述

合二为一会出现一个问题,比如在 header.jsp 中我定义了一个 int i,然后在主页面 jsp3.jsp 中,我先引入 header.jsp ,然后又定义了一个 int i,请求的时候就会报 500 的错!

main 下面就只放 java 和 resources 文件夹,不要存放其他任何文件夹

8.5、9 大内置对象

  • PageContext 代表一个页面,存东西
  • Request 存东西
  • Response
  • Session 存东西
  • Application 【SerlvetContext】 存东西
  • config 【SerlvetConfig】 配置
  • out 输出
  • page ,不用了解
  • exception

新建一个 pageContextDemo01.jsp,放入以下内容,实现存东西

脚本片段 <% %> 中的代码,会原封不动的生成到 JSP.java 中,这里面的代码必须保证 java 语法的正确性!即不能出现 JSP 类型的注释,如:<%--取出保存的值--%>

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

<%--内置对象--%>
<%--从底层到高层作用于:page -> request ->  session  -> application,application--%>
<%
    pageContext.setAttribute("name1","future1号"); //保存的数据只在一个页面中有效
    request.setAttribute("name2","future2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
    session.setAttribute("name3","future3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
    application.setAttribute("name4","future4号");  //保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>

<%--取出保存的值--%>
<%

    String name1 = (String) pageContext.getAttribute("name1");
    String name2 = (String) request.getAttribute("name2");
    String name3 = (String) session.getAttribute("name3");
    String name4 = (String) application.getAttribute("name4");
    String name5 = (String) application.getAttribute("name5"); // 不存在

%>

<%--使用 EL 表达式输出--%>
<h1>取出的值为:</h1>
<h1>${name1}</h1>
<h1>${name2}</h1>
<h1>${name3}</h1>
<h1><%=name4%></h1>
<h1><%=name5%></h1>

</body>
</html>

热部署 tomcat,请求 pageContextDemo01.jsp,不存在的值打印出了 null(因为使用 <%=name5%> 取值),如果使用 ${name5},会自动过滤,不会打印出任何东西
在这里插入图片描述

现有三个 page,三个 Servlet 请求:s1, s2, s3,三个 page 是三个不一样的浏览器,但是现在想存东西。下面有几种方法,首先是 request 作用域:比如第一个 page 请求 s1,携带了一个 name 数据,如果 s1 不转发,这个数据就不会存在了,但是可以通过转发,比如 s1 转发到 s2,s2 就拿到了这个数据

在这里插入图片描述

可以在服务器中存数据(session),三个浏览器 page,会产生三个 sesison,每个浏览器对应一个 session,但是无论是在 session 几存东西,所有 page 都可以拿到 session 1, 2, 3 的数据,因为数据是在服务器上的。

在这里插入图片描述

从底层到高层作用于:page -> request -> session -> application,application 都没找到,就不存在了,JVM 有一个双亲委派机制,也是逐渐找包的过程

pageContextDemo01.jsp 代码以及内容如下

<%--
  Created by IntelliJ IDEA.
  User: 15592
  Date: 2024/7/28
  Time: 20:37
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<%--内置对象--%>
<%
    pageContext.setAttribute("name1","future1号"); //保存的数据只在一个页面中有效
    request.setAttribute("name2","future2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
    session.setAttribute("name3","future3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
    application.setAttribute("name4","future4号");  //保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>

<%--取出保存的值--%>
<%

    String name1 = (String) pageContext.getAttribute("name1");
    String name2 = (String) request.getAttribute("name2");
    String name3 = (String) session.getAttribute("name3");
    String name4 = (String) application.getAttribute("name4");
    String name5 = (String) application.getAttribute("name5"); // 不存在

%>

<%--使用 EL 表达式输出--%>
<h1>取出的值为:</h1>
<h1>${name1}</h1>
<h1>${name2}</h1>
<h1>${name3}</h1>
<h1><%=name4%></h1>
<h1><%=name5%></h1>

</body>
</html>

在这里插入图片描述

下面新建 pageDemo02.jsp,内容如下:(相当于只保留了 pageContextDemo01.jsp 中取值的部分)

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

<%--取出保存的值--%>
<%

    String name1 = (String) pageContext.getAttribute("name1");
    String name2 = (String) request.getAttribute("name2");
    String name3 = (String) session.getAttribute("name3");
    String name4 = (String) application.getAttribute("name4");
    String name5 = (String) application.getAttribute("name5"); // 不存在

%>

<%--使用 EL 表达式输出--%>
<h1>取出的值为:</h1>
<h1>${name1}</h1>
<h1>${name2}</h1>
<h1>${name3}</h1>
<h1><%=name4%></h1>
<h1><%=name5%></h1>

</body>
</html>

上述两个 pageDemo02 ,pageContextDemo01 是完全不同的页面,热部署 tomcat 后,先请求 pageContextDemo01 再请求 pageDemo02

在这里插入图片描述

发现只能取出 3 号,4 号,1, 2 号没有了,因为 3 4 号是用 session 和 application,1,2 号是使用 pageContext 和 request。

新建一个 pageDemo03.jsp ,找到 pageContext.setAttribute 的实现

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

<%--

    public static final int PAGE_SCOPE = 1;
    public static final int REQUEST_SCOPE = 2;
    public static final int SESSION_SCOPE = 3;
    public static final int APPLICATION_SCOPE = 4;
    // scope 作用域
    public void setAttribute(String name, Object attribute, int scope) {
        switch (scope) {
            case 1:
                this.mPage.put(name, attribute);
                break;
            case 2:
                this.mRequest.put(name, attribute);
                break;
            case 3:
                this.mSession.put(name, attribute);
                break;
            case 4:
                this.mApp.put(name, attribute);
                break;
            default:
                throw new IllegalArgumentException("Bad scope " + scope);
        }

    }
--%>

<%
    pageContext.setAttribute("hello1", "hello", PageContext.SESSION_SCOPE);
    session.setAttribute("hello1", "hello");
%>

</body>
</html>

PageContext 类下有如下的 scope,用于设置作用域,默认是在当前页面有效,pageContext.setAttribute(“hello1”, “hello”, PageContext.SESSION_SCOPE); 等价于 session.setAttribute(“hello1”, “hello”); 提高到了 session 作用域下

public static final int PAGE_SCOPE = 1;
public static final int REQUEST_SCOPE = 2;
public static final int SESSION_SCOPE = 3;
public static final int APPLICATION_SCOPE = 4;

新建 pageContextDemo02.jsp,内容如下,实现跳转,下面两种跳转方式等价

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

<%
    pageContext.forward("/index.jsp"); // 页面端跳转
    // request.getRequestDispatcher("/index.jsp").forward(request,response); // servlet 后台跳转
%>

</body>
</html>

成功跳转
在这里插入图片描述

request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!

session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;

application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;

pageContext.forward("/index.jsp"); 这种类型实际上就是实现了请求转发,这样 request 携带的内容可以在转发的页面中读取到

8.6、JSP标签、JSTL标签、EL表达式

EL表达式: ${ }

  • 获取数据
  • 执行运算
  • 获取web开发的常用对象

使用需要导入依赖

<!-- JSTL表达式的依赖 -->
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>
<!-- standard标签库 -->
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>

JSP标签部分使用:

新建 jsptag.jsp ,内容如下:(通过 JSP 标签,跳转页面到)

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

<jsp:forward page="/jsptag2.jsp"></jsp:forward>

</body>
</html>

新建 jsptag2.jsp ,内容如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1> 这是一个 JSPtag2 页面 </h1>

</body>
</html>

热部署 tomcat,请求 jsptag.jsp,跳转成功
在这里插入图片描述

重写 jsptag.jsp 如下:(使其转发时携带参数)

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

<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="future"></jsp:param>
    <jsp:param name="age" value="12"></jsp:param>
</jsp:forward>

</body>
</html>

测试 jsptag2.jsp 取出参数

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

名字: <%=request.getParameter("name")%>
年龄: <%=request.getParameter("age")%>

</body>
</html>

热部署 tomcat,请求 jsptag,获取成功
在这里插入图片描述

前面还讲了一个 <jsp:include> 标签,这里不再赘述

JSTL表达式

JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和Java代码一样!

格式化标签(基本不用)

SQL标签(基本不用)

XML 标签(基本不用)

核心标签 (掌握部分)

上述的代码不需要记忆,查找即可,查找地址: https://www.runoob.com/jsp/jsp-jstl.html

在这里插入图片描述
JSTL 可以不使用,写 java 代码一样的可以!

JSTL 标签库使用步骤

  • 引入对应的 taglib
  • 使用其中的方法
  • 在Tomcat 也需要引入 jstl 的包,否则会报错:JSTL解析错误
c:if

if 测试,新建一个 coreif.jsp,内容如下:<form action="coreif.jsp" method="get"> 表示自己请求自己,然后 get 获取自己的表单

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

<%--引入 JSTL 核心标签库,我们才能使用 JSTL 标签--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>


<h4>if测试</h4>

<hr>

<form action="coreif.jsp" method="get"> 
    <%--
    EL表达式获取表单中的数据:${param.参数名}
    --%>
    <input type="text" name="username" value="${param.username}">
    <input type="submit" value="登录">
</form>

</body>

</html>

由于 tomcat 中没有 jstl 和 standard 的包,要手动粘贴到 tomcat 的 lib 文件夹下

在这里插入图片描述

在这里插入图片描述

加入包后重新启动 tomcat,请求 coreif.jsp

在这里插入图片描述

继续用 coreif.jsp 下执行 if 条件命令,如果用户名输入成功则返回 true,否则返回 false

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

<%--引入 JSTL 核心标签库,我们才能使用 JSTL 标签--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>


<h4>if测试</h4>

<hr>

<%----%>
<form action="coreif.jsp" method="get">
    <%--
    EL表达式获取表单中的数据
    ${param.参数名}
    --%>
    <input type="text" name="username" value="${param.username}">
    <input type="submit" value="登录">
</form>

<%--判断如果提交的用户名是管理员,则登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin"> <%-- 这个过程会获取到 isAdmin 为 true or false --%>
    <c:out value="管理员欢迎您!"/>
</c:if>

<%--自闭合标签--%>
<c:out value="${isAdmin}"/> <%--  输出上述的登录状态 --%>

</body>

</html>

在这里插入图片描述

在这里插入图片描述

c:choose、c:when

新建一个 corewhen.jsp ,内容如下

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

<%--定义一个变量score,值为85--%>
<c:set var="score" value="55"/>

<c:choose>
    <c:when test="${score>=90}">
        你的成绩为优秀
    </c:when>
    <c:when test="${score>=80}">
        你的成绩为一般
    </c:when>
    <c:when test="${score>=70}">
        你的成绩为良好
    </c:when>
    <c:when test="${score<=60}">
        你的成绩为不及格
    </c:when>
</c:choose>

</body>
</html>

不知道啥情况
在这里插入图片描述

c:forEach
<%

    ArrayList<String> people = new ArrayList<>();
    people.add(0,"张三");
    people.add(1,"李四");
    people.add(2,"王五");
    people.add(3,"赵六");
    people.add(4,"田六");
    request.setAttribute("list",people);
%>


<%--
var , 每一次遍历出来的变量
items, 要遍历的对象
begin,   哪里开始
end,     到哪里
step,   步长
--%>
<c:forEach var="people" items="${list}">
    <c:out value="${people}"/> <br>
</c:forEach>

<hr>

<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
    <c:out value="${people}"/> <br>
</c:forEach>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值