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页面:

  1. <html>
  2. <head>
  3. <title> HelloWorld </title>
  4. </head>
  5. <body>
  6. <%
  7. out.println("HelloWorld");
  8. %>
  9. </body>
  10. </html>

在tomcat的conf文件中的web.xml中

  1. <servlet>
  2. <servlet-name>jsp</servlet-name>
  3. <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
  4. <init-param>
  5. <param-name>fork</param-name>
  6. <param-value>false</param-value>
  7. </init-param>
  8. <init-param>
  9. <param-name>xpoweredBy</param-name>
  10. <param-value>false</param-value>
  11. </init-param>
  12. <load-on-startup>3</load-on-startup>
  13. </servlet>
  14. <servlet-mapping>
  15. <servlet-name>jsp</servlet-name>
  16. <url-pattern>*.jsp</url-pattern>
  17. </servlet-mapping>
  18. <servlet-mapping>
  19. <servlet-name>jsp</servlet-name>
  20. <url-pattern>*.jspx</url-pattern>
  21. </servlet-mapping>

tomcat源码中JSPServlet类的实现。

这个类主要也是继承HttpServlet。重写了HttpServlet的service方法。

如果jsp第一次使用,要将它编译成servlet。编译好后将生成我们相关的文件即HelloWorld_jsp.java

  1. public void service (HttpServletRequest request,
  2. HttpServletResponse response)
  3. throws ServletException, IOException {
  4. String jspUri = null;
  5. String jspFile = (String) request.getAttribute(Constants.JSP_FILE);
  6. if (jspFile != null) {
  7. // JSP is specified via <jsp-file> in <servlet> declaration
  8. jspUri = jspFile;
  9. } else {
  10. /*
  11. * Check to see if the requested JSP has been the target of a
  12. * RequestDispatcher.include()
  13. */
  14. jspUri = (String) request.getAttribute(Constants.INC_SERVLET_PATH);
  15. if (jspUri != null) {
  16. /*
  17. * Requested JSP has been target of
  18. * RequestDispatcher.include(). Its path is assembled from the
  19. * relevant javax.servlet.include.* request attributes
  20. */
  21. String pathInfo = (String) request.getAttribute(
  22. "javax.servlet.include.path_info");
  23. if (pathInfo != null) {
  24. jspUri += pathInfo;
  25. }
  26. } else {
  27. /*
  28. * Requested JSP has not been the target of a
  29. * RequestDispatcher.include(). Reconstruct its path from the
  30. * request's getServletPath() and getPathInfo()
  31. */
  32. jspUri = request.getServletPath();
  33. String pathInfo = request.getPathInfo();
  34. if (pathInfo != null) {
  35. jspUri += pathInfo;
  36. }
  37. }
  38. }
  39. if (log.isDebugEnabled()) {
  40. log.debug("JspEngine --> " + jspUri);
  41. log.debug("\t     ServletPath: " + request.getServletPath());
  42. log.debug("\t        PathInfo: " + request.getPathInfo());
  43. log.debug("\t        RealPath: " + context.getRealPath(jspUri));
  44. log.debug("\t      RequestURI: " + request.getRequestURI());
  45. log.debug("\t     QueryString: " + request.getQueryString());
  46. }
  47. try {
  48. boolean precompile = preCompile(request);
  49. serviceJspFile(request, response, jspUri, null, precompile);
  50. } catch (RuntimeException e) {
  51. throw e;
  52. } catch (ServletException e) {
  53. throw e;
  54. } catch (IOException e) {
  55. throw e;
  56. } catch (Throwable e) {
  57. throw new ServletException(e);
  58. }
  59. }

