文章目录

  • Java server pages(jsp)
  • jsp简介
  • jsp语法
  • jsp头部的page指令
  • jsp中常用的脚本
  • 声明脚本(**很少使用**)
  • 表达式脚本
  • 代码脚本
  • jsp中的三种注解
  • html注释
  • java注释
  • jsp注释
  • jsp对象
  • 九个内置对象
  • 四个域对象
  • 输出对象
  • jsp中常用标签
  • jsp静态包含
  • jsp动态包含
  • jsp标签-转发
  • jsp练习题
  • 练习一:在jsp页面中输出九九乘法表
  • 练习二:jsp输出一个表格,里面有10个学生信息


Java server pages(jsp)

jsp简介

什么是jsp,它有什么作用?

答:jsp全程是java server pages,java的服务器页面,主要作用是替代Servlet程序会穿html页面的数据。这是因为Servlet程序回传html页面数据是一件非常繁琐的事情,开发成本和维护成本都太高。

疑问:为什么要用servlet回传html页面?而不是选择跳转某个html页面?

一个原因是html是静态页面,并不是回传数据

如何访问jsp?

答:jsp页面和html页面一样,都是存放在web目录下,访问也和访问html页面一样

尚硅谷java项目笔记 尚硅谷javaweb笔记_java

访问地址是http://ip:port/工程路径/a.html以及http://ip:port/工程路径/a.jsp

jsp页面都本质是什么?

答:jsp页面本质上是一个servlet程序,

当第一次访问jsp页面的时候,Tomcat服务器会帮我们把jsp页面翻译称为一个java源文件,并且对它进行编译成为.class字节码文件,可以在idea中的tomcat执行窗口查看org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:对应路径找到该web工程下jsp被tomcat封装的jsp文件。

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/9.0.41
 * Generated at: 2021-02-14 02:43:30 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;

public final class a_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {
  // ....               
  }

进一步HttpJspBase是继承了HttpServlet对象,如下

尚硅谷java项目笔记 尚硅谷javaweb笔记_jsp_02

由此可知,jsp翻译出来的java类,间接地继承了 HttpServlet类,也就是说,一个jspBase类实际上就是一个Servlet对象

小结:通过翻译的java源码我们可知:jsp就是Servlet程序。也可以发现,jsp被封装称为java类后,底层也是通过输出流把html页面回传给客户端。

jsp语法

jsp头部的page指令

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

<%@ page contentType="text/html;charset=UTF-8"
         language="java"
         pageEncoding="UTF-8"
         import="java.util.*" autoFlush="true"
         errorPage="/error500.jsp"
         buffer="8kb"
         isErrorPage="true" %>
  • language属性:表示jsp翻译后是什么语言文件,暂时只支持java
  • contentType属性:表示jsp返回的数据类型是什么,也是源码中response.setContentType()参数值
  • pageEncoding属性:表示当前jsp页面本身的字符集(一般不作修改).
  • import属性:和java源代码一样,用于导包,导类。

