本文被 系统学习JavaWeb 收录点击订阅专栏


文章目录

  • 1 初探JSP
    • 1.1 何为JSP?
    • 1.2 JSP的本质
  • 2 JSP的page指令
  • 3 JSP中的常用脚本
    • 3.1 声明脚本
    • 3.2 表达式脚本(常用)
    • 3.3 代码脚本
    • 3.4 关于注释的说明
    • 3.5 练习:在jsp页面中输出乘法表
  • 4 JSP的内置对象
    • 4.1 jsp的九大对象概览
    • 4.2 四大域对象
    • 4.3 out输出与response.getWriter输出的区别
  • 5 JSP中的常用标签
    • 5.1 静态包含
    • 5.2 动态包含
    • 5.3 请求转发
  • 写在最后

1 初探JSP

1.1 何为JSP?

JSP(java server pages), 即Java的服务器界面。其主要作用是 代替 Servlet 程序回传 html 页面数据。
因为 Servlet 程序回传 html 页面数据很繁琐,维护成本比较高。

如果通过Servlet程序回传html数据,演示代码如下:

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;/*** @author 兴趣使然黄小黄* @version 1.0* 演示传统Servlet回传html数据的繁琐*/
public class PrintHtml extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//通过响应的输出流回传html页面数据resp.setContentType("text/html;charset=UTF-8");PrintWriter writer = resp.getWriter();writer.write("<!DOCTYPE html>\r\n");writer.write("<html lang=\"en\">\r\n");writer.write("<head>\r\n");writer.write("    <meta charset=\"UTF-8\">\r\n");writer.write("    <title>Title</title>\r\n");writer.write("</head>\r\n");writer.write("<body>\r\n");writer.write("这是html页面数据\r\n");writer.write("</body>\r\n");writer.write("</html>\r\n");writer.write("\r\n");}
}

而实际开发时,html的代码多达千行万行,可见,传统Servlet程序回传html的方式相当繁琐!

而JSP的主要作用就是代替Servlet程序回传html页面的数据:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
这是html页面数据
</body>
</html>

如何访问JSP页面?
a.jsp访问地址:http://ip:port/工程路径/a.jsp

1.2 JSP的本质

jsp页面的本质是一个Servlet程序。

当第一次访问jsp页面时,Tomcat服务器会帮我们把jsp页面翻译成为一个java源文件,并将它翻译成为.class字节码文件。

源代码中,jsp页面所翻译出来的类继承了HttpJSPBase类,该类直接继承了HttpServlet类。即,jsp翻译出来的java类,间接继承了HttpServlet类,是一个Servlet程序。


2 JSP的page指令

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

属性 说明
language属性 表示jsp翻译后是什么语言文件,目前只支持java
contentType属性 表示jsp返回的数据类型。也是源码中response.setContentType()的参数值
pageEncoding属性 表示当前jsp页面文件本身的字符集
import属性 用于导包,导类
autoFlush属性 设置当out输出流缓冲区满了之后,是否自动刷新缓冲区,默认值是true
buffer属性 设置out缓冲区的大小,默认8kb
errorPage属性 设置当jsp页面运行出错时,自动跳转的错误页面路径
isErrorPage属性 设置当前jsp页面是否有错误信息,默认是false,如果是true可以获取异常信息
session属性 设置访问当前jsp页面,是否会创建HttpSession对象,默认是true
extends属性 设置jsp翻译出来的java类默认继承的父类

3 JSP中的常用脚本

3.1 声明脚本

声明脚本的语法格式:

<%! 声明java代码 %>

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

演示代码如下:

<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %><%--Created by IntelliJ IDEA.User: 26510Date: 2022/10/17Time: 8:52To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<%--1.声明类属性--%>
<%!private String id;private String name;private int age;private static Map<String, Object> map;
%><%--2.声明static静态代码块--%>
<%!static {map = new HashMap<String, Object>();map.put("key1", "value1");map.put("key2", "value2");}
%><%--3.声明类方法--%>
<%!public int sum(int a, int b){return a+b;}
%><%--4.生成内部类--%>
<%!public static class A{private String telephone;}
%></body>
</html>

3.2 表达式脚本(常用)

表达式脚本的语法格式:

<%= 表达式 %>