生成的servlet类--HelloWorld_jsp.java

  1. package org.apache.jsp;
  2. import javax.servlet.*;
  3. import javax.servlet.http.*;
  4. import javax.servlet.jsp.*;
  5. public final class HelloWorld_jsp extends org.apache.jasper.runtime.HttpJspBase
  6. implements org.apache.jasper.runtime.JspSourceDependent {
  7. private static java.util.List _jspx_dependants;
  8. public Object getDependants() {
  9. return _jspx_dependants;
  10. }
  11. public void _jspService(HttpServletRequest request, HttpServletResponse response)
  12. throws java.io.IOException, ServletException {
  13. JspFactory _jspxFactory = null;
  14. PageContext pageContext = null;
  15. HttpSession session = null;
  16. ServletContext application = null;
  17. ServletConfig config = null;
  18. JspWriter out = null;
  19. Object page = this;
  20. JspWriter _jspx_out = null;
  21. PageContext _jspx_page_context = null;
  22. try {
  23. _jspxFactory = JspFactory.getDefaultFactory();
  24. response.setContentType("text/html");
  25. pageContext = _jspxFactory.getPageContext(this, request, response,
  26. null, true, 8192, true);
  27. _jspx_page_context = pageContext;
  28. application = pageContext.getServletContext();
  29. config = pageContext.getServletConfig();
  30. session = pageContext.getSession();
  31. out = pageContext.getOut();
  32. _jspx_out = out;
  33. out.write("<html>\r\n");
  34. out.write("\t<head>\r\n");
  35. out.write("\t\t<title>HelloWorld</title>\r\n");
  36. out.write("\t</head>\r\n");
  37. out.write("\t<body>\r\n");
  38. out.write("\t\t");
  39. out.println("HelloWorld");
  40. out.write("\r\n");
  41. out.write("\t</body>\r\n");
  42. out.write("</html>");
  43. } catch (Throwable t) {
  44. if (!(t instanceof SkipPageException)){
  45. out = _jspx_out;
  46. if (out != null && out.getBufferSize() != 0)
  47. out.clearBuffer();
  48. if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
  49. }
  50. } finally {
  51. if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
  52. }
  53. }
  54. }

我们看到,这个类继承了org.apache.jasper.runtime.HttpJspBase,具体HttpJspBase类的tomcat的源码如下:

根据时序图,首先调用service方法,然后service方法内部调用_jspService抽象方法,此方法并没有实现,故继承它的HelloWorld_jsp.java类实现。

  1. package org.apache.jasper.runtime;
  2. import java.io.IOException;
  3. import javax.servlet.ServletConfig;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import javax.servlet.jsp.HttpJspPage;
  9. import javax.servlet.jsp.JspFactory;
  10. import org.apache.jasper.compiler.Localizer;
  11. /**
  12. * This is the super class of all JSP-generated servlets.
  13. *
  14. * @author Anil K. Vijendran
  15. */
  16. public abstract class HttpJspBase
  17. extends HttpServlet
  18. implements HttpJspPage
  19. {
  20. protected HttpJspBase() {
  21. }
  22. public final void init(ServletConfig config)
  23. throws ServletException
  24. {
  25. super.init(config);
  26. jspInit();
  27. _jspInit();
  28. }
  29. public String getServletInfo() {
  30. return Localizer.getMessage("jsp.engine.info");
  31. }
  32. public final void destroy() {
  33. jspDestroy();
  34. _jspDestroy();
  35. }
  36. /**
  37. * Entry point into service.
  38. */
  39. public final void service(HttpServletRequest request, HttpServletResponse response)
  40. throws ServletException, IOException
  41. {
  42. _jspService(request, response);
  43. }
  44. public void jspInit() {
  45. }
  46. public void _jspInit() {
  47. }
  48. public void jspDestroy() {
  49. }
  50. protected void _jspDestroy() {
  51. }
  52. public abstract void _jspService(HttpServletRequest request,
  53. HttpServletResponse response)
  54. throws ServletException, IOException;
  55. }

如果:

让jsp既用java代码产生动态数据,又做美化会导致jsp的职责过重且页面难以维护。

让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。

总结:

不管是JSP还是Servlet,都可以用于开发动态web资源(学习的共同点)。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用(不同点,也可以说发挥各自优势!其中,JSP对于程序员来说省去了在后台手动拼接html代码的过程)。

因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做,这样职责单一,容易维护也正符合我们软件设计中的分层与单一职责等思想。

其实我们学习的各类技术以及各种设计模式,它们的出现或形成都是软件设计思想的一种体现!

