JSP编译成Servlet(一)语法树的生成——语法解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
云解析DNS,个人版 1个月
全局流量管理 GTM,标准版 1个月
简介: 一般来说,语句按一定规则进行推导后会形成一个语法树,这种树状结构有利于对语句结构层次的描述。同样Jasper对JSP语法解析后也会生成一棵树,这棵树各个节点包含了不同的信息,但对于JSP来说解析后的语法树比较简单,只有一个父节点和n个子节点。

一般来说,语句按一定规则进行推导后会形成一个语法树,这种树状结构有利于对语句结构层次的描述。同样JasperJSP语法解析后也会生成一棵树,这棵树各个节点包含了不同的信息,但对于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;

    }

}



点击订购作者《Tomcat内核设计剖析》




目录
相关文章
|
1月前
|
存储 SQL 消息中间件
ClickHouse(12)ClickHouse合并树MergeTree家族表引擎之AggregatingMergeTree详细解析
AggregatingMergeTree是ClickHouse的一种表引擎,它优化了MergeTree的合并逻辑,通过将相同主键(排序键)的行聚合为一行并存储聚合函数状态来减少行数。适用于增量数据聚合和物化视图。建表语法中涉及AggregateFunction和SimpleAggregateFunction类型。插入数据需使用带-State-的聚合函数,查询时使用GROUP BY和-Merge-。处理逻辑包括按排序键聚合、在合并分区时计算、以分区为单位聚合等。常用于物化视图配合普通MergeTree使用。查阅更多资料可访问相关链接。
84 4
|
1月前
|
存储 SQL 算法
ClickHouse(13)ClickHouse合并树MergeTree家族表引擎之CollapsingMergeTree详细解析
CollapsingMergeTree是ClickHouse的一种表引擎,它扩展了`MergeTree`,通过折叠行来优化存储和查询效率。当`Sign`列值为1和-1的成对行存在时,该引擎会异步删除除`Sign`外其他字段相同的行,只保留最新状态。建表语法中,`sign`列必须为`Int8`类型,用来标记状态(1)和撤销(-1)。写入时,应确保状态和撤销行的对应关系以保证正确折叠。查询时,可能需要使用聚合函数如`sum(Sign * x)`配合`GROUP BY`来处理折叠后的数据。使用`FINAL`修饰符可强制折叠,但效率较低。系列文章提供了更多关于ClickHouse及其表引擎的详细解析。
39 1
|
1月前
|
前端开发 小程序 Java
深入解析Java Servlet与JSP:构建高效服务器端应用
【6月更文挑战第23天】Java Servlet和JSP是Web开发的关键技术,用于构建高效服务器端应用。Servlet处理HTTP请求,执行业务逻辑,而JSP专注于动态HTML生成。两者结合,借助MVC架构,实现逻辑与视图分离,提高代码可读性和性能。尽管有新框架出现,Servlet和JSP仍是许多项目的基础。
|
1月前
|
关系型数据库 MySQL 数据库连接
蓝易云 - PHP基本语法解析与应用指南
以上只是PHP基本语法的简要概述,要深入了解和掌握PHP,你需要阅读更多的教程和参考资料,并通过实践来提高你的技能。
25 2
|
1月前
深入解析AVL树:高效实现二叉平衡搜索树(2)
深入解析AVL树:高效实现二叉平衡搜索树
8 1
|
1月前
|
存储
深入解析AVL树:高效实现二叉平衡搜索树
深入解析AVL树:高效实现二叉平衡搜索树
10 1
|
1月前
|
存储 安全 Java
深入解析Java HashMap的高性能扩容机制与树化优化
深入解析Java HashMap的高性能扩容机制与树化优化
24 1
|
1月前
|
传感器 存储 SQL
ClickHouse(15)ClickHouse合并树MergeTree家族表引擎之GraphiteMergeTree详细解析
GraphiteMergeTree是ClickHouse用于优化Graphite数据存储和汇总的表引擎,适合需要瘦身和高效查询Graphite数据的开发者。它基于MergeTree,减少存储空间并提升查询效率。创建表时需包括Path、Time、Value和Version列。配置涉及pattern、regexp、function和retention,用于指定聚合函数和数据保留规则。文章还提供了建表语句示例和相关资源链接。
30 1
|
23天前
|
JavaScript
js 解析和操作树 —— 获取树的深度、提取并统计树的所有的节点和叶子节点、添加节点、修改节点、删除节点
js 解析和操作树 —— 获取树的深度、提取并统计树的所有的节点和叶子节点、添加节点、修改节点、删除节点
30 0
|
1月前
|
测试技术 C语言
数据结构学习记录——树习题—Tree Traversals Again(题目描述、输入输出示例、解题思路、解题方法C语言、解析)
数据结构学习记录——树习题—Tree Traversals Again(题目描述、输入输出示例、解题思路、解题方法C语言、解析)
25 1

推荐镜像

更多