百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

一文弄懂Jasper引擎编译JSP文件的分析说明

yuyutoo 2024-11-06 21:00 6 浏览 0 评论


基本概念

  • 对于基于JSPWeb应用,可以在JSP页面直接编写Java代码,添加第三方库,使用EL表达式.但是最终输出到客户端浏览器的都是标准的HTML页面,包括js,css等等.并不包含Java相关的语法 .JSP可以看作是一种运行在服务器端的脚本,最终以HTML页面方式响应给客户端
  • 使用Tomcat中的Jasper引擎将jsp文件转换为HTML页面文件:JSP本质上是一个ServletTomcat使用JasperJSP语法进行解析,生成Servlet并生成Class字节码文件用户在访问jsp文件时,会访问转换后的Servlet, 最终的访问结果以HTML页面的方式直接响应在浏览器端在运行过程中 ,Jasper引擎会检测jsp文件是否修改,如果修改则重新编译jsp文件

编译方式

运行时编译

  • Tomcat不会在启动Web应用时自动编译JSP文件,而是在客户端第一次请求时,才编译需要访问的JSP文件

编译过程

  • Tomcat在默认的web.xml中配置了org.apache.jasper.servlet.JspServlet, 用于处理所有的 .jsp.jspx结尾的请求
  • JspServlet的实现就是运行编译时的入口
<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>
复制代码
  • JspServlet请求处理流程:

编译结果

  • 如果在tomcat/conf/web.xml 中配置了参数scratchdir,jsp编译后的结果会输出到配置的目录下:
<init-param>
	<param-name>scratchdir</param-name>
	<param-value>e:/jsp/</param-value>
</init-param>
复制代码
  • 如果没有配置该选项,则jsp编译后的结果,将会存放在Tomcat的安装目录的work/Catalina/localhost/ 目录下

预编译

  • 预编译: 直接在web项目启动时,一次性将web应用用的所有jsp页面一次性编译完成.这样在web项目运行过程中,可以不再需要实时编译,而是直接调用jsp页面对应的servlet完成请求处理,从而提升系统性能
  • 要想进行预编译,必须首先确保下载并安装了Apache Ant
  • Tomcat中提供了一个shell程序JspC用于支持jsp编译,而且在Tomcat安装目录下提供了一个catalina-tasks.xml文件声明了Tomcat支持的Ant任务,这样很容易使用Ant来执行jsp的预编译

编译原理

代码分析

  • 生成的Java文件的类名为index_jsp.java, 继承自org.apache.jasper.runtime.HttpJspBase,该类是HttpServlet的子类.所以jsp的本质就是一个servlet
  • 属性 _jspx_denpendants保存了当前jsp页面依赖的资源,包含引入的外部jsp页面,导入的标签,标签所在的jar包.便于后续处理过程中使用. 比如以Map形式保存了每个资源的上次修改时间便于重新编译检测
  • 属性 _jspx_imports_packages存放导入的java包,默认导入javax.servlet, javax.servlet.http, javax.servlet.jsp
  • 属性 _jspx_imports_classes存放导入的类 ,jsp页面中通过import标签导入的类都会包含在该集合 . _jspx_import_packages_jspx_import_classes属性主要用于配置EL引擎上下文
  • 请求处理由 _jspService方法完成,在父类HttpJspBase中的service方法通过模板方法模式,调用了子类的 _jspService方法
  • _jspService方法中定义了几个重要的局部变量 : pageContext, Session, application, config, out, page. 因为整个页面的输出都是由 _jspService方法完成,因此这些变量和参数会对整个jsp页面生效. 这个就是在jsp页面中能够使用变量的原因
  • jsp页面中指定文档类型的page变标签的值最终作为response.setContentType() 使用
  • 对于生成的html文件的静态内容,调用out.write() 输出
  • 对于 <% ..%> 标签中的代码,直接转换为Servlet类中的代码,如果在代码中嵌入了静态文件,同样会调用out.write() 输出