可以在jsp页面上输出数据。

演示代码如下:

<%--1.输出整型--%>
<%=12  %><br><%--2.输出浮点型--%>
<%=12.12 %><br><%--3.输出字符串--%>
<%="我是黄小黄" %><br><%--4.输出对象--%>
<%=map %><br>

表达式脚本的特点:

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

3.3 代码脚本

代码脚本的语法格式:

<% java语句 %>

可以在jsp页面中,编写自己需要的功能。

演示代码如下:

<%--1.代码脚本:if语句--%>
<%int i = 10;if (i == 10){System.out.println("i = 10");}else {System.out.println("i != 10");}
%><%--2.代码脚本:for语句--%>
<%for (int j = 0; j < 10; j++) {System.out.println(j);}
%><%--3.翻译后java文件中_jspService方法内的代码都可以写--%>
<%String username = request.getParameter("username");System.out.println("username = " + username);
%>

代码脚本的特点:

  1. 代码脚本翻译后在_jspService方法中
  2. 所有在_jspService方法中的现有对象都可以直接使用
  3. 可以由多个代码脚本组合成一个完整的java语句
  4. 代码脚本可以与表达式脚本一起组合使用,在jsp页面上输出数据
<%for (int j = 0; j < 10; j++) {%>
<%=j %>
<% }
%>

3.4 关于注释的说明

在jsp中分为三种注释:

  • html注释
<!--html注释-->

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

  • java注释
//单行注释
/*多行注释*/

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

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

jsp注释可以注释掉jsp中所有代码。

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

test.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>乘法表</title>
</head>
<body>
<table><%for (int i = 1; i <= 9; i++) {%><tr><%for (int j = 1; j <= i; j++) {%><td><%=j + "x" + i + "=" + (j*i)%></td><%}%></tr><%}%>
</table>
</body>
</html>


4 JSP的内置对象

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

4.1 jsp的九大对象概览

对象 说明
request 请求对象
response 响应对象
pageContext jsp的上下文对象
session 会话对象
application ServletContext对象
config ServletConfig对象
out jsp的输出流对象
page 指向当前的jsp对象
exception 异常对象

其中exception异常对象需要在page指令的参数isErrorPage="true"时才存在。

4.2 四大域对象

域对象是可以像Map一样存取数据的对象,四个域对象的功能一样,区别是对数据的存取范围。

下表列举了四个域对象和作用范围

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

在进行代码演示前,需要导入Tomcat中lib目录下的jsp与Servlet的jar包!

演示代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<h1>scope.jsp页面</h1>
<%//在四个域中都分别保存了数据pageContext.setAttribute("key", "pageContext");request.setAttribute("key", "request");session.setAttribute("key", "session");application.setAttribute("key", "application");
%>
pageContext域是否有值:<%=pageContext.getAttribute("key")%>
request域是否有值:<%=pageContext.getAttribute("key")%>
session域是否有值:<%=pageContext.getAttribute("key")%>
application域是否有值:<%=pageContext.getAttribute("key")%>
</body>
</html>

可以尝试多创建一个jsp页面,关闭浏览器,再次部署web项目打开服务器的方式一步步扩大范围,最终结果与表中所述一致!

四个域对象虽然都可以存取数据,但是 具有自己的优先顺序,优先级从小到大如下:

  1. pageContext
  2. request
  3. session
  4. application

4.3 out输出与response.getWriter输出的区别

response表示响应,用于设置返回给客户端的内容(输出);
out 也是给用户输出使用的。

演示案例:
虽然out语句在response之前,但是结果确是response在前,out在后。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<%out.write("out输出1 <br/>");out.write("out输出2 <br/>");response.getWriter().write("response输出1 <br/>");response.getWriter().write("response输出2 <br/>");
%>
</body>
</html>


过程图解如下:

当jsp页面中的所有代码执行完成后会做如下的操作:

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

由于jsp翻译的servlet程序中源码都是out进行输出的,为了避免打乱页面的内容顺序,所以在jsp中一般统一使用out输出。

关于out.write()与out.print()

