JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”

JSP 的本质原理解析:"编写的时候是JSP,心里想解读的是 java 源码"

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图

@


每博一文案

活明白的人,一生只做好了这两件事:
每个瞬间都充满了选择和承担,就算面前是一座独木桥,也必须选择是前进后退,亦或是留在原地此时此刻你所经历的一切。
这是过往无数个选择后的结果,哪些小的选择汇聚在了一起,最终成了我们今天的时光。
其实,活明白的人一生只做好了两件事看,一是选择,二是承担。常听人争论选择和努力哪个更重要。
其实,努力并不是选择的对比面,而是拥有选择的基本条件。不努力的人往往连选择的资格都没有,努力是为了,
更好的选择。正如马伯庸说:所谓的选择只是努力所赋予人的一种资格。
所有的一夜成名,刹那的焰火,实际是过往今年默默努力埋下的伏笔,因此这里说的选择不是投机取巧的小聪明。
而是积淀后的深思熟虑。常言道:选择不对,努力白费。
李兰娟院士在为了汕头大学的毕业学生送上给予时,表示:不管是在生活还是事业上,有很多外部变化和环境因素是我们
所无法选择的。我们可以选择的是在每一个人生路口要做出怎样的选择,以及如何勇敢的前行。
我们所有的人都在共享一段岁月,却在不同的选择中分道扬镳,因为人生最重要的除了努力还有选择。
当你被生活的疲惫裹挟着,被环境的艰难牵制着,这时你要么被生活牵着鼻子走,要么接收痛苦与打击,抗住一场场暴风雪,主动迎击一地鸡毛的琐碎,你要做的不是抱怨生活的不公,而是迈出步子,夺下生活的主导权,做出选择了。
一种选择就是一种代价,不同的选择造就了不同的人生,人打从生下来就面临着很多种未知的可能。
未来都是一张白纸,任由自己去上色作画。有些人完成地很好,也有人画得一团糟,人生的一万种可能好的,不好的
都是有认真选择好。
每一支画笔,在每次选择时都要坚持原则,便是对自己的人生负责。

                                            —————— 《一禅心灵庙语》

1. JSP 概述

JSP(全称JavaServer Pages),sun公司主导的一种动态网页技术,JSP在服务端运行,可以响应客户端的请求,根据请求内容动态的生成HTML、XML或其他格式文档的Web网页然后返回请求者。在JSP页面可以嵌入Java代码,JSP文件在运行时会被其编译器转换成更原始的Servlet代码,然后再由Java编译器来编译成能快速执行的二进制机器码。

2.特点:

  1. 能以模板化的方式简单、高效地添加动态网页内容。
  2. 可利用JavaBean和标签库技术复用常用的功能代码。
  3. 有良好的工具支持。
  4. 继承了Java语言的相对易用性。
  5. 继承了Java的跨平台优势,实现“一次编写,处处运行”。
  6. 页面中的动(控制变动内容的部分)/静(内容不需变动的部分)区域以分散但又有序的形式组合在一起,方便开发维护。
  7. 可与其它企业级Java技术相互配合。JSP可以只专门负责页面中的数据呈现,实现分层开发。

3.JSP页面组成:

在 HTML 页面文件中加入 Java 程序段和 JSP 标签,即可构成一个 JSP 页文件,JSP 页面由 5 种元素组合而成。
普通的 HTML 标记符。

  1. JSP 标签,如指令标签、动作标签。
  2. 变量和方法的声明。
  3. Java 程序段。
  4. Java 表达式。

2. 第一个 JSP 程序

我的第一个JSP程序:

这里给一个小的建议,大家在阅读如下,文章时,可以带着一个这样的问题:JSP 是什么 ? 去阅读文章,有助于后面的内容上的阅读理解。

WEB-INF目录之外创建一个 index.jsp文件,然后这个文件中没有任何内容。注意 了:我们对于这个jsp 文件当中并没有编写任何的内容,一个字符,一个标点都可以,就是一个空白的。如下显示的:

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图1

将上面的项目部署之后,启动服务器,打开浏览器,访问以下地址 http://127.0.0.1:8080/servlet14/index.jsp 我们部署的项目的路径:具体显示如下。

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图2

