图解JSP运行原理和过程
2016-09-29 11:34
405 查看
转自http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380146d96864968d4e414c422461c1b37b4e8797f4c51ce963c215afe170bf7a6613464587ef686cf8b4bd6ba922c2b9c6269304a895615a70eaebb1e648337912aa8f859a3e1a16584afa2c4af2444bd50127bf0e7fd5f1762cc7880102690d28e49654860bdfa4460e82f763eee2257b737ee9132797383&p=8b2a975e86cc41ac58ae8f344c0a8e&newp=8d62cb1085cc43b513bd9b7e0e1697231610db2151d1d001298ffe0cc4241a1a1a3aecbf26231600d4c678600bab485eebf13674340634f1f689df08d2ecce7e35c3&user=baidu&fm=sc&query=%5FjspService%BB%E1%D7%D4%B6%AF%B5%F7%D3%C3%C2%F0&qid=f2de0e110005699c&p1=7
WEB容器JSP页面的访问请求时,它将把该访问请求交给JSP引擎去处理。Tomcat中的JSP引擎就是一个Servlet程序,它负责解释和执行JSP页面。
每个JSP页面在第一次被访问时,JSP引擎先将它翻译成一个Servlet源程序,接着再把这个Servlet源程序编译成Servlet的class类文件,然后再由WEB容器像调用普通Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序。
我们用一个实例来说明上面的JSP运行过程:
下面代码通过注解来处理/hello的请求, 并在代码中将请求转发到上述hello.jsp.
这时用everything搜索本机上的hello_jsp.java文件, 可以找到如下内容的文件:
这里可以看出, 当我们访问需要jsp文件时, tomcat的Jasper组件会将jsp文件翻译成java文件, 然后再编译. 继续用everything搜索hello_jsp, 可以发现还有一个文件叫hello_jsp.class, 侧面印证了我们的论断.
同时我们在jsp文件中的代码, 都被编译到了
来响应用户的操作.
我们看下自动生成的类继承自 org.apache.jasper.runtime.HttpJspBase, 然后我们看下这个类的声明:
HttpJspBase实现了HttpServlet, 所以jsp文件生成的类也是一个servlet. 所以其生命周期也可以交由web服务器控制.
jsp编译成sevlet时继承了HttpJspBase类,在此类中有jsp里面重载的方法,但在这是空白的,在jsp里面被init()调用时,实际调用的是重载的方法。
我们先用图形大概解释一下上述流程:
简洁易懂. 接下来我们在思考每一步的具体实现, 看下图:
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服务器控制.
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”中的
就明白了.
从中可以看到, Servlet的service会自动调用我们的_jspService方法, init会自动调用我们的_jspInit()方法, 这下终于真相大白了.
[引用以下文章内容:
http://blog.csdn.net/fengdongkun/article/details/8159381
http://blog.csdn.net/hanxuemin12345/article/details/23831645]
JSP运行过程
WEB容器JSP页面的访问请求时,它将把该访问请求交给JSP引擎去处理。Tomcat中的JSP引擎就是一个Servlet程序,它负责解释和执行JSP页面。每个JSP页面在第一次被访问时,JSP引擎先将它翻译成一个Servlet源程序,接着再把这个Servlet源程序编译成Servlet的class类文件,然后再由WEB容器像调用普通Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序。
实例解释
我们用一个实例来说明上面的JSP运行过程:
1. Hello.jsp文件内容如下:
<%@ page pageEncoding="UTF-8" %> <html> <head> <title>Hello</title> </head> <body> <h1>Hello!</h1> <h2>当前时间:${currentTime}</h2> </body> </html>
2. servlet代码
下面代码通过注解来处理/hello的请求, 并在代码中将请求转发到上述hello.jsp.@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文件, 可以找到如下内容的文件:/* 这里显示这是由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, 然后我们看下这个类的声明:
public abstract class org.apache.jasper.runtime.HttpJspBase extends javax.servlet.http.HttpServlet implements javax.servlet.jsp.HttpJspPage
HttpJspBase实现了HttpServlet, 所以jsp文件生成的类也是一个servlet. 所以其生命周期也可以交由web服务器控制.
jsp编译成sevlet时继承了HttpJspBase类,在此类中有jsp里面重载的方法,但在这是空白的,在jsp里面被init()调用时,实际调用的是重载的方法。
图形解释
我们先用图形大概解释一下上述流程: 简洁易懂. 接下来我们在思考每一步的具体实现, 看下图:
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包中),
就明白了.
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]
相关文章推荐
- 图解JSP运行原理和过程
- JSP运行原理及运行过程
- JSP起源、JSP的运行原理、JSP的执行过程
- JSP运行原理以及执行过程源码分析
- jsp的运行原理及执行过程
- JSP起源、JSP的运行原理、JSP的执行过程
- JSP起源、JSP的运行原理、JSP的执行过程
- JSP起源、JSP的运行原理、JSP的执行过程
- JSP起源、JSP的运行原理、JSP的执行过程
- JSP运行原理及运行过程
- JSP运行原理和翻译过程
- JSP起源、JSP的运行原理、JSP的执行过程
- JSP运行原理及运行过程
- JSP起源、JSP的运行原理、JSP的执行过程
- JSP起源、JSP的运行原理、JSP的执行过程
- JSP的执行过程,运行原理(图)
- JSP运行原理以及执行过程源码分析
- JSP - 什么是JSP,JSP的特点、调用运行过程
- 生产过程的基本组成和运行原理
- 探究X Window System运行原理与启动过程