JavaWeb学习总结(八)jsp详解/头部page指令/声明脚本/表达式脚本/代码脚本/九大内置对象/四大域对象/out输出流和writer输出流/静态包含和动态包含区别/Listener监听器

2021/6/26 14:27:03

本文主要是介绍JavaWeb学习总结(八)jsp详解/头部page指令/声明脚本/表达式脚本/代码脚本/九大内置对象/四大域对象/out输出流和writer输出流/静态包含和动态包含区别/Listener监听器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、jsp简介

(一)概述

JSP(全称 Java Server Pages,Java 的服务器页面)是由 Sun 公司专门为了解决动态生成 HTML 文档的技术。

(二)作用

jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据。
如果我们要往客户端输出一个页面,我们可以使用 Servlet 程序来实现,但是十分不方便和繁琐。 并且有些复杂的页面上千上万行,那就更加的困难,开发成本和维护成本都极高。 所以 sun 公司推出一种叫做 jsp 的动态页面技术帮助我们实现对页面的输出繁锁工作。

(三)如何创建jsp页面

选中 Web目录,右键创建一个 jsp 文件
在这里插入图片描述
输入 jsp 页面的文件名
在这里插入图片描述
在 body 标签中添加你想要显示的文本内容
在这里插入图片描述
然后启动Tomcat,在浏览器中输入 jsp 页面的访问地址
jsp 页面的访问地址和 html 页面的访问路径一样 http://ip地址:端口号/工程名/文件名
在这里插入图片描述

注意:jsp 页面的访问千万不能像 HTML 页面一样,直接手拖到浏览器中或是直接用地址名访问。只能通过启动 Tomcat 服务器再用浏览器访问 jsp 页面

(四)jsp的本质

jsp 页面本质上是一个 Servlet 程序
当我们第一次访问 jsp 页面的时候,Tomcat 服务器会帮我们把 jsp 页面翻译成为一个 java 源文件。并且把它进行编译成为.class 字节码程序。我们可以通过启动Tomcat时IDEA的输出,找到Using CATALINA_BASE这一项,复制后面的地址到我的电脑的地址栏,再逐步点进work/Catalina/localhost/项目名org/apache/jsp,就可以找到我们的jsp页面翻译后的java源文件。我们打开 java 源文件不难发现其里面的内容是:
在这里插入图片描述

我们跟踪原代码发现,这个jsp翻译出来的类继承了HttpJspBase 类,查看HttpJspBase的源码发现,它直接地继承了 HttpServlet 类。也就是说:jsp 翻译出来的 java 类,它间接了继承了 HttpServlet 类。也就是说,jsp页面翻译出来的是一个 Servlet 程序。
在这里插入图片描述

总结:jsp 就是 Servlet 程序。
当我们访问 一个 xxx.jsp 文件后,翻译成 java 文件的全名是 xxx_jsp.java 文件
大家也可以去观察翻译出来的 Servlet 程序的源代码,不难发现,其底层实现,也是通过输出流,把 html 页面数据回传给客户端:
在这里插入图片描述

二、jsp语法

(一)头部的page指令

jsp 的 page 指令可以修改 jsp 页面中一些重要的属性,或者行为。

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

page指令中有如下属性:

  • language 属性 表示 jsp 翻译后是什么语言文件。暂时只支持 java。
  • contentType 属性 设置响应头 contentType 的内容。也是源码中 response.setContentType()参数值
  • pageEncoding 属性 表示当前 jsp 页面文件本身的编码。
  • import 属性 跟 java 源代码中一样,给当前 jsp 页面导入需要使用的类包。
  • autoFlush 属性 设置当 out 输出流缓冲区满了之后,是否自动刷新缓冲区。默认值是 true。
  • buffer 属性 设置 out 缓冲区的大小。默认是 8kb
  • errorPage 属性 设置当前 jsp 发生错误后,需要跳转到哪个页面去显示错误信息,这个页面的路径一般都是以/斜杠打头,它表示请求地址为 http://ip:port/工程路径/,映射到代码的 Web 目录
  • isErrorPage 属性 设置当前 jsp 页面是否是错误页面。是的话,就可以使用 exception 异常对象,从而获取异常信息
  • session 属性 设置当前 jsp 页面是否获取 session 对象,默认为 true
  • extends 属性 给服务器厂商预留的 jsp 默认翻译的 servlet 继承于什么类

