JSP 就是 Servlet

本贴最后更新于 2935 天前,其中的信息可能已经事过境迁

  自接触Java开发以来JSP在我的个人经验里一直扮演着重要的角色,一直以为能够熟练使用JSP就是很好的掌握了它,
  但在一次面试过程当中被问及一个问题:“JSP 与 Servlet 的相同之处是什么”时,才发现自己对JSP工作的原理几乎一无所知。
  现在我将与大家分享经过学习和整理后我所理解的JSP和Servlet,
  本观点仅代表个人看法,大家可在评论里就这个问题畅所欲言,以求大家共同进步。
  
  **首先JSP是什么呢?**
  
  JSP是一种动态页面技术 java server page,其根本是一个简化的Servlet设计。
  JSP诞生的目的就是为了让前端代码和后端代码分离在不同的文件中。
  它实现了Html语法中的java扩展(以 <%, %>形式),JSP与Servlet一样,在服务器端执行。
  通常返回给客户端的就是一个HTML文本,因此客户端只要有浏览器就能浏览。
  我们使用JSP的主要目的就是将表示逻辑从Servlet中分离出来,这样能够极大的简化开发。
  那么以上解释具体应该怎么理解呢?我们首先来看一个编译后的Servlet(.java)文件。
  jsp被变成了一个继承了org.apache.jasper.runtime.HttpJspBase的类。
  查看jasper.jar里的HttpJspBase源码就可以发现HttpJspBase继承自javax.servlet.http.HttpServlet,
  所以jsp就是一个servlet。
  
  **Jsp文件**

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> This is my JSP page. </body> </html>

  **Java文件**

/* * Generated by the Jasper component of Apache Tomcat * Version: JspCServletContext/1.0 * Generated at: 2017-02-24 03:08:52 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 javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; import java.util.*; public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map&lt;java.lang.String,java.lang.Long&gt; _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map&lt;java.lang.String,java.lang.Long&gt; getDependants() { return _jspx_dependants; } public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); } public void _jspDestroy() { } public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { 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; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; try { response.setContentType("text/html;charset=ISO-8859-1"); 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('\r'); out.write('\n'); String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; out.write("\r\n\r\n&lt;!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"&gt;\r\n&lt;html&gt;\r\n &lt;head&gt;\r\n &lt;base href=\""); out.print(basePath); out.write("\"&gt;\r\n \r\n &lt;title&gt;My JSP 'index.jsp' starting page&lt;/title&gt;\r\n\t&lt;meta http-equiv=\"pragma\" content=\"no-cache\"&gt;\r\n\t&lt;meta http-equiv=\"cache-control\" content=\"no-cache\"&gt;\r\n\t&lt;meta http-equiv=\"expires\" content=\"0\"&gt; \r\n\t&lt;meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\"&gt;\r\n\t&lt;meta http-equiv=\"description\" content=\"This is my page\"&gt;\r\n\t&lt;!--\r\n\t&lt;link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\"&gt;\r\n\t--&gt;\r\n &lt;/head&gt;\r\n \r\n &lt;body&gt;\r\n This is my JSP page. &lt;br&gt;\r\n &lt;/body&gt;\r\n&lt;/html&gt;\r\n"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null &amp;&amp; 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); } } }

  大家可以看到,在这个文件里面有html代码,但这个文件是从.jsp文件转译成的.java文件,并不是手动编写的。
  也就是说我们写的JSP文件并不是直接运行的,而是先会转译成.java文件。
  做这个工作的正是JSP Container 即Tomcat服务器,它会将.jsp文件转译成.java文件,
  然后再将.java文件编译成.class文件,.class文件会处理请求,返回响应,最后生成页面返回给客户端显示。
  所以也可以理解为JSP文件就是Servlet文件,因为JSP文件是转换成Servlet文件才运行的。
  没有JSP的话,就需要把静态页面的代码手动写到Servlet文件里,这时候其实就是将网页逻辑和网页设计写在了一起,
  这样的开发复杂且效率比较低,所以JSP的出现就是将网页设计分离出来,简化开发。
  
  既然是tomcat做的把jsp变为java的动作,那么java文件在哪呢?
  可以看看tomcat的以下路径,就会发现我们发布在tomcat上的jsp被tomcat转化后java文件了。
  tomcat\work\Catalina\localhost\工程名\org\apache\jsp\
  
  当然tomcat的jasper.jar里有个org.apache.jasper.JspC类。
  我们可以使用这个类手动来做jsp2java的动作。
  借助ant,我们就可以调用JspC这个类。
  执行jsp2java在outputDir设定的文件夹里就可以看到自己工程里jsp变成的java文件了。
 

<?xml version="1.0" encoding="GBK"?> <project name="WebApp Precompilation JSP to Java to Class to Jar" basedir="." default="help"> <target name="jsp2java"> <taskdef classname="org.apache.jasper.JspC" name="jsp2java"> <classpath id="jsp2java.classpath"> <fileset dir="D:/tomcat/bin"> <include name="*.jar"/> </fileset> <fileset dir="D:/tomcat/lib"> <include name="*.jar"/> </fileset> <fileset dir="D:/workspace/SSMv1.0/WebRoot/WEB-INF/lib"> <include name="*.jar"/> </fileset> </classpath> </taskdef> <!-- 注意JSP文件要设置为UTF-8编码 --> <jsp2java classpath="jsp2java.classpath" javaEncoding="UTF-8" validateXml="false" uriroot="D:/workspace/SSMv1.0/WebRoot" webXmlFragment="D:/workspace/SSMv1.0/WebRoot/WEB-INF/webJSP.xml" outputDir="D:/workspace/SSMv1.0/WebRoot/WEB-INF/JspC/src"/> </target> </project>

  希望以上解释能对大家有所帮助!

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 新人

    让我们欢迎这对新人。哦,不好意思说错了,让我们欢迎这位新人!
    新手上路,请谨慎驾驶!

    52 引用 • 228 回帖 • 1 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖 • 3 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 73 关注
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    54 引用 • 37 回帖 • 2 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 487 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    12 引用 • 5 回帖 • 630 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 1 关注
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    179 引用 • 408 回帖 • 486 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    7 引用 • 69 回帖 • 4 关注
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    76 引用 • 389 回帖
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖 • 1 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    27 引用 • 196 回帖 • 26 关注
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 660 关注
  • sts
    2 引用 • 2 回帖 • 221 关注
  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    21 引用 • 204 回帖 • 1 关注
  • HTML

    HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。

    108 引用 • 295 回帖
  • gRpc
    11 引用 • 9 回帖 • 88 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 568 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 3 关注
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    34 引用 • 467 回帖 • 760 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 4 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    289 引用 • 4492 回帖 • 658 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖
  • 音乐

    你听到信仰的声音了么?

    61 引用 • 512 回帖
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