JSP 就是 Servlet

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

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

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

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    14 引用 • 7 回帖 • 3 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    75 引用 • 258 回帖 • 627 关注
  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    21 引用 • 58 回帖
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 179 关注
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖 • 222 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    82 引用 • 122 回帖 • 618 关注
  • Mobi.css

    Mobi.css is a lightweight, flexible CSS framework that focus on mobile.

    1 引用 • 6 回帖 • 697 关注
  • 单点登录

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

    9 引用 • 25 回帖 • 2 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 544 关注
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 319 关注
  • 微信

    腾讯公司 2011 年 1 月 21 日推出的一款手机通讯软件。用户可以通过摇一摇、搜索号码、扫描二维码等添加好友和关注公众平台,同时可以将自己看到的精彩内容分享到微信朋友圈。

    129 引用 • 793 回帖 • 1 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    19 引用 • 73 回帖 • 1 关注
  • Openfire

    Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。

    6 引用 • 7 回帖 • 89 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    396 引用 • 3416 回帖
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    22 引用 • 31 回帖 • 2 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 641 关注
  • JavaScript

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

    710 引用 • 1173 回帖 • 172 关注
  • Jenkins

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

    51 引用 • 37 回帖 • 1 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 133 关注
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    15 引用 • 7 回帖 • 11 关注
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖 • 3 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    228 引用 • 1450 回帖 • 1 关注
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1398 回帖
  • PostgreSQL

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

    22 引用 • 22 回帖
  • SOHO

    为成为自由职业者在家办公而努力吧!

    7 引用 • 55 回帖 • 93 关注
  • WebClipper

    Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。

    3 引用 • 9 回帖 • 6 关注