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

Posted TheMagicalRainbowSea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 文件当中并没有编写任何的内容,一个字符,一个标点都可以,就是一个空白的。如下显示的:

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

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

这个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:\\Users\\huo\\AppData\\Local\\JetBrains\\IntelliJIdea2022.1\\tomcat\\4b6bbfbb-d520-498b-b8f2-090a7ad68f62\\work\\Catalina\\localhost\\servlet14\\org\\apache\\jsp

如下是我们的一个 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<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("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<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 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 这就是一个类。

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

如下是 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;


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

所以:一个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 私有化的,是公开的。所以为假单例),想要了解更多的,大家可以移步至:

    java web002——jsp(本质也是servlet)

    一、JSP简介

    1。JSP用于简化Servlet编写。JSP是一种实现普通静态HTML动态内容混合编码的技术
    2。JSP只需对网页中的要动态产生的内容采用Java代码来编写,而对固定不变的静态内容采用普通静态HTML页面的方式编写。
    3。JSP设计的目的在于简化表示层的表示。
    4。JSP页面的访问路径与普通HTML页面的访问路径形式完全一样。
    5。JSP页面是由HTML语句和嵌套在其中的Java代码组成的一个普通文本文件,JSP 页面的文件扩展名必须为.jsp。
    6。在JSP页面中编写的Java代码需要嵌套在<%和%>中,嵌套在<%和%>之间的Java代码被称之为脚本片段(Scriptlets),没有嵌套在<%和%>之间的内容被称之为JSP的模版元素
    7。JSP中的Java代码可以使用out.println语句将其他Java程序代码产生的结果字符串输出给客户端,也可以使用System.out.println语句将它们打印到命令行窗口。
    8。在JSP页面中也可以使用一种称之为JSP表达式的元素,只需将要输出的变量或表达式直接封装在<%= 和 %>之中,就可以向客户端输出这个变量或表达式的运算结果。在JSP表达式中嵌套的变量或表达式后面不能有分号

    二、JSP的运行原理

    1。WEB容器(Servlet引擎)接收到以.jsp为扩展名的URL的访问请求时,它将把该访问请求交给JSP引擎去处理。
    2。每个JSP 页面在第一次被访问时,JSP引擎将它翻译成一个Servlet源程序,接着再把这个Servlet源程序编译成Servlet的class类文件,然后再由WEB容器(Servlet引擎)像调用普通Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序。

    三、jsp登录例子




    四、JSP基本语法

    4.1、JSP模版元素

    。JSP页面中的静态HTML内容称之为JSP模版元素,在静态的HTML内容之中可以嵌套JSP的其他各种元素来产生动态内容。
    。JSP模版元素定义了网页的基本骨架,即定义了页面的结构和外观。

    4.2、JSP表达式

    JSP表达式中的变量或表达式后面不能有分号(;),

    <%= 表达式 %><%--格式--%>
    Time:<%=new Date() %><br><%--变量或表达式后面不能有分号(;)--%>
    Time:<%out.println(new Date()); %><br><%--非变量或表达式后面有分号(;)--%>
    

    4.3、JSP脚本片断

    。JSP脚本片断(scriptlet)是指嵌套在<% 和 %>之中的一条或多条Java程序代码。
    。在JSP脚本片断中,可以定义变量、执行基本的程序运算、调用其他Java类、访问数据库、访问文件系统等普通Java程序所能实现的功能。
    。在JSP脚本片断可以直接使用JSP提供的隐式对象来完成WEB应用程序特有的功能。
    。JSP脚本片断中的Java代码将被原封不动地搬移进由JSP页面所翻译成的Servlet的_jspService方法中,所以,JSP脚本片断之中只能是符合Java语法要求的程序代码。

    <%
    	int x = 3;
    %>
    <p>这是一个HTML段落</p>
    <%
    	out.println(x);
    %>
    

    4.4、JSP注释

    <%-- 该部分注释在网页中不会被显示--%> 
    

    4.5、JSP声明

    <%!
    static { System.out.println("loading Servlet!"); }
    private int globalVar = 0;
    public void jspInit() {
    	System.out.println("initializing jsp!");
    }
    %>
    <%!
    public void jspDestroy() {
    	System.out.println("destroying jsp!");
    }
    %>
    <%
    	int localVar = 0;
    %>
    globalVar:<%= ++globalVar %><br> 
    localVar:<%= ++localVar %>
    

    五、jsp隐含对象

    JSP根据Servlet API 规范提供了某些内置对象,开发者不用事先声明就可以使用标准的变量来访问这些对象。
    JSP供提供九种内置对象:
    request
    reponse
    out
    session
    application
    config
    pagecontext
    page
    exception
    其中,request、session、application、pagecontext为四个域对象,(有setAttribute和getAttribute方法)

    5.1、request(最常用)

    “request” 对象代表的是来自客户端的请求,例如我们在FORM表单中填写的信息等,是最常用的对象。关于它的方法使用较多的是getParameter、getParameterNames和getParameterValues,通过调用这几个方法来获取请求对象中所包含的参数的值。域对象之一,包含相关属性操作方法。

    5.2、response

    “response” 对象代表的是对客户端的响应,也就是说可以通过“response”对象来组织发送到客户端的数据。但是由于组织方式比较底层,所以不建议普通读者使用,需要向客户端发送文字时直接使用“out” 对象即可。

    5.3、pageContext

    。“pageContext” 对象直译时可以称作“页面上下文”对象,代表的是当前页面运行的一些属性。一般情况下“pageContext” 对象用到得也不是很多,只有在项目所面临的情况比较复杂的情况下,才会利用到页面属性来辅助处理。
    域对象之一,包含相关属性操作方法。

    5.4、session

    。“session” 对象代表服务器与客户端所建立的会话,当需要在不同的JSP页面中保留客户信息的情况下使用,比如在线购物、客户轨迹跟踪等。“session” 对象建立在cookie的基础上,所以使用时应注意判断一下客户端是否打开了cookie。
    域对象之一,包含相关属性操作方法。

    概要
    HTTP是无状态(stateless)协议;
    Web Server 对每一个客户端请求都没有历史记忆;
    Session用来保存客户端状态信息;
    由Web Server 写入;
    存于客户端;
    客户端的每次访问都把上次的session记录传递给Web Server;
    Web Server读取客户端提交的session来获取客户端的状态信息;

    5.5、application

    。“application” 对象负责提供应用程序在服务器中运行时的一些全局信息。
    域对象之一,包含相关属性操作方法。
    。是ServletContext类型的对象,ServletContext application=null;

    5.6、out

    “out” 对象代表了向客户端发送数据的对象,与“response” 对象不同,通过“out” 对象发送的内容将是浏览器需要显示的内容,是文本一级的,可以通过“out” 对象直接向客户端写一个由程序动态生成HTML文件。
    常用的方法除了pirnt和println之外,还包括clear、clearBuffer、flush、getBufferSize和getRemaining,这是因为“out” 对象内部包含了一个缓冲区,所以需要一些对缓冲区进行操作的方法。

    5.7、config

    “config” 对象提供一些配置信息,常用的方法有getInitParameter和getInitParameterNames,以获得Servlet初始化时的参数。

    5.8、page

    “page” 对象代表了正在运行的由JSP文件产生的类对象,不建议一般读者使用

    5.9、exception

    “exception” 对象则代表了JSP文件运行时所产生的例外对象,此对象不能在一般JSP文件中直接使用,而只能在使用了“<%@ page isErrorPage="true "%>”的JSP文件中使用

    5.10、四个域对象的访问各个域范围中的属性

    1、在application > session > request > pageContext对象中都可以调用setAttribute方法和getAttribute方法来设置和检索各自域范围内的属性。域对象使用setAttribute(String name,Object value)将对象的值放到域中,通过getAttribute(String name)获取对应的值。

    2、application的作用范围最大,是整个web运用(ServletContext application,ServletContext 是一个容器,一个项目只有一个容器);
    存储在application对象中的属性可以被同一个WEB应用程序中的所有Servlet和JSP页面访问。

    3、session的作用范围是同一个会话
    存储在session对象中的属性可以被属于同一个会话的所有Servlet和JSP页面访问。

    4、存储在request对象中的属性可以被属于同一个请求的所有Servlet和JSP页面访问。

    5、存储在pageContext对象中的属性仅可以被当前JSP页面的当前响应过程中调用的各个组件访问,例如,正在响应当前请求的JSP页面和它调用的各个自定义标签类。 PageContext类中还提供了对各个域范围的属性进行统一管理的方法,以简化对各个域范围内的属性的访问。

    5.11、jsp中使用域对象


    当前页面所有属性都可以读出来

    在另一个页面因为作用域不同,所以有些属性不能读出

    5.12、在servlet中使用域对象

    六、JSP指令

    6.1、Page指令


    page指令的import属性例子,导入要使用的Java类

    page指令的session属性例子,指定JSP页面是否使用session

    page指令的errorPage 指定当JSP页面发生异常时需要转向的错误处理页面

    上述异常亦可以在xml文件中配置,这样就可以不用再每一个jsp文件中都配置一次,节省代码。

    6.2、include指令-静态引入资源

    include指令-静态引入资源中:a中定义的变量,b中可以使用

    细节:
    除了指令元素之外,被引入的文件中的其他元素都被转换成相应的Java源代码,然后插入进当前JSP页面所翻译成的Servlet源文件中,插入位置与include指令在当前JSP页面中的位置保持一致。
    引入文件与被引入文件是在被JSP引擎翻译成Servlet的过程中进行合并,而不是先合并源文件后再对合并的结果进行翻译。当前JSP页面的源文件与被引入文件的源文件可以采用不同的字符集编码。
    file属性的设置值使用相对路径,如果以“/”开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前文件。


    七、JSP动作组件

    与JSP指令元素不同的是,JSP动作元素在请求处理阶段起作用。JSP动作元素是用XML语法写成的。
    利用JSP动作组件可以动态地插入文件、重用JavaBean组件、把用户重定向到另外的页面、为Java插件生成HTML代码。
    动作元素只有一种语法,它符合XML标准:

    7.1、<jsp:include>动作组件

    <jsp:include>动作组件-动态引入资源中:a中定义的变量,b中不可以使用

    <jsp:include>动作元素用来包含静态和动态的文件。该动作把指定文件插入正在生成的页面。语法格式如下:

    <jsp:include page="相对 URL 地址" flush="true" />
    

    <jsp:forward> 动作组件

    jsp:forward动作把请求转到另外的页面。jsp:forward标记只有一个属性page。语法格式如下所示:

    <jsp:forward page="相对 URL 地址" />
    

    <jsp:param> 动作组件

    <jsp:param>用于传递参数信息,必须配合< jsp:include>< jsp:forward>动作组件一起使用。语法如下:

    < jsp:param name=参数名称 ,value=值 />
    

    当该组件与<jsp:include>一起使用时,可以将param组件中的值传递到include动作组件要加载的文件中去。


    <jsp:param> 动作组件除了可以和上面的include组件使用还可以和forward组件一起使用

    补充:JavaBean

    符合下面的设计规则的任何 Java 类都是一个 JavaBean:
    (1)对于数据类型“protype”的每个可读属性,Bean 必须有一个get方法:public proptype getProperty() { }
    (2)对于数据类型“protype”的每个可写属性,Bean 必须有一个set方法:public setProperty(proptype x) { }
    (3)定义一个不带任何参数的构造函数。

    <jsp:useBean><jsp:setProperty><jsp:getProperty>动作组件


    以上是关于JSP 的本质原理解析:"编写的时候是JSP,心里想解读的是 java 源码"的主要内容,如果未能解决你的问题,请参考以下文章

    java web002——jsp(本质也是servlet)

    jsp原理

    自己看之区间DP

    JSP以及JSP解析原理

    Jsp页面中的中文乱码问题解决

    java环境配置及原理详解