(二)常用脚本

1.声明脚本(极少使用)

格式

<%!  
	java 代码 
%>

作用:可以给 jsp 翻译出来的 java 类定义全局变量、方法、静态代码块和内部类等。 (几乎可以写在类的内部写的代码,都可以通过声明脚本来实现)
在这里插入图片描述

2.表达式脚本(常用)

格式<%=表达式 %>
作用:表达式脚本用于向页面输出内容。

  • 表达式脚本翻译到 Servlet 程序的 _jspService() 方法中 以 out.print() 打印输出
  • 由于表达式脚本翻译的内容都在_jspService() 方法中,所以_jspService()方法中的对象,在表达时脚本中都可以直接使用
  • out 是 jsp 的一个内置对象,用于生成 html 的源代码
  • 注意:表达式不要以分号结尾,否则会报错
  • 表达式脚本可以输出任意类型。 比如:
    1. 输出整型
    2. 输出浮点型
    3. 输出字符串
    4. 输出对象

案例

<%=12 %> <br> 
<%=12.12 %> <br> 
<%="我是字符串" %> <br> 
<%=map%> <br> 
<%=request.getParameter("username")%>

和翻译出来的java源代码对照:
在这里插入图片描述

3.代码脚本(使用最多)

格式

<% 
	java 代码 
%> 

作用:代码脚本里可以书写任意的 java 语句。

  • 代码脚本的内容都会被翻译到 _jspService()方法中,所以 _jspService() 方法中可以写的 java 代码,都可以书写到代码脚本中
  • 可以由多个代码脚本块组合完成一个完整的 java 语句。
  • 代码脚本还可以和表达式脚本一起组合使用,在 jsp 页面上输出数据

案例
在这里插入图片描述

在这里插入图片描述
和翻译出来的java源代码对照:
在这里插入图片描述


练习1:在浏览器中输出九九乘法口诀表
在这里插入图片描述

在这里插入图片描述
练习2:jsp 输出一个表格,里面有 10 个学生信息
Student类:

public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private String phone;

    public Student() {
    }

    public Student(Integer id, String name, Integer age, String phone) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.phone = phone;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", phone='" + phone + '\'' +
                '}';
    }
}

Servlet:

import com.fox.bean.Student;

import javax.servlet.ServletException;
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;

public class SearchStudentServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 使用for循环生成查询到的数据做模拟
        List<Student> studentList = new ArrayList<Student>();
        for (int i = 0; i < 10; i++) {
            int t = i + 1;
            studentList.add(new Student(t,"name"+t, 18+t,"phone"+t));
        }
        // 保存查询到的结果(学生信息)到request域中
        req.setAttribute("stuList", studentList);
        // 请求转发到showStudent.jsp页面
        req.getRequestDispatcher("/showStudent.jsp").forward(req,resp);
    }
}

web.xml:

<servlet>
    <servlet-name>SearchStudentServlet</servlet-name>
    <servlet-class>com.fox.servlet.SearchStudentServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>SearchStudentServlet</servlet-name>
    <url-pattern>/searchStudentServlet</url-pattern>
</servlet-mapping>

showStudent.jsp:
在这里插入图片描述
在这里插入图片描述

(三)三种注释

1.html 注释

<!-- 这是 html 注释 -->

html 注释会被翻译到 java 源代码中,在_jspService() 方法里,以 out.writer 输出到客户端。

2.java 注释

用于给脚本中的java代码注释

<% 
	// 单行 java 注释 
	/* 
	多行 java 注释 
	*/ 
%>

java 注释会被翻译到 java 源代码中。

3.jsp 注释

<%-- 这是 jsp 注释 --%> 

jsp 注释可以注释掉jsp 页面中所有代码

三、jsp 九大内置对象