以下两个属性是给out输出流使用

  • autoFlush属性:设置当out输出流缓冲区满了之后,是否自动刷新缓冲,默认是true(一般不作修改
  • buffer属性:设置out缓冲区的大小,默认是8kb(经测试最优,一般不作修改)。

  • errorPage属性:设施当jsp页面运行时出错,自动跳转去的错误页面路径
<!-- errorPage 表示错误后自动跳转去的路径,这个路径一般是以斜杠大头,表示请求地址为http:ip:port/工程路径/-->
  • isErrorPage属性:设置当前页面是否是错误信息页面,默认是false,如果是true可以获取一场信息
  • session属性:设置访问当前jsp页面,是否会创建HttpSession对象,默认true(一般用默认不修改
  • extends属性:设置jsp翻译出来的java类默认继承谁

jsp中常用的脚本

声明脚本(很少使用)

声明脚本的格式如下:

<%! 声明java代码 %>

作用:可以给jsp翻译出来的java类定义属性和方法,甚至是静态代码块,内部类等。

<%--练习:
--%>

<%--1、声明类属性--%>
<%!
    private Integer id;
    private String name;
    private static Map<String, Object> map;//这个时候上面就会自动导包
%>
<%--2、声明static静态代码块--%>
<%!
    static {
        map = new HashMap<String, Object>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");
    }
%>
<%--3、声明类方法--%>
<%!
    public int abc() {
        return 12;
    }
%>
<%--4、声明内部类--%>
<%!
    public static class A {
        private Integer id = 12;
        private String abc = "abc";
    }
%>
表达式脚本

表达式脚本的声明格式如下:

<%=表达式%>

表达式脚本的作用是:在jsp页面上输出数据

<%--练习:
1.输出整型
2.输出浮点型
3.输出字符串
4.输出对象    --%>
<%=12 %> <br>

<%=12.12 %> <br>

<%="我是字符串" %> <br>

<%=map%> <br>

<%=request.getParameter("username")%>

效果如下图所示:

尚硅谷java项目笔记 尚硅谷javaweb笔记_尚硅谷java项目笔记_03

上述内容在源码中其实就是调用了write方法

尚硅谷java项目笔记 尚硅谷javaweb笔记_java_04

表达式脚本的特点

  1. 所有的表达式脚本都会被翻译到_jspService()方法中

尚硅谷java项目笔记 尚硅谷javaweb笔记_html_05

  1. 表达式脚本都会被翻译成为out.print()输出到页面上
  2. 由于表达式脚本翻译的内容都在_jspService()方法中,所以_jspService()中的对象都可以直接使用,如requestresponse
  3. 表达式脚本中的表达式不能以分号结束
代码脚本

代码脚本的格式如下

<%
	java语句
%>

代码脚本的作用:在jsp页面中,编写我们自己需要的功能(写的是java语句

代码脚本的特点是:

  1. 代码脚本翻译之后都在_jspService()方法中
  2. 代码脚本由于翻译到_jspService()方法中,所以该方法内的所有对象都可以使用
  3. 代码脚本可以由多个代码脚本块组合完成一个完整的java语句
<%--1.代码脚本----if 语句--%>
   <%
       int i = 13;
       if (i == 12) {
   %>
   <h1>国哥好帅</h1>		<!-- 这里是输出在页面上 -->
   <%
   } else {
   	System.out.println("我更帅") 	// 这里是输出在java控制台
   }
   %>

翻译得到的java源码如下:

int i = 13;
if (i == 12) {
  out.write("\n");
  out.write("<h1>国哥好帅</h1>\n");
} else {
  out.write("\n");
  out.write("<h1>国哥又骗人了!</h1>\n");
}
  1. 代码脚本还可以和表达式脚本一起组合使用,在jsp页面上输出数据
<%--2.代码脚本----for 循环语句--%>
   <table border="1" cellspacing="0">
       <%
           for (int j = 0; j < 10; j++) {
       %>
       <tr>
           <td>第 <%=j + 1%>行</td>
       </tr>
       <%
           }
       %>
   </table>

效果图

尚硅谷java项目笔记 尚硅谷javaweb笔记_尚硅谷java项目笔记_06

jsp中的三种注解

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

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

java注释
// 单行java主是
/* 多行java注释 */

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

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

jsp注释可以注掉jsp页面中所有代码,是jsp中真正的注释

jsp对象

九个内置对象

jsp中单内置对象:是指Tomcat在翻译jsp页面成为Servlet源代码后,内部提供的九大对象,叫做内置对象。见如下截图

尚硅谷java项目笔记 尚硅谷javaweb笔记_java_07

四个域对象

在上述的九个内置对象中,有四个域对象分别是

  • pageContexPageContextImpl类——在当前jsp页面范围内有效
  • requestHttpServletRequest类——一起请求内有效
  • sessionHttpSession类——一个会话(打开浏览器访问浏览,直到关闭浏览器)范围内有效
  • applicationServletContext类——整个web工程范围内都有效(只要web工程不停止,数据都在

域对象是可以像Map一样存取数据的对象。四个域对象功能一样,不同的是他们对数据的存取范围。

<%
    // 往四个域中都分别保存了数据
    pageContext.setAttribute("key", "pageContext");		// 当前页面有效,换一个jsp页面就没有
    request.setAttribute("key", "request");		// 当次请求有效,如果是请求重定向则有效,如果重新请求泽没有
    session.setAttribute("key", "session");	//只要此次浏览器没关闭,就有效,
    application.setAttribute("key", "application");	//重新部署项目后无效。
%>
pageContext域是否有值:<%=pageContext.getAttribute("key")%> <br>
request域是否有值:<%=request.getAttribute("key")%> <br>
session域是否有值:<%=session.getAttribute("key")%> <br>
application域是否有值:<%=application.getAttribute("key")%> <br>

说明:虽然四个域对象都可以存取数据,在使用他们上是有优先顺序的——从小到大的顺序

pageContex. ---->>>>. request ----->>>> session ---->>>> application

输出对象

jsp中有两种输出的方法,一种是out输出,以及response.getWriter输出

  • response中表示响应,我们常用于设置返回给客户端的内容(输出)
  • out也是给客户端的输出

上述两个输出之间存在着转移关系,具体转移顺序见下图

尚硅谷java项目笔记 尚硅谷javaweb笔记_html_08

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

  • out.write():输出字符串没有问题,但如果是其他数据类型,因为会用到字符数组类型作为缓冲,就会出现将其他数据强制转换为字符串数据类型,造成原始数据发生更改,从而使得在页面中的显示有问题,在java中对应的源码如下(以输出整型为例);
public void write(int c) throws IOException {
    if (this.writer != null) {
      this.writer.write(c);
    } else {
      this.ensureOpen();
      if (this.nextChar >= this.bufferSize) {
        this.reAllocBuff(1);
      }
  
      this.cb[this.nextChar++] = (char)c;		// 将int型转换成为了字符数组
    }
  
  }
  • out.println()输出任意数据都没有问题(都换转换成字符还后调用write输出)以后就用这种

jsp中常用标签

演示该部分的代码如下图所示

尚硅谷java项目笔记 尚硅谷javaweb笔记_jsp页面_09

jsp静态包含

静态包含出现的需求背景:对于一些重复出现在许多页面中的内容模块(例如许多大网站下方的加入我们…),我们不希望在修改时对每一个包含了该模块的页面进行修改,而是考虑将其单独写在一个页面中,如果有哪个页面需要,直接将其静态包含过去即可

语法为:

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

下方是main.jsp中的主要代码

<body>
头部信息 <br>
主体内容 <br>
<%--
    <%@ include file=""%> 就是静态包含
        file 属性指定你要包含的jsp页面的路径
        地址中第一个斜杠 / 表示为http://ip:port/工程路径/  映射到代码的web目录

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

下方为foot.jsp中的代码

<body>
友情连接 <br>
脚页信息 <br>
</body>
</html>

效果如下图所示:

尚硅谷java项目笔记 尚硅谷javaweb笔记_jsp_10

关于静态包含的一些说明:

  1. 静态包含不会翻译被包含的jsp页面(文件中只有main的代码)
  2. 静态包含其实是把被包含的jsp页面的代码拷贝到包含的位置执行输出

尚硅谷java项目笔记 尚硅谷javaweb笔记_尚硅谷java项目笔记_11

jsp动态包含

和静态包含相比,动态包含的调用语法如下

<jsp:include page="/include/foot.jsp">
    <jsp:param name="username" value="bbj"/>		<!-- 可选参数 -->
    <jsp:param name="password" value="root"/>   <!-- 可选参数 -->
</jsp:include>

动态包含的特点:

  1. 动态包含会把jsp页面也翻译成为java代码

尚硅谷java项目笔记 尚硅谷javaweb笔记_java_12

  1. 动态包含底层代码使用如下代码去调用被包含的jsp页面去执行输出:
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "/include/foot.jsp", out, false);

此时,当main.jsp把参数传递过去后,后者的requestresponse以及out都是前者对应的对象,因此两者共享相关的信息,于是后者就可以将内容写进前者的out缓冲区中,具体底层原理示意图翦下图。

  1. 动态包含还可以传递参数,此时上述调用方法如下
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "/include/foot.jsp" + "?" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("username", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("bbj", request.getCharacterEncoding()) + "&" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("password", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("root", request.getCharacterEncoding()), out, false);

动态包含的底层原理

尚硅谷java项目笔记 尚硅谷javaweb笔记_jsp_13

⭐️ 在实际开发中,我们更多的是使用静态包含

jsp标签-转发

<%--
    <jsp:forward page=""></jsp:forward> 是请求转发标签,它的功能就是请求转发
        page 属性设置请求转发的路径
--%>
<jsp:forward page="/scope2.jsp"></jsp:forward>

jsp练习题

练习一:在jsp页面中输出九九乘法表

<html>
<head>
    <title>Title</title>
</head>
<body>
<table>
    <%-- 练习一:在jsp页面中输出九九乘法口诀表 --%>
    <h1 align="center">九九乘法口诀表</h1>
    <table align="center">
        <% for (int i = 1; i <= 9; i++) { %>
        <tr>
            <% for (int j = 1; j <= i ; j++) { %>
            <td><%=j + "x" + i + "=" + (i*j)%></td>
            <% } %>
        </tr>
        <% } %>
    </table>
</body>
</body>
</html>

效果图:

尚硅谷java项目笔记 尚硅谷javaweb笔记_html_14

练习二:jsp输出一个表格,里面有10个学生信息

<%@ page import="java.util.List" %>
<%@ page import="pojo.Student" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <style>
        table{
            border: 1px blue solid;
            width: 600px;
            border-collapse: collapse;
        }
        td,th{
            border: 1px blue solid;
        }
    </style>
</head>
<body>
<%--练习二:jsp输出一个表格,里面有10个学生信息。--%>
<%
    List<Student> studentList = new ArrayList<Student>();
    for (int i = 0; i <; i++) {
        int t =i+1;
        studentList.add(new Student(t,"name"+t,18+t,"phone"+t));
    }
%>
<table>
    <tr>
        <td>编号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>电话</td>
        <td>操作</td>
    </tr>
    <% for (Student student: studentList) { %>
    <tr>
        <td><%=student.getId()%></td>
        <td><%=student.getName()%></td>
        <td><%=student.getAge()%></td>
        <td><%=student.getPhone()%></td>
        <td>删除、修改</td>
    </tr>
    <% } %>
</table>

</body>
</html>

效果图

尚硅谷java项目笔记 尚硅谷javaweb笔记_java_15

在实际的需求中,servlet与jsp页面的协同合作如下图所示:

尚硅谷java项目笔记 尚硅谷javaweb笔记_html_16

由于servlet不适合发送数据,于是servlet会把查询得到的数据请求转发给jsp页面,然后jsp页面再将其呈现在用户面前

上述过程用代码实现如下

public class SearchStudentServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

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

        // 获取请求的参数
        // 发sql语句查询学生的信息
        // 使用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域中
        // 请求转发到showStudent.jsp页面
        request.setAttribute("stuList", studentList);		
        request.getRequestDispatcher("/test/showStudent.jsp").forward(request, response);

    }
}

对应的jsp页面中也作如下修改(获取来自于request域中的对应的数据第4行

<body>
<%--练习二:jsp输出一个表格,里面有10个学生信息。--%>
<%
    List<Student> studentList = (List<Student>) request.getAttribute("stuList");
%>
<table>
    <tr>
        <td>编号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>电话</td>
        <td>操作</td>
    </tr>
    <% for (Student student: studentList) { %>
    <tr>
        <td><%=student.getId()%></td>
        <td><%=student.getName()%></td>
        <td><%=student.getAge()%></td>
        <td><%=student.getPhone()%></td>
        <td>删除、修改</td>
    </tr>
    <% } %>
</table>

</body>

然后请求访问SearchStudentServlet,即可得到表格结果**(不能直接访问对应的jsp)**

尚硅谷java项目笔记 尚硅谷javaweb笔记_尚硅谷java项目笔记_17