JSP概述与运行原理

这篇文章犹豫了很久,还是觉得提起笔来,好好地来讲解下JSP。

相信大家也都有所听闻,不管是视频上、博客中、公司里,都有着这么一个声音:这都21世纪二十年代,JSP这种技术还有什么学习的价值。诚然,这句话是有一定的道理的,随着技术的不断创新和软件设计思想的变革,首先是Velocity、Freemarker、Thymeleaf等模板引擎的出现来挤压JSP的空间,而前后端分离的架构彻底的让JSP失去了生存的土壤。于是一代传奇,早期Web开发中的旗手,慢慢的淡出了开发人员的视野。

但是,回过头来,我们再来看JSP是否还需要学这个问题。首先一点就是,当你点开这篇文章,那么JSP对你就是有用的,那么在这里来猜测下你的身份。

​可能一:学生、Web开发小白,在初学时进行简单的项目开发时,往往所有的工作都是一个人完成的,如果采用前后端分离,那么json、ajax、jQuery、Vue、Rest等等技术,都是你可能需要直面的问题,那么可能真的要走一条从入门到放弃的道路了,而JSP则可以帮我们将上述工作进行简化,所有的事全包在JSP身上了,让你可以把更多的精力专于一点,而不是被繁杂的技术吓到。

​可能二:开发人员、在维护一个老项目,JSP与ASP在上世纪90年代末与本世纪前十年,一直程序员进行Web开发的首选,并且其宿主语言Java最后还干死了C#,所以许多早期的项目都是使用JSP开发的,并且看不到重构的希望,那么你也只能继续使用JSP来继续进行功能的开发或者bug修复了。

​可能三:吃瓜群众。

资源分配图

​闲话聊完了,下面我们就来学下JSP的相关知识。

1.什么是JSP

​在Web开发中,当我们访问Servlet,不可避免的要对用户的请求进行响应,在前面我们知道,可以通过response向前端输出html页面,但是这样,需要写许多的输出语句,并且许多静态内容会和动态内容糅杂在一起,导致Servlet程序变得非常臃肿。为此,Sun公司在Servlet的基础上,推出了JSP技术。

资源分配图

​那JSP到底是啥呢?JSP的全称为Java服务端页面,英文全称为Java Server Pages,是一种以Servlet为基础的动态网页开发技术。在JSP文件,HTML代码嵌入Java代码,网页中的静态内容主要由Html代码来完成,Java代码用来实现网页中的动态内容的显示。

​JSP技术其宿主语言是Java,因此其可以自动的继承Java的特征,主要如下:

  • 跨平台:使用JSP的Web应用,也是可以跨平台的,只要操作系统中安装了JDK和Web服务器即可,JSP可以和Java同样的实现,一次编译多处运行;
  • **预编译:**预编译就是在用户第一次通过浏览器访问JSP页面时,服务器将对JSP页面代码进行编译,并且仅执行一次编译。编译好的代码将被保存,在用户下一次访问时,会直接执行编译好的代码;
  • **组件重用:**JSP中可以引用Java代码,即可以在JSP中直接引用我们写的Service层的方法等等,不过这里不建议如此操作。

2.一个JSP页面包含的内容

​创建一个JSP页面很简单,我们这里就不在赘述了。那一个JSP页面,应该包含哪些内容呢?

资源分配图
  • JSP指令:比如页面第一行的page指令,其可以对本JSP页面上的某些特性进行描述,如指明语言、页面编码方式、MIME类型等,当然还可以指定页面的其他属性;
  • HTML:JSP页面中完全兼容HTML,包括js文件、css文件的引入,script标签等;
  • Java脚本:也称为JSP脚本,即在JSP页面中嵌入Java代码,主要有三种形式,<% ... %>、<%! ... %>、<%= ... %>
  • JS脚本:这本身也是HTML中的用法,这里提出来就是为了和上面的Java脚本做一个区别,JSP页面中的许多交互,比如点击事件、alert等操作,仍然是有JS来完成的;
  • 九大内置对象:也称之为隐式对象,在JSP页面中,我们可以很方便的使用一些对象,如out、request、session等。

3.JSP运行原理

​我们在之前的一篇文章中,讲到缺省的urlPattern时,不知道还记得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>
  <url-pattern>*.jspx</url-pattern>
</servlet-mapping>