JSP实现原理的更多相关文章

  1. jsp学习--JSP运行原理,九大隐式对象和JSP常用标签

    一.JSP运行原理 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet ...

  2. JSP JSP工作原理 JSP语法 JSP声明 JSP注释 JSP指令 jsp九大隐式/内置对象

    1 什么是JSP   1)为什么说,Servlet是一个动态Web开发技术呢?     Servlet是基于服务端的一种动态交互技术,     HttpServletRequest表示客户端到服务端的 ...

  3. JavaWeb(二)jsp运行原理,九大内置对象

    JSP运行原理: 每个JSP页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ...

  4. JSP基本语法总结【1】(jsp工作原理,脚本元素,指令元素,动作元素)

    时隔半年,回头对jsp复习整理一下,温故而知新. jsp工作原理: jsp服务器管理jsp页面分两个阶段:转换阶段(translation phase)和执行阶段(execution phase). ...

  5. Unit04: JSP基本语法 、 JSP运行原理

    Unit04: JSP基本语法 . JSP运行原理 hello.jsp <%@page pageEncoding="utf-8"%> <!doctype html ...

  6. JSP以及JSP解析原理

    什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写htm ...

  7. JSP的原理

    一.什么是JSP JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大特点在于,写JSP就行html, ...

  8. JSP工作原理

    一.历史 JSP是Servlet的扩展,JSP没出现之前,就已经出现了Servlet技术.Servlet是利用了"输出流",动态的生成了HTML页面.包括 每一个HTML标签和所有 ...

  9. 你也可以当面霸-Servlet与JSP的原理及特点

    既然是面试系列,就是面试官和应聘者之间的对话.本文是采用一问一答的形式呈现给读者的,这样能有一个明确的考察点,不像理论知识那么枯燥. 01.什么是Servlet技术 Servlet是和平台无关的服务器 ...

  10. JSP学习——原理

    JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术.   JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比 ...

随机推荐

  1. JZOJ.5246【NOIP2017模拟8.8】Trip

    Description        多年之后,worldwideD厌倦竞争,隐居山林.       他的家乡开始发展起了旅游业,在一条很长的主干道上,有N个旅游景点,按顺序编号为1到N.根据游客们网 ...

  2. 【BZOJ4345】[POI2016]Korale 堆(模拟搜索)

    [BZOJ4345][POI2016]Korale Description 有n个带标号的珠子,第i个珠子的价值为a[i].现在你可以选择若干个珠子组成项链(也可以一个都不选),项链的价值为所有珠子的 ...

  3. Java String.replaceAll() 与后向引用(backreference)

    问题 昨天看到一篇博文,文中谈到一道 Java 面试题: 给定一字符串,若该字符串中间包含 "*",则删除该 "*":若该字符串首字符或尾字符为 "* ...

  4. [LintCode] 有效回文串

    class Solution { public: /** * @param s A string * @return Whether the string is a valid palindrome ...

  5. JS中:数组和二维数组、MAP、Set和枚举的使用

    1.数组和二维数组:   方法一: var names = ['Michael', 'Bob', 'Tracy']; names[0];// 'Michael' 方法二: var mycars=new ...

  6. Java模拟并发

    =========================one============================= public class Bingfa { public static void m ...

  7. 解决scipy安装(pip install scipy)失败,以及其他问题

    解决scipy安装(pip install scipy)失败,以及其他问题 解决: 1.在scipy官方库中并没有适合Windows的python3.6相关版本,故需要在网址http://www.lf ...

  8. npm的本地模式与全局模式

    关于npm的本地模式和全局模式的总结: npm install命令就是采用本地模式,即把包安装到当前目录的node_modules子目录下:npm [install/i] [package_name] ...

  9. 使用maven搭建SSM框架

    使用maven搭建SSM框架,首先得准备好maven环境. 搭建maven环境 第一步:下载maven http://maven.apache.org/download.cgi 下载后解压就可以了. ...

  10. Kubernetes初探:原理及实践应用

    总体概览 如下图所示是我初步阅读文档和源代码之后整理的总体概览,基本上可以从如下三个维度来认识Kubernetes. 操作对象 Kubernetes以RESTFul形式开放接口,用户可操作的REST对 ...