编译流程

  • Jasper的编译流程主要包括代码生成和编译两部分
  • Compiler通过一个PageInfo对象保存jsp页面编译过程中的各种配置. 这些配置可以是来自于web应用的初始化参数,也可以是来自于jsp页面的标签指令配置,比如page, include
  • 调用ParseController解析标签指令节点,验证标签指令是否合法,同时将配置信息保存到PageInfo中,用于控制代码生成
  • 调用ParseController解析整个jsp页面,由于jsp是逐行解析,所以会对每一行创建一个具体的Node对象,比如静态文本TemplateText, Java代码Scriptlet, 定制标签CustomTag, Include标签指令IncludeDirective
  • 验证标签指令外的其余节点的合法性. 比如脚本,定制标签 ,EL表达式等
  • 获取标签指令以外的其余节点的页面配置信息
  • 编译并加载当前jsp页面依赖的标签
  • 对于jsp页面的EL表达式,生成对应的映射函数
  • 生成jsp页面对应的servlet源代码
  • 代码生成完成后 ,Compiler会生成SMAP信息. 如果配置生成了SMAP信息 ,Compiler则会在编译阶段将SMAP信息写到class文件中
  • 在编译阶段 ,Compiler的两个实现AntCompilerJDTCompiler分别调用相关框架的API进行源代码解析AntCompiler通过构造一个Antjavac任务完成编译JDTCompiler通过调用org.eclipse.jdt.internal.compiler.Compiler完成编译

相关推荐

.NET 奇葩问题调试经历之3——使用了grpc通讯类库后,内存一直增长......

...

全局和隐式 using 指令详解(全局命令)

1.什么是全局和隐式using?在.NET6及更高版本中,Microsoft引入了...

请停止微服务,做好单体的模块化才是王道:Spring Modulith介绍

1、介绍模块化单体是一种架构风格,代码是根据模块的概念构成的。对于许多组织而言,模块化单体可能是一个很好的选择。它有助于保持一定程度的独立性,这有助于我们在需要的时候轻松过渡到微服务架构。Spri...

ASP.NET程序集引用之痛:版本冲突、依赖地狱等解析与实战

我是一位多年后端经验的工程师,其中前几年用ASP.NET...

.NET AOT 详解(.net 6 aot)

简介AOT(Ahead-Of-TimeCompilation)是一种将代码直接编译为机器码的技术,与传统的...

一款基于Yii2开发的免费商城系统(一款基于yii2开发的免费商城系统是什么)

哈喽,我是老鱼,一名致力于在技术道路上的终身学习者、实践者、分享者!...

asar归档解包(游戏arc文件解包)

要学习Electron逆向,首先要有一个Electron开发的程序的发布的包,这里就以其官方的electron-quick-start作为例子来进行一下逆向的过程。...

在PyCharm 中免费集成Amazon CodeWhisperer

CodeWhisperer是Amazon发布的一款免费的AI编程辅助小工具,可在你的集成开发环境(IDE)中生成实时单行或全函数代码建议,帮助你快速构建软件。简单来说,AmazonCodeWhi...

2014年最优秀JavaScript编辑器大盘点

1.WebstormWebStorm是一种轻量级的、功能强大的IDE,为Node.js复杂的客户端开发和服务器端开发提供完美的解决方案。WebStorm的智能代码编辑器支持JavaScript,...

基于springboot、tio、oauth2.0前端vuede 超轻量级聊天软件分享

项目简介:基于JS的超轻量级聊天软件。前端:vue、iview、electron实现的PC桌面版聊天程序,主要适用于私有云项目内部聊天,企业内部管理通讯等功能,主要通讯协议websocket。支持...

JetBrains Toolbox推出全新产品订阅授权模式

捷克知名软件开发公司JetBrains最为人所熟知的产品是Java编程语言开发撰写时所用的集成开发环境IntelliJIDEA,相信很多开发者都有所了解。而近期自2015年11月2日起,JetBr...

idea最新激活jetbrains-agent.jar包,亲测有效

这里分享一个2019.3.3版本的jetbrains-agent.jar,亲测有效,在网上找了很多都不能使用,终于找到一个可以使用的了,这里分享一下具体激活步骤,此方法适用于Jebrains家所有产品...

CountDownTimer的理解(countdowntomars)

CountDownTimer是android开发常用的计时类,按照注释中的说明使用方法如下:kotlin:object:CountDownTimer(30000,1000){...

反射为什么性能会很慢?(反射时为什么会越来越长)

1.背景前段时间维护一个5、6年前的项目,项目总是在某些功能使用上不尽人意,性能上总是差一些,仔细过了一下代码发现使用了不少封装好的工具类,工具类里面用了好多的反射,反射会影响到执行效率吗?盲猜了一...

btrace 开源!基于 Systrace 高性能 Trace 工具

介绍btrace(又名RheaTrace)是抖音基础技术团队自研的一款高性能AndroidTrace工具,它基于Systrace实现,并针对Systrace不足之处加以改进,核心改进...

取消回复欢迎 发表评论: