JSP

发布时间 2023-09-18 21:54:19作者: 一往而深,

什么是JSP以及他有什么用


servlet程序用于接收并处理客户端的请求,并做出响应,并将响应(一般是一个Html页面)回传给客户端

  • 演示一般情况下回传html页面
  • a.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
这是html页面数据
</body>
</html>
  • servlet程序
package com.servlet;

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.io.PrintWriter;

public class HtmlServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //通过响应的回传流回传html页面数据
            //设置响应的字符集
        resp.setContentType("text/html;charset=utf-8");
        final PrintWriter writer = resp.getWriter();
        writer.write("<!DOCTYPE html>");
        writer.write("<html lang=\"en\">");
        writer.write("<head>");
        writer.write("   <meta charset=\"UTF-8\">");
        writer.write("    <title>Title</title>");
        writer.write("</head>");
        writer.write("<body>");
        writer.write("这是html页面数据");
        writer.write("</body>");
        writer.write("</html>");

    }
}

我们需要用servlet程序给客户端回传a.html页面,可以发现我们需要将html代码的每一行都需要通过write方法写入到客户端。可以发现这样非常麻烦

而且在实际的项目中,页面的代码成千上万,这样太难写了,维护成本也太高了

  • 如果我们使用jsp文件呢

  • 创建a.jsp文件

<%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/14
  Time: 22:59
  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>

</body>
</html>

  • 这里感觉jsp的原理还不是很懂,特此标记

jsp小结

  • 1.如何创建jsp页面
    直接在web目录下面创建jsp文件即可

jsp页面的本质


  • 我们重新启动项目
  • 接下来当我们访问jsp文件的时候会发生什么呢?


  • 我们打开a_jsp类
  • 我们打开 HttpJspBase类的源代码

  • 通过观察jsp文件的java文件的底层原码,不难发现其底层也是通过输出流把html页面回传给客户端

jsp的三种语法

(a)jsp头部的page指令

  • 我们知道servlet程序可以写循环,if间接访问数据库,这些jsp都可以做到吗

  • contentType属性:表示jsp返回数据(可以是页面)类型是什么,以及其字符集
    在其翻译的servlet程序中以response.setContentType()来体现

  • pageEncoding表示当前jsp文件本身的字符集(一般默认不写)

  • import属性可以像java类一样可以导包,导类

  • 演示缓存区溢出的情况

  • 我们有下面要输出大量内容并且不刷新缓存的jap文件,然后访问

  • errorPage属性:当jsp文件出现异常,跳转导errorPage属性所保存的路径

注意:jsp文件本质上来说是servlet程序,里面的资源路径还是被服务器解析,而不是被服务器解析

  • isErrorPage属性
    当我们在jsp文件中将isErrorPage设置为ture,然后访问jsp文件后可以看到他对应的servlet中出现了异常对象

jsp常用脚本

1.声明脚本(本质上就是用来扩展生成的servlet程序)

  • jsp中注释<%-- --%>(IDEA快捷键ctrl+shift+/)
  • 敲<%!,然后回车,IDEA将会自动补全

从上面的内容我们知道jsp文件本质上是servlet程序,在被服务器解析的时候会被解析成servelt程序并生成对应的java代码和class代码。声明脚本是指用于在JSP页面中声明变量或方法的脚本。JSP声明脚本使用<%! %>标记来包含Java代码,这些代码在编译时被嵌入到Servlet类中。

2.表达式脚本(常用)


3.代码脚本

  • 1.在和html页面一样jsp页面上的标签文字内容和直接由浏览器进行解析
  • 2.由表达式脚本输出的内容,由out.wirit()发送给浏览器进行解析

问题:本来想使用System.out.println()来向控制台输出,但是一直报错。好像是jsp禁用了一些系统的功能。后面怎么解决这个问题还没有解决

jsp的三种注释

  • java注释一般是写在声明脚本或者代码脚本中

  • jsp注释可以注释掉Jps中的一切

jsp中九大内置对象

jsp 中的内置对象,是指 Tomcat 在翻译 jsp 页面成为 Servlet 源代码后,内部提供的九大对象,叫内置对象。

jsp四个域对象的演示

  • 在九大内置对象中有4个是域对象
  • 域对象:可以像map集合一样存储数据

注意:从一个jps跳转到另一个jsp是一个请求,因为Jps本质上是servlt程序

重新部署或者重启服务器,Application才会消失

  • 有四个域对象,我们到底使用哪个?
    我们的域对象会存储在内存中,域对象的今早释放可以减轻服务器的压力。 最小的使用范围就会在最短的时间内,在数据不需要使用的使用将他的内存释放掉。所以
    我们根据自己的需求从使用从小到大进行选择

  • 演示4个域对象的使用范围

  • 1.我们先创建a.jsp页面,并在存储4个域的域对象,并输出域对象

  • a.jsp

<%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/17
  Time: 16:03
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <h>这是c.jsp文件</h><br>
    <%
        //在jsp的4个域对象中存储值
    pageContext.setAttribute("key","pageContext");

    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>
</head>
<body>

</body>
</html>


因为都在这四个域的访问范围内

  • 2.在c.jsp中请求转发到d.jsp中

  • d.jsp

<%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/17
  Time: 16:07
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>


</head>
<body>
<h>d.jsp文件</h> <br>

pageContext是否有值   <%=   pageContext.getAttribute("key")%><br>
request是否有值   <%=   request.getAttribute("key")%><br>
session是否有值   <%=   session.getAttribute("key")%><br>
application是否有值   <%=   application.getAttribute("key")%><br>
</body>
</html>


我们可以发现pageContext中的值是空的了,因为已经超出了在jsp页面中的范围。因为请求转发是一次请求所以request的值还在

  • 3.重新访问一下d.jsp

    我们发现request的值不见了,因为又是一次请求,超出了请求的范围

  • 4.浏览器重新访问

    关于浏览器从新访问就已经不属于一次会话了,所以session的值就没有了

  • 4.重启服务器,项目重新部署applicton就没有了

jsp中的out输出和response.getWriter输出的区别

  • out.pirnt和out.write方法
  • 都是输出字符串
  • 发现没有任何问题
  • 当我们输出整形时
  • 发现我们的write方法出现了问题

  • 为什么write()方法输出整形会有问题?


  • 结论

JSP常用标签之静态包含


  • 静态包含的使用

  • 使用main.jsp来模拟一个网站的结构
    main.jsp

<%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/17
  Time: 18:06
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>一个网站</title>
</head>
<body>
    头部信息<br>
    主题内容<br>
    <%--页脚信息用静态包含--%>
     <%@include file="/include/footer.jsp"%>

</body>
</html>

  • footer.jsp(main.jsp静态包含的文件,提供页脚信息)
<%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/17
  Time: 18:09
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>页脚内容</title>
</head>
<body>
  页脚信息
</body>
</html>

  • 静态包含实现的底层原理

  • 静态包含特点

  • 静态包含文件他不会被服务器解析成servlet文件,而是将该文件的代码整体拷贝到main.jsp文件中,然后一起被翻译成servlet程序

常用标签之动态包含

  • 1.动态包含可以达成静态包含一样的效果
  • 换成动态包含来实现

    发现一样可以实现同样的效果
  • 但是动态包含的底层原理有什么不同吗?
  • 动态包含特点
  • 原理

对于静态包含和动态包含来说:目前绝大多数情况下只用使用静态包含就可以了

常用标签之请求转发

jsp练习题

1.九九乘法口诀表

<%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/17
  Time: 20:17
  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>
<%--输出九九乘法口诀表--%>
<%
    for (int i  = 1; i <=9 ; i++) {
        for (int j = 1; j <= i; j++) {%>
            <%=i+"*"+j+"="+(i*j)%>

       <%}%>
     <br>
    <%
        }
    %>

</body>
</html>

我们发现他的输出对的不是很齐,所以我们把他添加表格

<%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/17
  Time: 20:17
  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>
<%--输出九九乘法口诀表--%>
<table>



    <%  for (int i  = 1; i <=9 ; i++) {%>
    <tr>
       <% for (int j = 1; j <= i; j++) {%>
          <td>  <%=i+"*"+j+"="+(i*j)%></td>



       <%}%>
    </tr>

    <%   } %>

</table>
</body>
</html>

  • 这样输出就对齐了

  • 我们可以给table标签添加样式,这样效果更好

<%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/17
  Time: 20:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <style type="text/css">
        table{
            width: 650px;
        }
    </style>
</head>
<body>
<%--输出九九乘法口诀表--%>
<h1 align="center">九九乘法口诀表</h1>