重点: 实际上我们访问的以上的这个:index.jsp,底层执行的是:index_jsp.class 这个java程序。我们可以在我们本地电脑上访问到该生成是 index_jsp.class,index_jsp.java的文件,该生成的对应的.class,.java文件所在的路径是在我们启动 Tomcat 服务器当中提示的,一个 CATALINA_BASE路径下的 C:UsershuoAppDataLocalJetBrainsIntelliJIdea2022.1tomcat4b6bbfbb-d520-498b-b8f2-090a7ad68f62

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图3

这个index.jsp会被tomcat翻译生成index_jsp.java文件,然后tomcat服务器又会将 index_jsp.java编译生成index_jsp.class文件。访问index.jsp,实际上执行的是index_jsp.class中的方法。

如下是我们访问 index.jsp 在我本地电脑上生成的 CATALINA_BASE的 路径下的,index_jsp.java,index_jsp.class 的文件。 C:UsershuoAppDataLocalJetBrainsIntelliJIdea2022.1tomcat4b6bbfbb-d520-498b-b8f2-090a7ad68f62workCatalinalocalhostservlet14orgapachejsp

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图4

如下是我们的一个 index.jsp(空内容) 被翻译为 index_jsp.java 文件的内容如下:

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/10.0.12
 * Generated at: 2023-04-21 03:20:48 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 jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.jsp.*;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

  private static final jakarta.servlet.jsp.JspFactory _jspxFactory =
          jakarta.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map _jspx_dependants;

  private static final java.util.Set _jspx_imports_packages;

  private static final java.util.Set _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet();
    _jspx_imports_packages.add("jakarta.servlet");
    _jspx_imports_packages.add("jakarta.servlet.http");
    _jspx_imports_packages.add("jakarta.servlet.jsp");
    _jspx_imports_classes = null;
  }

  private volatile jakarta.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set getClassImports() {
    return _jspx_imports_classes;
  }

  public jakarta.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 jakarta.servlet.http.HttpServletRequest request, final jakarta.servlet.http.HttpServletResponse response)
      throws java.io.IOException, jakarta.servlet.ServletException {

    if (!jakarta.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, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
        return;
      }
    }

    final jakarta.servlet.jsp.PageContext pageContext;
    jakarta.servlet.http.HttpSession session = null;
    final jakarta.servlet.ServletContext application;
    final jakarta.servlet.ServletConfig config;
    jakarta.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    jakarta.servlet.jsp.JspWriter _jspx_out = null;
    jakarta.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html");
      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(' ');
      out.write(' ');
    } catch (java.lang.Throwable t) {
      if (!(t instanceof jakarta.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);
    }
  }
}

3. JSP 的本质就是 Servlet

从上述我们编写的第一jsp 程序,index.jsp 空内容的,index.jsp访问的时候,会自动翻译生成index_jsp.java,会自动编译生成index_jsp.class,那么index_jsp 这就是一个类。

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图5

从图中我们可以看到,该index.jsp 翻译的 index_jsp.java 类是继承了 extends org.apache.jasper.runtime.HttpJspBase 类的,我们查阅其 Tomcat 10 的 HttpJspBase 源码如下:

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图6

如下是 HttpJspBase 的源码内容

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jasper.runtime;

import java.io.IOException;

import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.jsp.HttpJspPage;

import org.apache.jasper.Constants;
import org.apache.jasper.compiler.Localizer;

/**
 * This is the super class of all JSP-generated servlets.
 *
 * @author Anil K. Vijendran
 */
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {

    private static final long serialVersionUID = 1L;

    protected HttpJspBase() {
    }

    @Override
    public final void init(ServletConfig config)
        throws ServletException
    {
        super.init(config);
        jspInit();
        _jspInit();
    }

    @Override
    public String getServletInfo() {
        return Localizer.getMessage("jsp.engine.info", Constants.SPEC_VERSION);
    }

    @Override
    public final void destroy() {
        jspDestroy();
        _jspDestroy();
    }

    /**
     * Entry point into service.
     */
    @Override
    public final void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        _jspService(request, response);
    }

    @Override
    public void jspInit() {
    }

    public void _jspInit() {
    }

    @Override
    public void jspDestroy() {
    }

    protected void _jspDestroy() {
    }

    @Override
    public abstract void _jspService(HttpServletRequest request,
                                     HttpServletResponse response)
        throws ServletException, IOException;
}

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图7

