JSP实现原理
JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。
起源:
在很多动态网页中,绝大部分内容都是固定不变的,只有局部内容需要动态产生和改变。如果使用Servlet程序来输出只有局部内容需要动态改变的网页,其中所有的静态内容也需要程序员用Java程序代码产生,整个Servlet程序的代码将非常臃肿,编写和维护都将非常困难。
解决方案:
为了弥补Servlet的缺陷,SUN公司在Servlet的基础上推出了JSP(Java Server Pages)技术作为解决方案。JSP是简化Servlet编写的一种技术,它将Java代码和HTML语句混合在同一个文件中编写,只对网页中的要动态产生的内容采用Java代码来编写,而对固定不变的静态内容采用普通静态HTML页面的方式编写
与Html相比:
html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据。
与Servlet相比:
servlet很难对数据进行排版,而jsp除了可以用java代码产生动态数据的同时,也很容易对数据进行排版,避免了servlet中编写大量的拼接HTML代码。
思考:JSP为什么可以像Servlet一样,也可以叫做动态web资源的开发技术?
解释:其实Jsp就是一个Servlet。下面是对这句话的具体解释!
JSP的调用过程原理图:
执行流程简介:
1,当WEB容器(Servlet引擎)接收到以.jsp为扩展名的URL的访问请求时,它将把该访问请求交给JSP引擎去处理。
2,Tomcat中的JSP引擎就是一个Servlet程序,它负责解释和执行JSP页面。
3,当我们第一次访问Jsp的时候,Jsp引擎都会将这个Jsp翻译成一个Servlet,这个文件存放在Tomcat中的work目录中
4,接着再把这个Servlet源程序编译成Servlet的class类文件
5,然后再由WEB容器(Servlet引擎)像调用普通Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序。
具体代码示例:
jsp页面:
- <html>
- <head>
- <title> HelloWorld </title>
- </head>
- <body>
- <%
- out.println("HelloWorld");
- %>
- </body>
- </html>
在tomcat的conf文件中的web.xml中
- <servlet>
- <servlet-name>jsp</servlet-name>
- <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
- <init-param>
- <param-name>fork</param-name>
- <param-value>false</param-value>
- </init-param>
- <init-param>
- <param-name>xpoweredBy</param-name>
- <param-value>false</param-value>
- </init-param>
- <load-on-startup>3</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>jsp</servlet-name>
- <url-pattern>*.jsp</url-pattern>
- </servlet-mapping>
- <servlet-mapping>
- <servlet-name>jsp</servlet-name>
- <url-pattern>*.jspx</url-pattern>
- </servlet-mapping>
tomcat源码中JSPServlet类的实现。
这个类主要也是继承HttpServlet。重写了HttpServlet的service方法。
如果jsp第一次使用,要将它编译成servlet。编译好后将生成我们相关的文件即HelloWorld_jsp.java
- public void service (HttpServletRequest request,
- HttpServletResponse response)
- throws ServletException, IOException {
- String jspUri = null;
- String jspFile = (String) request.getAttribute(Constants.JSP_FILE);
- if (jspFile != null) {
- // JSP is specified via <jsp-file> in <servlet> declaration
- jspUri = jspFile;
- } else {
- /*
- * Check to see if the requested JSP has been the target of a
- * RequestDispatcher.include()
- */
- jspUri = (String) request.getAttribute(Constants.INC_SERVLET_PATH);
- if (jspUri != null) {
- /*
- * Requested JSP has been target of
- * RequestDispatcher.include(). Its path is assembled from the
- * relevant javax.servlet.include.* request attributes
- */
- String pathInfo = (String) request.getAttribute(
- "javax.servlet.include.path_info");
- if (pathInfo != null) {
- jspUri += pathInfo;
- }
- } else {
- /*
- * Requested JSP has not been the target of a
- * RequestDispatcher.include(). Reconstruct its path from the
- * request's getServletPath() and getPathInfo()
- */
- jspUri = request.getServletPath();
- String pathInfo = request.getPathInfo();
- if (pathInfo != null) {
- jspUri += pathInfo;
- }
- }
- }
- if (log.isDebugEnabled()) {
- log.debug("JspEngine --> " + jspUri);
- log.debug("\t ServletPath: " + request.getServletPath());
- log.debug("\t PathInfo: " + request.getPathInfo());
- log.debug("\t RealPath: " + context.getRealPath(jspUri));
- log.debug("\t RequestURI: " + request.getRequestURI());
- log.debug("\t QueryString: " + request.getQueryString());
- }
- try {
- boolean precompile = preCompile(request);
- serviceJspFile(request, response, jspUri, null, precompile);
- } catch (RuntimeException e) {
- throw e;
- } catch (ServletException e) {
- throw e;
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- throw new ServletException(e);
- }
- }
生成的servlet类--HelloWorld_jsp.java
- package org.apache.jsp;
- import javax.servlet.*;
- import javax.servlet.http.*;
- import javax.servlet.jsp.*;
- public final class HelloWorld_jsp extends org.apache.jasper.runtime.HttpJspBase
- implements org.apache.jasper.runtime.JspSourceDependent {
- private static java.util.List _jspx_dependants;
- public Object getDependants() {
- return _jspx_dependants;
- }
- public void _jspService(HttpServletRequest request, HttpServletResponse response)
- throws java.io.IOException, ServletException {
- JspFactory _jspxFactory = null;
- PageContext pageContext = null;
- HttpSession session = null;
- ServletContext application = null;
- ServletConfig config = null;
- JspWriter out = null;
- Object page = this;
- JspWriter _jspx_out = null;
- PageContext _jspx_page_context = null;
- try {
- _jspxFactory = JspFactory.getDefaultFactory();
- 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("<html>\r\n");
- out.write("\t<head>\r\n");
- out.write("\t\t<title>HelloWorld</title>\r\n");
- out.write("\t</head>\r\n");
- out.write("\t<body>\r\n");
- out.write("\t\t");
- out.println("HelloWorld");
- out.write("\r\n");
- out.write("\t</body>\r\n");
- out.write("</html>");
- } catch (Throwable t) {
- if (!(t instanceof SkipPageException)){
- out = _jspx_out;
- if (out != null && out.getBufferSize() != 0)
- out.clearBuffer();
- if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
- }
- } finally {
- if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
- }
- }
- }
我们看到,这个类继承了org.apache.jasper.runtime.HttpJspBase,具体HttpJspBase类的tomcat的源码如下:
根据时序图,首先调用service方法,然后service方法内部调用_jspService抽象方法,此方法并没有实现,故继承它的HelloWorld_jsp.java类实现。
- package org.apache.jasper.runtime;
- import java.io.IOException;
- import javax.servlet.ServletConfig;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.jsp.HttpJspPage;
- import javax.servlet.jsp.JspFactory;
- 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
- {
- protected HttpJspBase() {
- }
- public final void init(ServletConfig config)
- throws ServletException
- {
- super.init(config);
- jspInit();
- _jspInit();
- }
- public String getServletInfo() {
- return Localizer.getMessage("jsp.engine.info");
- }
- public final void destroy() {
- jspDestroy();
- _jspDestroy();
- }
- /**
- * Entry point into service.
- */
- public final void service(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException
- {
- _jspService(request, response);
- }
- public void jspInit() {
- }
- public void _jspInit() {
- }
- public void jspDestroy() {
- }
- protected void _jspDestroy() {
- }
- public abstract void _jspService(HttpServletRequest request,
- HttpServletResponse response)
- throws ServletException, IOException;
- }
如果:
让jsp既用java代码产生动态数据,又做美化会导致jsp的职责过重且页面难以维护。
让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。
总结:
不管是JSP还是Servlet,都可以用于开发动态web资源(学习的共同点)。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用(不同点,也可以说发挥各自优势!其中,JSP对于程序员来说省去了在后台手动拼接html代码的过程)。
因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做,这样职责单一,容易维护也正符合我们软件设计中的分层与单一职责等思想。
其实我们学习的各类技术以及各种设计模式,它们的出现或形成都是软件设计思想的一种体现!
JSP实现原理的更多相关文章
- jsp学习--JSP运行原理,九大隐式对象和JSP常用标签
一.JSP运行原理 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet ...
- JSP JSP工作原理 JSP语法 JSP声明 JSP注释 JSP指令 jsp九大隐式/内置对象
1 什么是JSP 1)为什么说,Servlet是一个动态Web开发技术呢? Servlet是基于服务端的一种动态交互技术, HttpServletRequest表示客户端到服务端的 ...
- JavaWeb(二)jsp运行原理,九大内置对象
JSP运行原理: 每个JSP页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ...
- JSP基本语法总结【1】(jsp工作原理,脚本元素,指令元素,动作元素)
时隔半年,回头对jsp复习整理一下,温故而知新. jsp工作原理: jsp服务器管理jsp页面分两个阶段:转换阶段(translation phase)和执行阶段(execution phase). ...
- Unit04: JSP基本语法 、 JSP运行原理
Unit04: JSP基本语法 . JSP运行原理 hello.jsp <%@page pageEncoding="utf-8"%> <!doctype html ...
- JSP以及JSP解析原理
什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写htm ...
- JSP的原理
一.什么是JSP JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大特点在于,写JSP就行html, ...
- JSP工作原理
一.历史 JSP是Servlet的扩展,JSP没出现之前,就已经出现了Servlet技术.Servlet是利用了"输出流",动态的生成了HTML页面.包括 每一个HTML标签和所有 ...
- 你也可以当面霸-Servlet与JSP的原理及特点
既然是面试系列,就是面试官和应聘者之间的对话.本文是采用一问一答的形式呈现给读者的,这样能有一个明确的考察点,不像理论知识那么枯燥. 01.什么是Servlet技术 Servlet是和平台无关的服务器 ...
- JSP学习——原理
JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比 ...
随机推荐
- 怎样从Mysql官网下载mysql.tar.gz版本的安装包
今天学习在Linux上部署项目,用到了Mysql,因此想要下载适用于Linux的安装版本,在Mysql官网找了半天,终于找到怎样下载了,这里写出来,以后大家找的时候就好找了. 第一步:在百度输入My ...
- 浅析PageRank算法(转)
浅析PageRank算法 本文首先会讨论搜索引擎的核心难题,同时讨论早期搜索引擎关于结果页面重要性评价算法的困境,借此引出PageRank产生的背景.第二部分会详细讨论PageRank的思想来源.基础 ...
- 酷壳用的还是 Wordpress
WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站.也可以把 WordPress当作一个内容管理系统(CMS)来使用. http: ...
- VS2013\VS2017 使用git 总是需要输入账号密码
问题: VS2013\VS2017 使用git 总是需要输入账号密码 解决方案:删除原凭证,或者修改原凭证,重新输入一次账号和密码并且选择“记住凭证”即可!
- zookeeper基本概念及原理
zookeeper是一个分布式的,开源的分布式应用程序,该程序主要用于管理其他分布式应用程序.其他分布式应用程序可以基于zookeeper实现数据同步,配置维护和命名服务等等.zookeeper是Ha ...
- myslq中插入时间当前时间
create table classic_movie_info( id ) primary key auto_increment not null, movie_name varchar(), mov ...
- Python IDLE或shell中切换路径
在Python自带的编辑器IDLE中或者python shell中不能使用cd命令,那么跳到目标路径呢.方法是使用os包下的相关函数实现路径切换功能. import os os.getcwd() # ...
- Powershell Function Get-TimeZone
代码原文地址: https://gallery.technet.microsoft.com/scriptcenter/Get-TimeZone-PowerShell-4f1a34e6 <# .S ...
- 让WebApi支持Namespace
环境:VS2012 .net 4.0 参考: http://aspnet.codeplex.com/SourceControl/changeset/view/dd207952fa86#Samples/ ...
- IIS 部署WCF时遇到这么个错:
转(http://blog.csdn.net/vic0228/article/details/48806405) 部署WCF时遇到这么个错: "The service cannot be a ...