JSP复盘

发布于 2021-01-11  391 次阅读


一,JSP的底层原理

JSP的基本概念:JSP是一种动态模板引擎,相比较于静态模板引擎,它是静态代码和java代码段的组合体,它需要编译和代码解析

含义:JSP本质上是一个Servlet,它使用了Servlet的内置对象和处理逻辑,相比于Servlet ,JSP的主要功能是展示数据,而Servlet是处理业务逻辑

JSP的运行实现过程:① JSP文件 ---> ② Tomcat的Jasper引擎(JSP引擎)编译成.java文件  ---> ③ java编译器再把.java文件编译成.class字节码文件 ---> ④ JVM执行字节码文件 ---> ⑤ HTML网页文件

一,JSP的底层代码解析

JSP编译成java文件后的源码结构:以index.jsp为例

package org.apache.jsp;
//导入Servlet的一系列包
import javax.servlet.*a'a;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.*;

//类名和jsp的名称一致,它继承了HttpJspBase,实现了JspSourceDependent和JspSourceImports
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {
  //实例化JSP的Factory的工厂
  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;
  //依赖包的set集合
  private static final java.util.Set<java.lang.String> _jspx_imports_packages;
  //依赖类的class的set集合
  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;
  }
  //el的表达式工厂
  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  //tomcat的事务管理
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
   
  //返回当前页有源依赖项的文件名列表(这是实现runtime.JspSourceDependent)后需要实现的方法
  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }
  
  //获取PackageImports对象
  public java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }
  
  //获取ClassImports对象
  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }
  
  //获取_getExpressionFactory的el工厂
  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;
  }
  
  //获取tomcat的InstanceManger引擎对象
  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;
  }
  
  //_jsp的init初始化方法
  public void _jspInit() {
  }
  
  //_jsp的销毁方法
  public void _jspDestroy() {
  }
  
  //_jsp的Service的逻辑处理方法(所有的java代码和EL表达式,html代码都在这个方法中实现),形参request,response,exception
  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, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 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;
    
    //分别是out和context,在try中会分别等于out和context
    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;

      //打印jsp中的hmtl代码
      out.write("\n");
      out.write("\n");
      out.write("<html>\n");
      out.write("  <head>\n");
      out.write("    <title>$Title$</title>\n");
      out.write("  </head>\n");
      out.write("  <body>\n");
      out.write("  ");
      out.write("\n");
      out.write("  <h1>\n");
      out.write("    <p>a = ");
      out.print( a);
      out.write("</p>\n");
      out.write("\n");
      out.write("    </h1>\n");
      out.write("  </body>\n");
      out.write("</html>\n");
    } 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的6个全局变量

  1. javax.servlet.jsp.JspFactory _jspxFactory:public抽象类JspFactory扩展了java.lang.ObjectJspFactory是一个抽象类,它定义了许多在运行时JSP页面可用的工厂方法,用于创建“用于支持JSP实现的各种接口和类的creatinq实例”。一个符合要求的JSP引擎实现将在初始化期间实例化这个类的一个依赖于实现的子类,并通过静态setDefaultFactory()方法请求用这个类创建的实例,使其可被JSP实现类全局使用。
  2. java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants:依赖源文件名列表。
  3. java.util.Set<java.lang.String> _jspx_imports_packages:依赖包的set集合
  4. java.util.Set<java.lang.String> _jspx_imports_classes:依赖类的set集合
  5. javax.el.ExpressionFactory _el_expressionfactory:el表达式工厂
  6. org.apache.tomcat.InstanceManager _jsp_instancemanager:tomcat的jsp事务引擎

1,JspFactory工厂类

工厂类的API:

static JspFactory getDefaultFactory()
Returns the default factory for this implementation.
abstract  JspEngineInfo getEngineInfo()
called to get implementation-specific information on the current JSP engine.
abstract  PageContext getPageContext(javax.servlet.Servlet servlet, javax.servlet.ServletRequest request, javax.servlet.ServletResponse response, java.lang.String errorPageURL, boolean needsSession, int buffer, boolean autoflush)
obtains an instance of an implementation dependent javax.servlet.jsp.PageContext abstract class for the calling Servlet and currently pending request and response.
abstract  void releasePageContext(PageContext pc)
called to release a previously allocated PageContext object.
static void setDefaultFactory(JspFactory deflt)
set the default factory for this implementation.

API:

  • getDefaultFactory:获取Factory默认工厂对象
  • getEngineInfo:获取当前JSP引擎的特定实现信息
  • getPageContext:获取PageContext对象
  • releasePageContext:释放当前的分配的PageContext对象
  • setDefaultFactory:设置工厂配置信息

二,jsp的九大内置对象

九大内置对象都在_jspservice方法中,内置对象大多是引入了Servlet中的对象

形参中的三个内置对象:

  1. javax.servlet.http.HttpServletRequest request:Servlet的Request
  2. javax.servlet.http.HttpServletResponse response:Servlet的response
  3. javax.servlet.ServletException:Exception的异常处理对象

局部变量中的六个内置对象:

  1. javax.servlet.jsp.PageContext pageContext:pagecontext是servlet第四大域,也能获取servlet重要对象
  2. javax.servlet.http.HttpSession session:servlet的session对象
  3. javax.servlet.ServletContext application:ServletContext对象
  4. avax.servlet.ServletConfig config:ServletConfig获取servlet配置信息
  5. javax.servlet.jsp.JspWriter out:Jspwriter打印流对象
  6. java.lang.Object page:page 对象代表JSP本身,只有在JSP页面内才是合法的。 page隐含对象本质上包含当前 Servlet接口引用的变量,类似于Java编程中的 this 指针

JSP中的四大域:

  1. pagecontext:最小域,作用域为当前页面
  2. httpservletrequest:作用域为当前请求的转发
  3. httpservletsession:作用域为当前会话
  4. httpservletcontext:当前应用服务器
一,pageContext
它继承了JspContext,pageContext本身也是一个域对象,但它的域范围太小只适用于当前页面
pageContext作用:
                            ①提供域空间
                            ②获取其他Servlet对象,如Session,Request,ServletConfig……
父类JspContext的方法:
本身方法: