前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图解JSP运行原理和过程

图解JSP运行原理和过程

作者头像
望天
发布2018-08-02 11:19:19
2.2K0
发布2018-08-02 11:19:19
举报
文章被收录于专栏:along的开发之旅along的开发之旅

JSP运行过程

  1. WEB容器JSP页面的访问请求时,它将把该访问请求交给JSP引擎去处理。Tomcat中的JSP引擎就是一个Servlet程序,它负责解释和执行JSP页面。
  2. 每个JSP页面在第一次被访问时,JSP引擎先将它翻译成一个Servlet源程序,接着再把这个Servlet源程序编译成Servlet的class类文件,然后再由WEB容器像调用普通Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序。

实例解释

我们用一个实例来说明上面的JSP运行过程:

1. Hello.jsp文件内容如下:

代码语言:javascript
复制
<%@ page pageEncoding="UTF-8" %>
<html>
<head>
    <title>Hello</title>
</head>
<body>
<h1>Hello!</h1>
<h2>当前时间:${currentTime}</h2>
</body>
</html>

2. servlet代码

下面代码通过注解来处理/hello的请求, 并在代码中将请求转发到上述hello.jsp.

代码语言:javascript
复制
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentTime = dateFormat.format(new Date());
        req.setAttribute("currentTime",currentTime);
        req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);
    }
}

3. 运行服务器并访问

这时用everything搜索本机上的hello_jsp.java文件, 可以找到如下内容的文件:

代码语言:javascript
复制
/* 这里显示这是由Tomcat的Jasper组件自动生成的, 接下来我们看下其中最主要的方法
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/9.0.0.M4
 * Generated at: 2016-05-13 01:56:54 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.WEB_002dINF.jsp;

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

  ...

  // 这里是最主要的方法, 我们在jsp文件里的内容, 都在这里通过out.write写入到输出中.
  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {    
    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");
      out.write("<html>\n");
      out.write("<head>\n");
      out.write("    <title>Hello</title>\n");
      out.write("</head>\n");
      out.write("<body>\n");
      out.write("\n");
      out.write("<h1>Hello!</h1>\n");
      out.write("\n");
      out.write("<h2>当前时间:");
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${currentTime}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
      out.write("</h2>\n");
      out.write("\n");
      out.write("</body>\n");
      out.write("</html>");
    } catch (java.lang.Throwable t) {
      ...
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

这里可以看出, 当我们访问需要jsp文件时, tomcat的Jasper组件会将jsp文件翻译成java文件, 然后再编译. 继续用everything搜索hello_jsp, 可以发现还有一个文件叫hello_jsp.class, 侧面印证了我们的论断.

同时我们在jsp文件中的代码, 都被编译到了_jspService函数中, 这个函数会在servlet中service中执行, 来响应用户的操作.

我们看下自动生成的类继承自 org.apache.jasper.runtime.HttpJspBase, 然后我们看下这个类的声明:

代码语言:javascript
复制
public abstract class org.apache.jasper.runtime.HttpJspBase extends javax.servlet.http.HttpServlet implements javax.servlet.jsp.HttpJspPage

HttpJspBase实现了HttpServlet, 所以jsp文件生成的类也是一个servlet. 所以其生命周期也可以交由web服务器控制.

图形解释

我们先用图形大概解释一下上述流程:

这里写图片描述
这里写图片描述

简洁易懂. 接下来我们在思考每一步的具体实现, 看下图:

1.客户端请求jsp文件, web服务器(tomcat等)根据jsp文件生成java文件.

这里写图片描述
这里写图片描述

2.java文件生成对应的class字节码文件,字节码文件是可以通过classloader加载进虚拟机的.

这里写图片描述
这里写图片描述

3.web容器加载class字节码文件.

这里写图片描述
这里写图片描述

4.web容器通过反射等手段建立hello_jsp实例.

这里写图片描述
这里写图片描述

5.调用对应的jspInit来进行实例初始化.

这里写图片描述
这里写图片描述

6.调用_jspservice, 响应用户请求.

这里写图片描述
这里写图片描述

7.调用jspDestroy销毁jsp_hello实例.

这里写图片描述
这里写图片描述

因为jsp_hello继承自HttpJspBase, HttpJspBase又继承自Servlet, 所以jsp_hello是个servlet, 其生命周期可以交由web服务器控制.

JSP的生命周期

1)翻译: jsp->java文件 2)编译: java文件->class文件(servlet程序) 3)构造方法(第1次访问) 4)init方法(第1次访问):_jspInit() 5)service方法:_jspService() 6)destroy方法:_jspDestroy()

这里你可能会有疑问, 为什么调用的是 _jspService方法, 而不是Servlet的service方法? 我们看下HttpJspBase源码(在”tomcat\lib\jasper.jar”中的org.apache.jasper.runtime包中), 就明白了.

代码语言:javascript
复制
    public final void init(ServletConfig config) throws ServletException {
        super.init(config);
        this.jspInit();
        this._jspInit();
    }

    public String getServletInfo() {
        return Localizer.getMessage("jsp.engine.info");
    }

    public final void destroy() {
        this.jspDestroy();
        this._jspDestroy();
    }

    public final void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this._jspService(request, response);
    }

从中可以看到, Servlet的service会自动调用我们的_jspService方法, init会自动调用我们的_jspInit()方法, 这下终于真相大白了.

[引用以下文章内容: http://blog.csdn.net/fengdongkun/article/details/8159381 http://blog.csdn.net/hanxuemin12345/article/details/23831645]

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年05月13日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JSP运行过程
  • 实例解释
    • 1. Hello.jsp文件内容如下:
      • 2. servlet代码
        • 3. 运行服务器并访问
        • 图形解释
        • JSP的生命周期
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档