而 HttpServlet 是 extends 了 GenericServlet 抽象类,而 GenericServlet 抽象类是 实现了 Servlet 接口的。

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图8

所以:一个index_jsp类就是一个Servlet类。总结就是:一个 index.jsp 文件会被翻译为一个 index_jsp.java 类,而 该 翻译的 index_jsp.java类是 继承 了 org.apache.jasper.runtime.HttpJspBase 类的,而 org.apache.jasper.runtime.HttpJspBase 类 是继承了 HttpServlet 类的。这下逻辑就清晰了,JSP 就是 Servlet

  • JSP 的生命周期和Servlet的生命周期完全相同。完全就是一个东西。没有任何区别。
  • JSP和servlet一样,都是单例的。(假单例,真单例是:其类的构造器是 private 私有化的,而Servlte 的构造器不是 private 私有化的,是公开的。所以为假单例),想要了解更多的,大家可以移步至: 🔜🔜🔜 javaEE Web(Tomcat)深度理解 和 Servlet的本质_ChinaRainbowSea的博客-CSDN博客

现在我们可以比较清晰的回答 JSP是什么了 ?

  • JSP是java程序。(JSP本质还是一个Servlet)
  • JSP是:JavaServer Pages的缩写。(基于Java语言实现的服务器端的页面。)
  • Servlet是JavaEE的13个子规范之一,那么JSP也是JavaEE的13个子规范之一。
  • JSP是一套规范。所有的web容器/web服务器都是遵循这套规范的,都是按照这套规范进行的“翻译”
  • 每一个web容器/web服务器都会内置一个JSP翻译引擎。这里所谓的翻译指的是: 将我们访问的 jsp 文件翻译成 对应的以.java 后缀结尾的Java文件,再将 该 java 文件编译生成 .class 文件。

问题:JSP第一次访问的时候是比较慢的,为什么?

同问: 为什么大部分的运维人员在给客户演示项目的时候,为什么提前先把所有的jsp文件先访问一遍。

因为我们第一次比较麻烦,需要进行一个项目的资源的加载。

  • 第一次比较麻烦的地方:
    • 要把jsp文件翻译生成java源文件
    • java源文件要编译生成class字节码文件
    • 然后通过class去创建servlet对象
    • 然后调用servlet对象的init方法
    • 最后调用servlet对象的service方法。
  • 第二次就比较快了,为什么?
    • 因为第二次直接调用单例servlet对象的service方法即可。

注意点:

实际上我们对于 JSP 进行错误调试的时候,还是要直接打开JSP文件对应翻译生成的 java文件,检查其中 java代码。

开发JSP的最高境界: 眼前编写的是JSP代码,但是我们心里,脑袋里面当中呈现的是 java代码。

JSP既然本质上是一个Servlet,那么JSP和Servlet到底有什么区别呢?

职责不同:

  • Servlet的职责是什么:收集数据。(Servlet的强项是后端的逻辑处理,业务处理,然后链接数据库,获取/收集数据。)
  • JSP的职责是什么:展示数据。(JSP的强项是做 前端数据的展示)

4. JSP 的基础语法

上面我们学习,了解到了 JSP 的本质原理,下面我们就来学习一下有关 JSP的基础语法吧

4.1 在 JSP 文件中直接编写文字

在 jsp 文件中直接编写文字,都会自动被翻译到哪里?

如下我们实验一下,我们在上一个 index.jsp 文件当中,直接编写一个 “Hello Wrold” 。当我们浏览器端访问该 index.jsp 文件时,浏览器端有是显示一个则样的效果,而其本质中 “Hello Wrold” 又是被翻译到了,成了什么,翻译到了哪里。

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图9

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图10

如下我们查看对应 index.jsp 翻译的 index_jsp.java 文件的内容如下:

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/10.0.12
 * Generated at: 2023-04-21 06:10:10 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 jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.jsp.*;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

  private static final jakarta.servlet.jsp.JspFactory _jspxFactory =
          jakarta.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map _jspx_dependants;

  private static final java.util.Set _jspx_imports_packages;

  private static final java.util.Set _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet();
    _jspx_imports_packages.add("jakarta.servlet");
    _jspx_imports_packages.add("jakarta.servlet.http");
    _jspx_imports_packages.add("jakarta.servlet.jsp");
    _jspx_imports_classes = null;
  }

  private volatile jakarta.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set getClassImports() {
    return _jspx_imports_classes;
  }

  public jakarta.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 jakarta.servlet.http.HttpServletRequest request, final jakarta.servlet.http.HttpServletResponse response)
      throws java.io.IOException, jakarta.servlet.ServletException {

    if (!jakarta.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, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
        return;
      }
    }

    final jakarta.servlet.jsp.PageContext pageContext;
    jakarta.servlet.http.HttpSession session = null;
    final jakarta.servlet.ServletContext application;
    final jakarta.servlet.ServletConfig config;
    jakarta.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    jakarta.servlet.jsp.JspWriter _jspx_out = null;
    jakarta.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html");
      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("Hello World");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof jakarta.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 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图11

翻译到 servlet类的 service() 方法的 out.write("翻译到这里") ,直接翻译到双引号里,被java程序当做普通字符串打印输出到浏览器。

补充一点: 解决浏览器端显示的乱码问题 ?

JSP的page指令(这个指令后面再详细说,这里先解决一下中文乱码问题),解决响应时的中文乱码问题:

  • 通过page指令来设置响应的内容类型,在内容类型的最后面添加:charset=UTF-8
    • ,表示响应的内容类型是text/html,采用的字符集UTF-8
    • 表示到对应的 包信息

在JSP中编写的HTML CSS JS代码,这些代码对于JSP来说只是一个普通的字符串。但是JSP把这个普通的字符串一旦输出到浏览器,浏览器就会对HTML CSS JS进行解释执行。展现一个效果。举例如下:






    my first JSP page

    
        function sayHello() {
            window.alert("你好 JSP")
        }
    


    

My first JSP page

fajsi ffasdfda fasd afjsfi9 Sytstem.out.println("hello JSP");

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图12

访问 index.jsp 显示的效果如下:

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图13

