JSP编译成Servlet(一)语法树的生成——语法解析
一般来说,语句按一定规则进行推导后会形成一个语法树,这种树状结构有利于对语句结构层次的描述。同样Jasper对JSP语法解析后也会生成一棵树,这棵树各个节点包含了不同的信息,但对于JSP来说解析后的语法树比较简单,只有一个父节点和n个子节点。例如node1是表示形如<!-- 字符串 -->的注释节点,节点里面包含了一个表示注释字符串的属性;而node2则可能是表示形如<%= a+b %>的表达式节点,节点里面包含一个表示表达式的属性,同样地其他节点可能表示JSP的其他语法,有了这棵树我们就可以很方便地生成对应的Servlet。
现在看看怎样解析生成这棵树的,
①首先定义树数据结构,其中parent指向父节点,nodes是此节点的子节点,且nodes应该是有序的列表,这样能保证与解析顺序一致。另外由于每个节点的属性不同,Node类只提供公共的部分属性,对于不同节点其他属性需要继承Node额外实现。
public class Node {
private Node parent;
private List<Node> nodes;
private String text;
private Attributes attrs;
}
public class RootNode{}
public class CommentNode{}
public class PageNode{}
public class IncludeNode{}
public class TaglibNode{}
②其次需要一个读取JSP文件的工具类,此工具类主要提供对JSP文件的字符操作,其中有个cursor变量用于表示目前解析位置,主要的方法则包括判断是否到达文件末尾的hasMoreInput方法,获取下个字符的nextChar方法,获取某个范围内的字符组成的字符串getText方法,匹配是否包含某字符串的matches方法,跳过空格符的skipSpaces方法,以及跳转到某个字符串的skipUntil方法。有了这些辅助操作就可以开始读取解析语法了。
public class JspReader{
private int cursor;
public int getCursor(){ return cursor ; }
boolean hasMoreInput(){...}
public int nextChar(){...}
public String getText(int start,int end){...}
boolean matches(String string){...}
int skipSpaces(){...}
int skipUntil(String limit){...}
}
③需要一个JSP语法解析器对JSP进行解析,这里为了简单说明只解析<!-- .... -->注释语法、<@page .../%>页面指令、<%@include.../%>包含指令、<%@taglib.../%>标签指令。假设对index.jsp进行语法解析,匹配到<%--则表示注释语法,获取其中的注释文字并创建commentNode节点作为根节点的子节点,如果匹配到<%@则有三种可能,所以需要进一步解析,即对应页面指令、包含指令和标签指令等的解析。最后解析出来的就是如图所示的一棵语法树。
public class Parser{
public RootNode parse(){
JspReader reader = new JspReader("index.jsp");
RootNode root = new RootNode();
while (reader.hasMoreInput()) {
if (reader.matches("<%--")) {
int start = reader.getCursor();
reader.skipUntil("--%>");
int end = reader.getCursor();
CommentNode commentNode = new CommentNode ();
commentNode.setText(reader.getText(start, stop));
commentNode.setParent(parent);
parent.getList().add(commentNode);
} else if (reader.matches("<%@")) {
if (reader.matches("page")) {
解析<%@page.../%>里面的属性生成attrs
PageNode pageNode = new PageNode ();
pageNode.setAttributes(attrs);
pageNode.setParent(parent);
parent.getList().add(pageNode);
} else if (reader.matches("include")) {
解析<%@include.../%>里面的属性生成attrs
IncludeNode includeNode = new IncludeNode ();
includeNode.setAttributes(attrs);
includeNode.setParent(parent);
parent.getList().add(includeNode);
} else if (reader.matches("taglib")) {
解析<%@taglib.../%>里面的属性生成attrs
TaglibNode taglibNode = new TaglibNode ();
taglibNode.setAttributes(attrs);
taglibNode.setParent(parent);
parent.getList().add(taglibNode);
}
}
}
return root;
}
}
喜欢java的同学可以交个朋友
JSP编译成Servlet(一)语法树的生成——语法解析的更多相关文章
- JSP编译成Servlet(四)JSP与Java行关系映射
我们知道java虚拟机只认识class文件,要在虚拟机上运行就必须要遵守class文件格式,所以JSP编译成servlet后还需要进一步编译成class文件,但从JSP文件到java文件再到class ...
- JSP编译成Servlet(三)JSP编译后的Servlet
JSP编译后的Servlet类会是怎样的呢?他们之间有着什么样的映射关系?在探讨JSP与Servlet之间的关系时先看一个简单的HelloWorld.jsp编译成HelloWorld.java后会是什 ...
- JSP编译成Servlet(二)语法树的遍历——访问者模式
语法树可以理解成是一种数据结构,假如某些语句已经被解析成一棵语法树,那么接下来就是要对此语法树进行处理,但考虑到不将处理操作与数据结构混合在一块,我们需要一种方法将其分离.其实对于语法树的处理最典型的 ...
- JSP编译成Servlet(五)JDT Compiler编译器
通过JSP编译器编译后生成了对应的java文件,接下去要把Java文件编译成class文件.对于这部分完全没有必要重新造轮子,常见的优秀编译工具有Eclipse JDT Java编译器和Ant编译器. ...
- jsp页面编译成Servlet类文件
package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.js ...
- JSP转译成Servlet详细过程【转】
JSP转译成Servlet详细过程 JSP是Servlet的扩展,在没有JSP之前,就已经出现了Servlet技术.Servlet是利用输出流动态生成HTML页面,包括每一个HTML标签和每个在HTM ...
- jsp编译原理
jsp运行时都要先转换成servlet,使用tomcat时会在tomcat安装目录下的work生成一系列的运行的项目文件夹,文件下面含有.java文件和编译后的.class文件.jsp最终转化为ser ...
- JSP编译指令、JSP动作指令
JSP编译指令:通过指令中的属性配置来向JSP容器发出指令,用来控制JSP页面的某些特征 JSP指令格式:<%@ 指令名 [一个或多个指令属性]%> 1.page:用于对JSP页面中的 ...
- JSP转译成Servlet详细过程
很多人都会认为JSP的执行性能会和Servlet相差很多,其实执行性能上的差别只在第一次的执行.因为JSP在执行第一次后,会被编译成 Servlet的类文件,即.class,当再重复调用执行时,就直接 ...
随机推荐
- gravity和layout_gravity的区别
一.gravity和layout_gravity相同处 两者都是设置对齐方式的属性.内部的属性值相同. 根据英文意思也能理解其中的意思.如center_horizontal表示在水平方向上的位置为中间 ...
- 一个使用 Web Components 的音乐播放器: MelodyPlayer
先上效果预览: Web Components 首先,什么是 Web Components ? MDN 给出的定义是: Web Components 是一套不同的技术,允许您创建可重用的定制元素(它们的 ...
- Spring完全基于Java配置和集成Junit单元测试
要点: 配置继承WebApplicationInitializer的类作为启动类,相当于配置web.xml文件 使用@Configuration注解一个类,在类中的方式使用@Bean注解,则表名该方法 ...
- git清空某个文件的历史版本
比如你要清空文件private.ini git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch priva ...
- 【Unity Shader】新书封面 — Low Polygon风格的渲染
写在前面 最近又开心又担心,因为我的书马上就要上市了,开心当然是因为等了这么久终于可以如愿了,担心是因为不少人对它的期待都很大,我第一次写书,能力也有限,不知道能不能让大家满意,让大家也都喜欢上它.不 ...
- Gazebo機器人仿真學習探索筆記(六)工具和实用程序
Gazebo附带了许多工具和实用程序. 这些教程说明了这些可用的工具,以及如何使用它们. 主要有: 1 记录和播放 2 日志过滤 3 应用力/扭矩 4 HDF5数据集 官网介绍通俗具体,非常容易,请参 ...
- [转]django-registration quickstart
Basic configuration and use--------------------------- Once installed, you can add django-registrati ...
- Java异常处理-----finally
finally 1: 实现方式一: try{ // 可能发生异常的代码 } catch( 异常类的类型 e ){ // 当发生指定异常的时候的处理代码 }catch- 比较适合用于专门的处理异常的代码 ...
- UIKit中ImageView动画堆叠显示的微调整
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 网上看到一个PackingList项目(如果需要源代码可以Q我 ...
- 探究java接口中的变量与方法
关于变量 java接口里的变量都是默认 pubic static final的 为啥? public 接口得能被所有对象调用 static 这个变量是属于接口本身,而不是实现了接口的对象的 具体来说 ...