我们打开翻译后的 java 文件,查看_jspService() 方法:
在这里插入图片描述
jsp 中九大内置对象分别是:

  • request 对象 请求对象,可以获取请求信息
  • response 对象 响应对象。可以设置响应信息
  • pageContext 对象 当前页面上下文对象。可以在当前上下文保存属性信息
  • session 对象 会话对象。可以获取会话信息。
  • exception 对象 异常对象只有在 jsp 页面的 page 指令中设置 isErrorPage=“true” 的时候才会存在
  • application 对象 ServletContext 对象实例,可以获取整个工程的一些信息。
  • config 对象 ServletConfig 对象实例,可以获取 Servlet 的配置信息
  • out 对象 输出流。
  • page 对象 表示当前 Servlet 对象实例(用它不如使用 this 对象)。

九大内置对象,都是我们可以在【代码脚本】或【表达式脚本】中直接使用的对象

四、jsp 四大域对象

四大域对象经常用来保存数据信息。

四个域对象分别是:

  • pageContext (PageContextImpl 类) 同一个 jsp 页面范围内有效
  • request (HttpServletRequest 类)一次请求内有效
  • session (HttpSession 类) 一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器)
  • application (ServletContext 类) 整个 web 工程范围内都有效(只要 web 工程不停止,数据都在)

域对象就是可以像 Map 一样存取数据的对象。四个域对象功能一样,不同的是它们对数据的存取范围。 虽然四个域对象都可以存取数据。在使用上它们是有优先顺序的。 四个域在使用的时候,优先顺序是他们有效范围从小到大的顺序:
pageContext ====>>> request ====>>> session ====>>> application

案例:测试四个域对象的作用域(有效范围)
context1.jsp:
在这里插入图片描述

context2.jsp:
在这里插入图片描述

  • 测试 pageContext 作用域

    • 直接访问 context1.jsp 文件
      在这里插入图片描述
  • 测试 request 作用域

    1. 直接访问 context2.jsp 文件 (没有数据)
      在这里插入图片描述
    2. 在 context1.jsp 文件中添加转发到 context2.jsp(page域对象没有数据,request有数据)
      在这里插入图片描述
  • 测试 session 作用域

    1. 访问完 context1.jsp 文件
      在这里插入图片描述
    2. 关闭浏览器。但是要保持服务器一直开着
    3. 打开浏览器,直接访问 context2.jsp 文件(session没有数据,因为会话关闭了)
      在这里插入图片描述
  • 测试 application 作用域

    1. 访问完 context1.jsp 文件,然后关闭浏览器
      在这里插入图片描述
    2. 停止服务器。再启动服务器。
    3. 打开浏览器访问 context2.jsp 文件(都没数据,因为web工程停止了)
      在这里插入图片描述

五、out 输出流和 response.getwriter() 输出流

(一)jsp 中 out 和 response 的 writer 的区别演示

a.jsp:
在这里插入图片描述
浏览器访问a.jsp:
在这里插入图片描述
图解 out 流和 writer 流的两个缓冲区如何工作
在这里插入图片描述
当jsp页面所有代码执行完成后会做以下两个操作:

  1. 执行out.flush()操作,会把out缓冲区中的数据追加写入到response的writer缓冲区的末尾
  2. 会执行response的writer缓冲区的刷新操作,将全部数据写给客户端

由于 jsp 翻译之后,底层源代码都是使用 out 来进行输出,所以一般情况下,我们在 jsp 页面中统一使用 out 输出流来进行输出,避免打乱页面输出内容的顺序。

(二)out输出流的两种输出方式

  • out.write() 输出字符串没有问题,但是输出别的类型会得不到想要的结果
  • out.print() 输出任意数据类型都没有问题(都会转换成为字符串后调用out.write()输出)

结论:在 jsp 页面中,可以统一使用 out.print()来进行输出

六、jsp的常用标签

(一)jsp静态包含

开发中,我们可能会写很多网页,但是假设每个网页的页脚信息都是一样的,而我们需要修改页脚信息就要把每个网页都修改一遍很麻烦,于是想到将页脚信息提取出来成为单独一份jsp,再将它包含到每个网页即可。(静态包含或动态包含)

静态包含是把包含的页面内容原封不动地输出到包含的位置。
格式

<%@ include file="/被包含的 jsp 页面的路径" %> 

file 属性指定你要包含的jsp页面的路径
地址中第一个斜杠 / 表示为http://ip:port/工程路径/ 映射到代码的web目录