​我们可以看到,jsp页面是有指定的Servlet来进行处理的,JspServlet可以理解为JSP引擎(容器),其可以将一个JSP文件转换成一个Servlet,我们可以理解为比较特殊的"编译"。

资源分配图

​通过上图,我们来对JSP的运行过程做更具体的描述:

  1. 客户端发出请求,访问JSP页面资源;
  2. 如果页面是第一次被访问,JSP容器会将JSP文件转换成一个Java文件,即一个Java Servlet程序,如果转换过程发生异常,则终止,并抛出异常;
  3. 如果转换成功,则由Servlet容器将其加载至内存(执行init方法),并根据urlPattern来进行调用(调用service方法),处理用户对JSP页面的请求;
  4. 如果JSP页面在项目运行过程中被修改了,则服务器会根据设置决定是否进行重新编译(默认重新编译),如果需要重新编译,则将新生成的Servlet加载入内存,这也是为什么我们在eclipse中开发时,JSP文件修改后不需要重启项目(idea中需要自行设置);
  5. 当用户的JSP请求被对应JSP的Servlet处理完成后,响应由对应的JSP容器进行接收,并将HTML格式的响应信息发送回客户端。

​下面我们通过一个例子来讲解下上面的流程,首先我们启动项目,我们可以先行查看下Tomcat安装目录/work/Catalina/localhost/FirstProject/org/apache/jsp文件夹下,其中为空,没有任何文件,当我们在浏览器中访问jspDemo.jsp后,我们可以看到,此目录中多了如下两个文件:

资源分配图

​其中的jspDemo_jsp.java即为JSP容器将jspDemo.jsp转换得到的,其中的部分代码如下:

public final class jspDemo_jsp extends org.apache.jasper.runtime.HttpJspBase
  implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
  //...
  public void _jspInit() {
  }

  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=UTF-8");
      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;
			//将jsp中的html进行输出
      out.write("\n");
      out.write("<!DOCTYPE html>\n");
      out.write("<html>\n");
      out.write("<head>\n");
      out.write("<meta charset=\"UTF-8\">\n");
      out.write("<title>Insert title here</title>\n");
      out.write("<script src=\"./js/jquery-3.2.1.min.js\"></script>\n");
      out.write("</head>\n");
      out.write("<body>\n");
      out.write("\t<h1>这是HTML标签</h1>\n");
      out.write("\t");
      
 			//java语句直接嵌入
      out.print("<h1>这是Java输出的标签</h1>");
      //注释
      if(true){
        out.print("<h1>还可嵌入Java语句</h1>");
      }
	
      out.write("\n");
      out.write("\t\n");
      out.write("\t<script type=\"text/javascript\">\n");
      out.write("\t\t$(document).ready(function(){\n");
      out.write("\t\t\tconsole.log(\"页面中同样可以嵌入JS脚本\");\n");
      out.write("\t\t})\n");
      out.write("\t</script>\n");
      out.write("</body>\n");
      out.write("</html>");
    } catch (java.lang.Throwable t) {
      //...
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }            
}

​从上面编译后得到的jspDemo_jsp.java可以看到,我们为何能直接在jsp页面中使用out对象,就是因为JSP会帮我们定义这些内置对象。

​对于jspDemo_jsp继承的org.apache.jasper.runtime.HttpJspBase,我们来看下其声明(Jasper Runtime jar包中),可以看到,其实HttpServlet的一个子类,也证实了JSP页面会被JSP引擎转换成一个Servlet。

public abstract class HttpJspBase extends HttpServlet implements HttpJspPage{
  //...
}

4.小结

​JSP虽然在慢慢的退出Web开发的舞台,但是其留下的风景还是非常让人迷醉的,而且其更适合新手学习,所以在短期内,Java Web的学习中,JSP仍然是很重要的一块。本文仅是简单的介绍了JSP的概念,和JSP页面中可以包含的内容,后续我们会对JSP进行详细的讲解。


​又到了分隔线以下,本文到此就结束了,本文内容全部都是由博主自己进行整理并结合自身的理解进行总结,如果有什么错误,还请批评指正。

​Java web这一专栏会是一个系列博客,喜欢的话可以持续关注,如果本文对你有所帮助,还请还请点赞、评论加关注。

​有任何疑问,可以评论区留言。

展开阅读全文
©️2020 CSDN 皮肤主题: 像素格子 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值