JSP 就是 Servlet

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

  自接触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>

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

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    710 引用 • 1173 回帖 • 177 关注
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    21 引用 • 22 回帖
  • SendCloud

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

    2 引用 • 8 回帖 • 438 关注
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 681 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    21 引用 • 140 回帖 • 25 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 350 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    273 引用 • 679 回帖
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 454 关注
  • V2Ray
    1 引用 • 15 回帖
  • 30Seconds

    📙 前端知识精选集,包含 HTML、CSS、JavaScript、React、Node、安全等方面,每天仅需 30 秒。

    • 精选常见面试题,帮助您准备下一次面试
    • 精选常见交互,帮助您拥有简洁酷炫的站点
    • 精选有用的 React 片段,帮助你获取最佳实践
    • 精选常见代码集,帮助您提高打码效率
    • 整理前端界的最新资讯,邀您一同探索新世界
    488 引用 • 383 回帖 • 2 关注
  • 招聘

    哪里都缺人,哪里都不缺人。

    189 引用 • 1056 回帖
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖 • 1 关注
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    35 引用 • 35 回帖
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 68 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    138 引用 • 268 回帖 • 201 关注
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    89 引用 • 113 回帖
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 605 关注
  • 外包

    有空闲时间是接外包好呢还是学习好呢?

    26 引用 • 232 回帖 • 6 关注
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 12 关注
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    180 引用 • 400 回帖 • 1 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 243 关注
  • 机器学习

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

    76 引用 • 37 回帖
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 107 关注
  • 996
    13 引用 • 200 回帖 • 1 关注
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖 • 1 关注
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 18 关注