案例
main.jsp:
在这里插入图片描述
footer.jsp:
在这里插入图片描述

在这里插入图片描述
我们可以在main.jsp翻译出来的java源代码中看到被包含的jsp的内容:
在这里插入图片描述

静态包含的特点

  1. 静态包含不会将被包含的jsp页面单独翻译成java代码。
  2. 静态包含其实是把被包含的jsp页面的代码拷贝到包含的位置执行输出。

(二)jsp动态包含

动态包含会把包含的 jsp 页面单独翻译成 servlet 文件,然后在执行到的时候再调用翻译的 servlet 程序,并把计算的结果返回。 动态包含是在执行的时候,才会加载,所以叫动态包含。
格式

<jsp:include page="/被包含的 jsp 页面的路径"></jsp:include> 

案例

main.jsp:
在这里插入图片描述
footer.jsp:
在这里插入图片描述

在这里插入图片描述
动态包含的特点

  1. 动态包含会把包含的 jsp 页面也翻译成为 java 代码
  2. 动态包含底层代码使用如下代码去调用被包含的 jsp 页面执行输出。 JspRuntimeLibrary.include(request, response, "/footer.jsp", out, false);
  3. 动态包含,还可以传递参数

动态包含底层原理
在这里插入图片描述

动态包含和静态包含的区别

静态包含动态包含
是否生成 java 文件不生成生成
_JspService() 方法中的区别把被包含的内容原封拷贝到 _JspService() 中_JspService() 方法中调用JspRuntimeLibrary.include 方法
是否可以传递参数不能可以
编译次数1被包含的文件数 + 1
适用范围适用包含纯静态内容(CSS,HTML,JS),或没有非常耗时操作、或大量 java 代码的 jsp包含需要传递参数,或含有大量 java代码的jsp

在这里需要补充说明一点:我们在工作中,几乎都是使用静态包含。理由很简单,因为 jsp 页面虽然可以写 java 代码,做其他的功能操作,但是由于 jsp 在开发过程中被定位为专门用来展示页面的技术。也就是说,jsp 页面中,基本上只有 html,css,js,还有一些简单的 EL,表达式脚本等输出语句,所以我们都使用静态包含。

(三)jsp页面转发

格式

<jsp:forward page="/转发的路径"></jsp:forward>

相当于 request.getRequestDispatcher("/xxxx.jsp").forward(request, response); 的功能。

七、Listener监听器

(一)概述

  • 监听器就是实时监视一些事物状态的程序
  • 监听器的作用是,监听某种事物的变化,然后通过回调函数,反馈给客户(程序)去做一些相应的处理
  • Listener 监听器它是 JavaWeb 的三大组件之一。(JavaWeb 的三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器)。
  • Listener 它是 JavaEE 的规范,就是接口

(二)ServletContextListener 监听器

  • ServletContextListener 它可以监听 ServletContext 对象的创建和销毁。
  • ServletContext 对象在 web 工程启动的时候创建,在 web 工程停止的时候销毁
  • 监听到创建和销毁之后都会分别调用 ServletContextListener 监听器的两个方法反馈:
public interface ServletContextListener extends EventListener { 
	// 在 ServletContext 对象创建之后马上调用,做初始化
	public void contextInitialized(ServletContextEvent sce); 
	// 在 ServletContext 对象销毁之后调用
	public void contextDestroyed(ServletContextEvent sce); 
}

如何使用 ServletContextListener 监听器监听 ServletContext 对象?
使用步骤如下:

  1. 编写一个类去实现 ServletContextListener
  2. 实现其两个回调方法
  3. 到 web.xml 中去配置监听器

案例

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext对象被创建了");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("ServletContext对象被销毁了");
    }
}

web.xml:

<listener>
    <listener-class>com.fox.servlet.MyServletContextListener</listener-class>
</listener>

启动web工程:
在这里插入图片描述
停止web工程:
在这里插入图片描述



这篇关于JavaWeb学习总结(八)jsp详解/头部page指令/声明脚本/表达式脚本/代码脚本/九大内置对象/四大域对象/out输出流和writer输出流/静态包含和动态包含区别/Listener监听器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程