方法 说明
out.write() 输出字符串
out.print() 输出任意数据类型(转换成字符串后调用了write输出

5 JSP中的常用标签

5.1 静态包含

静态包含一般用于加载进页面显示后就再也不变的东西, 比如页眉、背景、标题等等。静态包含不会检查所含文件的变化,把文件包含进来后,被包含文件的修改变化是不会影响已被包含进来的内容的。

静态包含发生在编译阶段。比如:a.jsp中使用了语句 <%@ include file=“b.jsp”%>,把b.jsp包含了进来,那么在编译a.jsp文件时, 会直接把b.jsp文件的内容全部内嵌到a.jsp文件中包含b的语句的位置。 然后运行a,显示a页面。也就是说,静态include是先把被包含文件的内容全部复制内嵌到包含文件中,再进行编译运行的。也 正是因为要把b包含进a,所以b中的变量等不能与a重复,否则会报错。

演示案例:将footer.jsp内嵌在main.jsp中

footer.jsp

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

main.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
头部信息<br>
主体内容<br>
<%@include file="/include/footer.jsp"%>
</body>
</html>


静态包含小结:

  • 静态包含不会翻译被包含的jsp页面;
  • 静态包含实际上是把被包含的jsp页面的代码拷贝到包含的位置执行输出。

5.2 动态包含

动态包含用于加载经常变化的、要求显示最新版本内容的东西。 比如提交时间戳:用户打开博客编辑页面时,有一个时间加载进来了。用户编写完博客,点击提交时,就应该使用/显示提交瞬间的时间而不是打开编辑页面时的那个时间。所以这里要用的就是最新时间。由上面我们知道,静态include是先包含进来,再编译,运行并传回浏览器显示的,所以不能满足我们要求某些部分使用最新内容的要求。那么,我们就要用到动态include。

动态include与静态include的最大不同在于:包含文件与被包含文件都是先编译执行,再包含。二者的编译阶段是相互独立的,只有在包含文件的include语句处把被包含文件的执行结果包含进来。 换言之,包含文件先编译,执行。执行到了include语句的时候才触发被包含文件的编译、执行,并实时把结果包含进来。从而达到获取最新的被包含内容的目的。同样使用a.jsp包含b.jsp的例子:加入a.jsp中动态include了b.jsp。现在,a先编译成servlet类文件,然后运行,当运行到包含b的语句处,引起b的编译,运行,并把b的运行servlet运行结果包含进a。最后a顺利运行完毕,把a的servlet类运行结果输出到浏览器显示。

案例代码:
footer.jsp

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

main.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
头部信息<br>
主体内容<br>
<jsp:include page="/include/footer.jsp"></jsp:include>
</body>
</html>

运行结果页面与上个案例一致(但是底层原理和对象有区别)

原理示意图:

动态包含小结:

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

5.3 请求转发

之前学过的请求转发:

request.getRequestDispatcher("/include/footer.jsp").forward(request, response);

另一种形式

<jsp:forward page="/include/footer.jsp"></jsp:forward>

写在最后

 本文部分内容参考:尚硅谷JavaWeb课程。好了,本文内容到这里就告一段落了,欢迎大家订阅专栏,加入JavaWeb学习!点击订阅

 如果你有任何问题,欢迎私信,感谢您的支持!

【JavaWeb】JSP技术详解相关推荐

  1. 读 孙卫琴《Tomcat与Javaweb开发技术详解》

    最初读这本书是因为做比赛要用到服务器端,但是网络上的知识太多了,感觉自己丝毫没有头绪,于是在知乎上找到了一本推荐的书,如上. 现在对于网络编程的那些细节还没有去了解,甚至说是环境还没有按照书上配好,但 ...

  2. 【H.264/AVC视频编解码技术详解】十九:熵编码算法(5)——H.264的CABAC(上):语法元素的二值化方法...

    <H.264/AVC视频编解码技术详解>视频教程已经在"CSDN学院"上线,视频中详述了H.264的背景.标准协议和实现,并通过一个实战工程的形式对H.264的标准进行 ...

  3. Linux磁盘阵列技术详解(二)--raid 1创建

    我在Linux磁盘阵列技术详解(一)里已经详细介绍了几种RAID磁盘阵列方式,原理以及创建raid 0 的详细步骤.那么这篇文档就着重讲解如何创建raid 1的技术: 步骤如下: ① 分区 同样我们还 ...

  4. 《Hadoop技术详解》一导读

    前 言 Hadoop技术详解 本书采用的约定 本书采用以下排版约定. 斜体 用于表明新的术语.URL.电子邮件地址.文件名和文件扩展名. 等宽字体 用于程序清单,正文段落中有关的程序元素,如变量及函数 ...

  5. 科普:5G网络关键技术详解

    不久前,中国华为公司主推的Polar Code(极化码)方案,成为5G控制信道eMBB场景编码方案.消息一出,在网络上就炸开了锅,甚至有媒体用"华为碾压高通,拿下5G时代"来形容这 ...

  6. zookeeper 分布式过程协同技术详解.pdf_阿里大牛耗时18个月整理这份ZooKeeper分布式详解文档...

    前言 摩尔定律揭示了集成电路每18个月计算性能就会增加一倍.随着信息的飞速膨胀,很多应用都无法依赖单个服务器的性能升级来处理如此庞大的数据量,分布式系统和应用越来越受到人们的青睐.分布式系统和应用不仅 ...

  7. Qtum量子链研究院:Plasma技术详解(下篇)

    Plasma的设计模型有两个主要的分支:Plasma MVP(Minimal Viable Plasma,最小可行的Plasma)和Plasma Cash.Plasma MVP的目标是为最基本的可用的 ...

  8. Python数据科学-技术详解与商业实践视频教程

    Python数据科学-技术详解与商业实践(八大案例) 网盘地址:https://pan.baidu.com/s/13QrR_5Er6LgWCWzSb7qOrQ 提取码:s7vw 备用地址(腾讯微云): ...

  9. 视频直播技术详解(8)直播云 SDK 性能测试模型

    <视频直播技术详解>系列之八:直播云 SDK 性能测试模型 牛小七2016年10月12日发布在 视频直播技术详解 七牛云于 6 月底发布了一个针对视频直播的实时流网络 LiveNet 和完 ...

最新文章

  1. 集成学习VotingClassifier、HistGradientBoostingClassifier、Stacking、Blending
  2. 理解离散傅立叶变换(一)
  3. mysql数据库木马查杀_Linux系统木马后门查杀方法详解
  4. 使用Windbg找出死锁,解决生产环境中运行的软件不响应请求的问题
  5. 信息系统项目管理师算职称吗
  6. 技术面试官的一些建议
  7. ImportError: cannot import name ‘moving_averages‘
  8. django 1.8 官方文档翻译:13-1-3 密码管理
  9. 题目管理后台系统_中后台产品最爱的后台:CMS(社区)管理系统搭建
  10. linux 解决Linux上解压jdk报错gzip: stdin: not in gzip format
  11. dht11传感器c语言程序,树莓派 DHT11 温湿度传感器读取 C 语言版
  12. 保温杯市场前景分析及行业研究报告
  13. php trying to get,php 做微信认证登陆 返回错误 Trying to get property of non-object
  14. vcftools手册重要参数集合
  15. 《IDSSIM:基于改进的疾病语义相似度方法的lncRNA功能相似度计算模型》论文梳理
  16. 饼图加引导线_【如何在饼形图中添加引导线(Excel)】excle里面一条竖状线
  17. Linux TC 带宽管理队列规则
  18. 如何用一张影像动图来对比成都市2019年和2020年油菜花分布状态?
  19. 转:最好的300款免费软件
  20. Interpretability Beyond Feature Attribution: Quantitative Testing with Concept Activation Vectors

热门文章

  1. 电脑PC端利用android-sdk使用微信、360云盘等应用
  2. [C#]Unicode与汉字互转
  3. 北京君正案例:超能面板PRO采用4英寸IPS超清多彩屏,值不值得买?
  4. mysql 空闲链接超时时间_解决mysql 中共8小时空闲后连接超时的有关问题
  5. 大数据管理神器:Ambari自定义stack和服务二次开发详细教程
  6. iOS实现绘画文字动画
  7. VS编译运行时出现exe文件无法打开的原因
  8. 矩形连乘问题c语言,矩阵连乘问题
  9. UmiJS4非Umi Max开启Dva及其他插件的方法
  10. 英特尔核显驱动hd630_AMD与英特尔彻底失去合作关系?中止Kaby Lake-G更新支持