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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 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内核设计剖析》




目录
相关文章
|
30天前
|
Java 容器
【学习笔记】Jsp与Servlet技术
【学习笔记】Jsp与Servlet技术
61 0
|
4天前
|
自然语言处理 编译器 Linux
|
10天前
|
自然语言处理 编译器 Linux
告别头文件,编译效率提升 42%!C++ Modules 实战解析 | 干货推荐
本文中,阿里云智能集团开发工程师李泽政以 Alinux 为操作环境,讲解模块相比传统头文件有哪些优势,并通过若干个例子,学习如何组织一个 C++ 模块工程并使用模块封装第三方库或是改造现有的项目。
|
1月前
|
Java 编译器
解析用GraalVm编译的class文件
这篇文章介绍了如何使用`javap`工具反编译由GraalVM编译的`.class`文件,详细展示了`javap`的用法和输出内容,包括类声明、版本信息、访问标志、类层次结构、接口、字段、方法、属性以及常量池等信息。
11 0
解析用GraalVm编译的class文件
|
3月前
|
SQL Java 数据库
jsp中使用Servlet查询SQLSERVER数据库中的表的信息,并且打印在屏幕上
该博客文章介绍了在JSP应用中使用Servlet查询SQL Server数据库的表信息,并通过JavaBean封装图书信息,将查询结果展示在Web页面上的方法。
jsp中使用Servlet查询SQLSERVER数据库中的表的信息,并且打印在屏幕上
|
3月前
|
缓存 安全 Java
Java服务器端技术:Servlet与JSP的集成与扩展
Java服务器端技术:Servlet与JSP的集成与扩展
32 3
|
3月前
|
存储 缓存 前端开发
Servlet与JSP在Java Web应用中的性能调优策略
Servlet与JSP在Java Web应用中的性能调优策略
31 1
|
3月前
|
供应链 前端开发 Java
JSP+servlet+mybatis+layui服装库存管理系统(大三上学期课程设计)
这篇文章通过一个服装库存管理系统的实例,展示了在Spring Boot项目中使用Ajax、JSON、layui、MVC架构和iframe等技术,涵盖了注册登录、权限管理、用户管理、库存管理等功能,并提供了系统运行环境和技术要求的详细说明。
JSP+servlet+mybatis+layui服装库存管理系统(大三上学期课程设计)
|
3月前
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
基于Servlet和JSP的Java Web应用开发指南
39 0
|
3月前
|
前端开发 安全 Java
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
27 0

推荐镜像

更多