<table align="center">



    <%  for (int i  = 1; i <=9 ; i++) {%>
    <tr>
       <% for (int j = 1; j <= i; j++) {%>
          <td>  <%=i+"*"+j+"="+(i*j)%></td>



       <%}%>
    </tr>

    <%   } %>

</table>
</body>
</html>

练习2:遍历输出10个学生信息到表格中

  • 先准备一个Student类
package com.pojo;

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

    /**
     * 获取
     * @return id
     */
    public Integer getId() {
        return id;
    }

    /**
     * 设置
     * @param id
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public Integer getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(Integer age) {
        this.age = age;
    }

    /**
     * 获取
     * @return phone
     */
    public String getPhone() {
        return phone;
    }

    /**
     * 设置
     * @param phone
     */
    public void setPhone(String phone) {
        this.phone = phone;
    }

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

  • jsp文件
<%@ page import="com.pojo.Student" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/18
  Time: 12:22
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
  <style>
 table{
   border: 1px red solid;
   width: 600px;
   border-collapse: collapse;
 }
 td,th{
   border: 1px red solid;
 }


  </style>
</head>
<body>
<%--练习2:遍历输出10个学生信息到表格中--%>
<%
//创建10个学生对象并实例化
  List<Student> list = new ArrayList<Student>();
    int t=5;
  for (int i = 0; i <10; i++) {
     t +=i;
     list.add(new Student(i++,"刘涛"+t,19+t,"1234"+t));
  }

%>
<table>
  <tr>
    <td>id</td>
    <td>姓名</td>
    <td>年龄</td>
    <td>电话</td>

  </tr>
<% for (Student student : list) {%>
  <tr>
  <td> <%=student.getId()%></td>
  <td> <%= student.getName()%></td>
  <td> <%=student.getAge()%></td>
  <td> <%=student.getPhone()%></td>

  </tr>

<%  }%>
</table>

</body>
</html>

  • 运行结果

请求转发的使用说明

**问题概述:客户端搜索特定数据,服务器处理并响应

  • 前面的将对象输出到浏览器中是给这个使用请求转发做铺垫
  • servlnt程序
package com.servlet;

import com.pojo.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;

//用于处理查询学生信息的servlet程序
public class SearchStudentServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //1.接收客户端的请求参数
        //2.调用service的方法进行请求处理
        //3.获得返回的学生对象
        //前面的2步之前演示过,这里直接将数据给出来
        List<Student> list = new ArrayList<Student>();
        int t=5;
        for (int i = 0; i <10; i++) {
            t +=i;
            list.add(new Student(i++,"刘涛"+t,19+t,"1234"+t));
        }


        //4.将他们保存到request域中
        req.setAttribute("list",list);
        //5.进行请求转发
        req.getRequestDispatcher("/test/showStudent.jsp").forward(req,resp);
    }
}

  • jsp程序
<%@ page import="com.pojo.Student" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/18
  Time: 12:22
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
  <style>
 table{
   border: 1px red solid;
   width: 600px;
   border-collapse: collapse;
 }
 td,th{
   border: 1px red solid;
 }


  </style>
</head>
<body>
<%
  //获取request域中的对象
 List<Student> list =(List) request.getAttribute("list");
%>


<table>
  <tr>
    <td>id</td>
    <td>姓名</td>
    <td>年龄</td>
    <td>电话</td>

  </tr>
<% for (Student student : list) {%>
  <tr>
  <td> <%=student.getId()%></td>
  <td> <%= student.getName()%></td>
  <td> <%=student.getAge()%></td>
  <td> <%=student.getPhone()%></td>

  </tr>

<%  }%>
</table>

</body>
</html>

什么是Listener监听器

ServletContextListener监听器

  • ServletContextListener监听器可以用于监听ServletContext对象的创建和销毁。

  • ServletContext对象在web工程被创建的时候被创建在服务器关闭的时候被销毁
    监听器的细节看官方文档

  • ServletContextListener监听器使用的演示

  • 监听器类

package com.listen;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
//用于监听ServletContext对象的创建和销毁
public class MyListener implements ServletContextListener {
    //1、编写一个类去实现 ServletContextListener
    //2、实现其两个回调方法
    //3、到 web.xml 中去配置监听
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext对象被创建了");
    }

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

}

  • 监听器配置

我们在启动服务器后将会调用MyLister里面的初始化方法,在关闭服务器器将会调用MyListener中的销毁方法