对应翻译的java 的内容如下:注意:都是被翻译到了 service()方法体当中去了

 public void _jspService(final jakarta.servlet.http.HttpServletRequest request, final jakarta.servlet.http.HttpServletResponse response)
      throws java.io.IOException, jakarta.servlet.ServletException {

    if (!jakarta.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, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
        return;
      }
    }

    final jakarta.servlet.jsp.PageContext pageContext;
    jakarta.servlet.http.HttpSession session = null;
    final jakarta.servlet.ServletContext application;
    final jakarta.servlet.ServletConfig config;
    jakarta.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    jakarta.servlet.jsp.JspWriter _jspx_out = null;
    jakarta.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("rn");
      out.write("rn");
      out.write("rn");
      out.write("rn");
      out.write("rn");
      out.write("    my first JSP pagern");
      out.write("rn");
      out.write("    rn");
      out.write("        function sayHello() {rn");
      out.write("            window.alert("你好 JSP")rn");
      out.write("        }rn");
      out.write("    rn");
      out.write("rn");
      out.write("rn");
      out.write("    

My first JSP page

rn"); out.write(" rn"); out.write("rn"); out.write(" fajsi ffasdfdarn"); out.write(" fasdrn"); out.write(" afjsfi9rn"); out.write("rn"); out.write(" Sytstem.out.println("hello JSP");rn"); out.write("rn"); out.write(""); } catch (java.lang.Throwable t) { if (!(t instanceof jakarta.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); } } }

4.2 在JSP中编写Java程序 与

4.2.1


在这个符号当中编写的被视为java程序,被翻译到Servlet类的 service方法体内部。举例如下:JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图14









访问 浏览器前端访问:demo01.jsp 效果

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图15

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图16

因为我们只在 demo01.jsp 文件当中编写了,Java代码,并没有编写其他的,而且我们的Java代码编写的仅仅只是一个简单的输出到控制台上的一个输出语句而已了。所以前端浏览器是没有任何的显示内容的。

如下是 对应我们访问 demo01.jsp 文件翻译为 demo01_jsp.java 文件的源码信息如下:

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/10.0.12
 * Generated at: 2023-04-21 06:43:13 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 jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.jsp.*;

public final class demo01_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

  private static final jakarta.servlet.jsp.JspFactory _jspxFactory =
          jakarta.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map _jspx_dependants;

  private static final java.util.Set _jspx_imports_packages;

  private static final java.util.Set _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet();
    _jspx_imports_packages.add("jakarta.servlet");
    _jspx_imports_packages.add("jakarta.servlet.http");
    _jspx_imports_packages.add("jakarta.servlet.jsp");
    _jspx_imports_classes = null;
  }

  private volatile jakarta.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set getClassImports() {
    return _jspx_imports_classes;
  }

  public jakarta.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 jakarta.servlet.http.HttpServletRequest request, final jakarta.servlet.http.HttpServletResponse response)
      throws java.io.IOException, jakarta.servlet.ServletException {

    if (!jakarta.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, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
        return;
      }
    }

    final jakarta.servlet.jsp.PageContext pageContext;
    jakarta.servlet.http.HttpSession session = null;
    final jakarta.servlet.ServletContext application;
    final jakarta.servlet.ServletConfig config;
    jakarta.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    jakarta.servlet.jsp.JspWriter _jspx_out = null;
    jakarta.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(' ');
      out.write(' ');
      out.write(' ');
      out.write('r');
      out.write('n');

    System.out.println("Hello World");

      out.write("rn");
      out.write("rn");
      out.write("rn");

    System.out.println("Hello JSP");

      out.write("rn");
      out.write("rn");

    System.out.println("你好世界");

      out.write('r');
      out.write('n');
    } catch (java.lang.Throwable t) {
      if (!(t instanceof jakarta.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 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图17

的使用的注意事项:

  • 这里你要细心点,你要思考,在这个符号里面写java代码的时候,你要时时刻刻的记住你正在“sevice() 方法体”当中写代码,方法体中可以写什么,不可以写什么,你心里是否明白呢?

方法体当中不可以,定义静态代码块,以及代码块,不可以再定义方法了,不可以被定义成员变量 (被权限修饰符修饰的变量。)

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图18

如果在 jsp 当中所编写的 Java程序存在错误,浏览器端是会抱 500 错误的。如下所示:以 5 开头的一般都是服务器端的错误,这时候,我们一般是通过查看其中翻译的 java 程序当中翻译的错误了。

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图19
JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图20

  • 在service方法当中编写的代码是有顺序的,方法体当中的代码要遵循自上而下的顺序依次逐行执行。
  • service方法当中不能写静态代码块,不能写方法,不能定义成员变量。。。。。。
  • 在同一个JSP当中 这个符号可以出现多个。

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图21

4.2.2


  • 在这个符号当中编写的java程序会自动翻译到service方法之外。简单的说就是: Servlet 类当中,service() 方法外,那不就是 成员变量,方法,代码块了。

举例如下:

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图22

启动部署,访问运行如下

JSP 的本质原理解析:”编写的时候是JSP,心里想解读的是 java 源码”插图23

  • 这个语法很少用,为什么?并且也不建议使用,因为在service方法外面写静态变量和实例变量,都会存在线程安全问题,因为JSP就是servlet,servlet是单例的,多线程并发的环境下的,这个静态变量和实例变量一旦有修改操作,必然会存在线程安全问题。

4.3 通过JSP当中的 向浏览器前端输入 Java变量

怎么向浏览器上输出一个java变量。

错误方式: 直接在 jsp 当中编写对应变量名,因为我们的在 JSP文件当中直接编写的文字的内容是被翻译到了 service() 方法体当中去了被 out.write("

文章来源于互联网:JSP 的本质原理解析:"编写的时候是JSP,心里想解读的是 java 源码"

THE END
分享
二维码