jsp 的本质是 servlet,当用户请求 servlet 的时候,servlet 利用输出流动态输出 HTML 内容。

由于包括了大量的 HTML 标签、大量的静态文本等,导致 servlet 开发效率极为低下,因为所有的前端内容都必须全部耦合在 java 代码中。

jsp 的出现弥补了这种不足,jsp 通过在标准的 HTML 页面中嵌入 java 代码,静态部分无需 java 控制,但是需要 java 控制的部分,我们可以通过 jsp 的一些标签语法直接书写 java 代码。

从上面的介绍可以看出,JSP 页面内容由如下两部分组成。

1、静态部分:标准的 HTML 的内容

2、动态部分:受 java 程序控制的内容

如:

<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
// 项目目录路径
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%> <html>
<head>
<base href=" <%=basePath%>">
<title>jsp 基本原理</title>
</head>
<body>
</body>
</html>

  

上面的 "<%" 和 "%>" 括起来的部分就是动态部分,而下面的是我们正常的 html,而且我们可以在 html 中嵌入 jsp 的内容,如上面的 "<base href=" <%=basePath%>">"。

上面的代码我们可以直接放到 web 应用内运行,这是因为,jsp 在运行之前会把 jsp 页面编译成对应的 servlet 文件,我们运行的还是 servlet,每一个 jsp 页面就是一个 servlet 实例。

我们可以看看其中的一个由 jsp 生成的 java 文件:

/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/9.0.5
* Generated at: 2018-03-18 00:21: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.*; public final class a_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports { private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; private static final java.util.Set<java.lang.String> _jspx_imports_packages; private static final java.util.Set<java.lang.String> _jspx_imports_classes; static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
} private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
} public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
} public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
} public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
} public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
} public void _jspInit() {
} public void _jspDestroy() {
} 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, "JSPs only permit GET, POST or HEAD. Jasper also permits OPTIONS");
return;
}
} final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null; try {
response.setContentType("text/html; charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out; out.write('\n'); String path = request.getContextPath();
// 项目目录路径
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; out.write("\n");
out.write("\n");
out.write("<html>\n");
out.write("<head>\n");
out.write(" <base href=\" ");
out.print(basePath);
out.write("\">\n");
out.write(" <title>徒手创建一个 jsp 项目</title>\n");
out.write(" <link href=\"assets/prism/prism.css\" rel=\"stylesheet\" />\n");
out.write(" <link href=\"assets/css/style.css\" rel=\"stylesheet\" />\n");
out.write("</head>\n");
out.write("<body>\n");
out.write(" <h1>徒手创建一个 jsp 项目</h1>\n");
out.write("\n");
out.write("<div class=\"content\">\n");
out.write(" <div class=\"step\">\n");
out.write(" <p>1. 在任意目录新建一个名为 \"jsp\" 的项目, 这个目录会是最终的应用文件夹</p>\n");
out.write(" <p>2. 在上一步新建的文件夹内新建一个 WEB-INF 文件夹(区分大小写)</p>\n");
out.write(" <p>3. 进入 tomcat 的 webapp 目录, 进入里面任意一个应用, 复制里面的 web.xml 到上一步新建的 WEB-INF 中</p>\n");
out.write(" <p>4. 修改复制后的 web.xml, 将文件修改成只有一个根元素的 XML 文件. 修改后的 web.xml 如下:\n");
out.write(" <pre>\n");
out.write(" <code class=\"language-xml\">\n");
out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
out.write("<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\"\n");
out.write(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
out.write(" xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee\n");
out.write(" http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd\"\n");
out.write(" version=\"4.0\"\n");
out.write(" metadata-complete=\"true\">\n");
out.write("</web-app>\n");
out.write(" </code>\n");
out.write(" </pre>\n");
out.write(" </p>\n");
out.write(" <p>5. 在第二步新建的 WEB-INF 路径下, 新建两个文件夹 classes 和 lib, 这两个文件夹的作用完全相同, 都是用于保存 Web 应用所需要的 java 文件, \n");
out.write(" 区别是 classes 保存单个 *.class 文件, 而 lib 保存打包后的 jar 文件.\n");
out.write(" </p>\n");
out.write(" <p>6. 经过以上步骤, 已经建立了一个空的 Web 应用. 将该应用文件夹复制到 tomcat 的 webapps 路径下, 就可以通过浏览器来访问这些页面了.\n");
out.write(" 不难发现 Web 应用应该有如下文件结构:\n");
out.write(" <pre>\n");
out.write(" <code class=\"language-xml\">\n");
out.write("<jsp> -- 这是 web 应用的名称, 可以改变\n");
out.write("|-WEB-INF\n");
out.write("| |-classes\n");
out.write("| |-lib\n");
out.write("| |-web.xml\n");
out.write("|-<a.jsp> -- 此处可放任意多个 jsp 页面\n");
out.write("\n");
out.write(" </code>\n");
out.write(" </pre>\n");
out.write(" </p>\n");
out.write(" <p>7. 我们在应用根目录下新建一个 a.jsp 文件, 页面内容如下:\n");
out.write(" <pre>\n");
out.write(" <code class=\"language-xml\">\n");
out.write("<%@ page contentType=\"text/html; charset=UTF-8\" language=\"java\" %>\n");
out.write("<html>\n");
out.write("<head>\n");
out.write(" <title>徒手创建一个 jsp 项目</title>\n");
out.write("</head>\n");
out.write("<body>\n");
out.write(" <h1>徒手创建一个 jsp 项目</h1>\n");
out.write("</body>\n");
out.write("</html>\n");
out.write(" </code>\n");
out.write(" </pre>\n");
out.write(" </p>\n");
out.write("\n");
out.write(" <p>8. 我们访问 http://localhost:8080/jsp/a.jsp, 就可以看到上面的内容了</p>\n");
out.write(" </div>\n");
out.write("</div>\n");
out.write("\n");
out.write("<script src=\"assets/prism/prism.js\"></script>\n");
out.write("</body>\n");
out.write("</html>");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}

  

也就是说,jsp 文件里面的全部 html 代码都被 java 用 out.write 包裹起来了。

而我们写在 "<% ... %>" 中的代码还是原样出现在该 java 文件中。

而我们写的 jsp 表达式,成了下面的样子:

out.write("    <base href=\" ");
out.print(basePath);
out.write("\">\n");

  

我们还能发现上面有三个 _jsp 前缀的方法,去掉前缀就是:

init():初始化 JSP/Servlet 的方法

destroy(): 销毁 JSP/ Servlet 的方法

service():对用户请求生成响应的方法

下图显示了 JSP 的工作原理:

根据上面的图,可以得到如下 3 个结论:

1、JSP 文件必须在 JSP 服务器运行

2、JSP 文件必须生成 Servlet 才能执行

3、每个 JSP 页面的第一个访问者速度很慢,因为必须等待 JSP 编译成 Servlet。

jsp 基本原理的更多相关文章

  1. JSP基本原理

    JSP的基本原理: jsp的本质是servlet.jsp通过在标准的HTML页面中嵌入java代码,其静态的部分无需Java程序控制,只有那些需要从数据库读取或需要 动态生成的的页面内容,才使用Jav ...

  2. JSP学习(1)---JSP基本原理

    一.JSP的本质 其本质是Servlet,web应用中的每个jsp页面都会由servlet容器生成对应的servlet. 在tomcat中,jsp生成的servlet在work文件夹下: 原jsp文件 ...

  3. 请求与响应编码及jsp基本原理

    1.请求转发和请求包含 (1)请求转发: this.getServletContext().getRequestDispatcher("").forward(request,res ...

  4. jsp笔记1(基本原理与语法)

    web.xml文件配置管理的范围: 1.配置jsp 2.配置和管理Servlet 3.配置和管理Listener 4.配置和管理Filter 5.配置标签库 6.配置jsp属性 7.配置和管理JAAS ...

  5. JSP基本知识

    JSP基本原理: JSP本质是Servlet(一个特殊的Java类),当用户向指定Servlet发送请求时,Servlet利用输出流动态生成HTML页面.JSP通过在标准的HTML页面中嵌入Java代 ...

  6. 01.JSP基础语法

        本章主要讲解Java Web与JSP的入门内容,适合有JSP或Java Web基础的读者学习. 1.Web应用与web.xml文件 (1)Java Web应用程序的结构     Java We ...

  7. 深入理解JSP

    JSP(Java server page)是Java EE规范最基本成员,他是Java Web开发的重点知识,尽管我们一直在用.但其原理知之甚少.今天重点研究一些JSP核心内容以及其工作原理. JSP ...

  8. JavaWeb基础—JSP

    一.什么是JSP JSP 全称是 Java Server Pages,是一种开发动态web资源的技术 在原HTML上添加JAVA脚本(灵魂工程师,为页面添加灵魂),可以说 jsp = html + j ...

  9. JavaWeb开发学习(一)-JavaWeb开发概述

    1.Web相关概念 Web程序也就是一般所说的网站,由服务器.客户端浏览器以及网络组成.Web程序的好处是使用简单,不需要安装.学习,有一台电脑.一根网线就可以使用.Web程序不是一般意义上的网站.网 ...

随机推荐

  1. 解决xampp启动mysql失败

    进入到注册表内 命令:regedit 进入到路径:计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MySQL 修改路径为:" ...

  2. Selenium WebDriver 下 plugin container for firefox has stopped working

    用selenium 的webdriver 和 firefox 浏览器做自动化测试,经常会出现 plugin container for firefox has stopped working 如下图所 ...

  3. 曾经我是一个只会excel的数据分析师,直到我遇到了……

    我是一个数据分析师. 准确来说我是一个当年只会excel数据透视表,就天不怕地不怕地来当数据分析师的人.当年的某一天,我的老板Q我: 小刘啊,我小姨子给了我一个全国市委书记的名单,你帮我看看,有什么规 ...

  4. Spring学习(四)—— java动态代理(JDK和cglib)

    JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他 的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托 ...

  5. lintcode-415-有效回文串

    415-有效回文串 给定一个字符串,判断其是否为一个回文串.只包含字母和数字,忽略大小写. 注意事项 你是否考虑过,字符串有可能是空字符串?这是面试过程中,面试官常常会问的问题. 在这个题目中,我们将 ...

  6. DB2 9.5 数据库分区管理及应用实践

    DB2 数据库分区是 DB2 企业版 DPF(Data Partitioning Feature)选件提供的,它主要用来为大规模数据处理.高并发数据访问提供支持.DB2 数据库分区采用 Share-n ...

  7. 操作系统作业一——仿CMD

    实验一.CMD实验 2014商软2  卓宇靖  4238 一.        实验目的 (1)掌握命令解释程序的原理: (2)掌握简单的DOS调用方法: (3)掌握C语言编程初步. 二.        ...

  8. QtCharts模块在QtWideget中图表绘制(非QML)

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QtCharts模块在QtWideget中图表绘制(非QML)     本文地址:http:/ ...

  9. Vue于React特性对比(二)

    一,关于响应式数据更新方式的实现 1)只有在data里面定义的数据才会有响应式更新 vue依赖的defineProperty的数据劫持加上依赖数据,实现数据的响应式更新.可以称之为依赖式的响应.因为依 ...

  10. puppeteer设置代理并检查代理是否设置成功

    1. 设置代理: 这一步超级简单,但我掉到了坑里并扑腾了小一天的时间,那就是:箭头指向处一定一定不要加空格!!! 2. 检查代理是否设置成功: 在打开的浏览器里,打开百度,输入ip,如果查出来的结果跟 ...