Bootstrap

从零开始看poi-tl源码

poi-tl 源码介绍-主要类介绍

这次源码只做学习参考,来源poi-tl文档,git仓库,建议了解poi-tl的同学再来观看 q(≧▽≦q)

官方学习文档地址:https://deepoove.com/poi-tl/

git源码仓库地址:https://github.com/Sayi/poi-tl

下列几个类是poi-tl比较重要的类介绍

  1. XWPFTemplate类
    • 最核心的类,启动第一步。
  2. NiceXWPFDocument类
    • 继承自XWPFDocument,对Word文档进行扩展和处理。
  3. Configure类
    • 用于配置poi-tl的相关参数,例如标签的前缀后缀等。
  4. TemplateResolver类
    • 解析Word文档模板,识别模板中的标签等。
  5. DefaultRender类
    • 默认的渲染器,根据数据模型填充模板中的标签。
  6. MetaTemplate类
    • 代表模板中的元素,例如段落、表格等。

XWPFTemplate类主要方法介绍

  • compile() 方法:poi-tl是最核心的方法,也是启动第一步
  • render()方法:将数据模型渲染到模板中的标签位置。
  • write()方法:将渲染好数据的模板写入到输出流。
  • writeAndClose()方法:将渲染好数据的模板写入到输出流并关闭相关资源。
  • reload()方法:重新加载模板。

我们来看XWPFTemplate,XWPFTemplate.compile() 方法,poi-tl是最核心的方法,也是启动第一步。

public static XWPFTemplate compile(InputStream inputStream, Configure config) {
    try {
        //创建一个空的XWPFTemplate对象。
        XWPFTemplate template = new XWPFTemplate();
        //将传入的配置对象赋值给XWPFTemplate对象的config属性,用于设置模板的配置信息。
        template.config = config;
        //使用传入的输入流创建一个NiceXWPFDocument对象,表示模板的文档对象。
        template.doc = new NiceXWPFDocument(inputStream);
        //根据模板的配置信息创建一个TemplateResolver对象,用于解析模板。
        template.resolver = new TemplateResolver(template.config);
        //创建一个DefaultRender对象,用于渲染模板。
        template.renderer = new DefaultRender();
        //调用TemplateResolver的resolveDocument方法,解析模板文档并返回模板元素的列表,然后赋值给XWPFTemplate对象的eleTemplates属性。
        template.eleTemplates = template.resolver.resolveDocument(template.doc);
        return template;
    } catch (OLE2NotOfficeXmlFileException e) {
        logger.error("Poi-tl currently only supports .docx format");
        throw new ResolverException("Compile template failed", e);
    } catch (IOException e) {
        throw new ResolverException("Compile template failed", e);
    }
}
  1. template.config = config;

如果没有在compile function时 增加自定义config,就会使用XWPFTemplate line: 108

//XWPFTemplate line: 108
public static XWPFTemplate compile(File templateFile) {
    return compile(templateFile, Configure.createDefault());
}
//跳转到builder
public static Configure createDefault() {
    return builder().build();
}

引申出两个类,Configure和ConfigureBuilder

Configure类介绍

Configure是 poi-tl 库中用于配置模板生成和数据渲染行为的配置类。

存放RenderPolicy的Map介绍

Configure里有个四个专门存放RenderPolicy的映射,用于存储不同类型模板的渲染策略,并指定了它们的优先级顺序:

protected final Map<String, RenderPolicy> CUSTOM_POLICYS = new HashMap<String, RenderPolicy>();

protected final Map<Character, RenderPolicy> DEFAULT_POLICYS = new HashMap<Character, RenderPolicy>();

protected final Map<ChartTypes, RenderPolicy> DEFAULT_CHART_POLICYS = new EnumMap<ChartTypes, RenderPolicy>(
        ChartTypes.class);

protected final Map<Class<? extends MetaTemplate>, RenderPolicy> DEFAULT_TEMPLATE_POLICYS = new HashMap<>();
  1. CUSTOM_POLICYS

    • 该映射存储自定义模板的渲染策略。
    • 键为模板标签名(String),值为对应的渲染策略(RenderPolicy)。
    • 这些渲染策略具有最高优先级,用于处理自定义模板。
  2. DEFAULT_POLICYS

    • 该映射存储基于字符的默认模板渲染策略。
    • 键为字符(Character),通常用于标识模板的特定类型或操作,如文本、图片、表格等。
    • 值为对应的渲染策略(RenderPolicy)。
    • 这些渲染策略具有中等优先级,用于处理基于字符的模板。
IMAGE('@'),TEXT('\0'),TEXT_ALIAS('='),TABLE('#'),NUMBERING('*'),
DOCX_TEMPLATE('+'),ITERABLE_START('?'),BLOCK_END('/');
  1. DEFAULT_CHART_POLICYS
    • 该映射存储基于图表类型的默认模板渲染策略。
    • 键为图表类型(ChartTypes),如AREA、BAR、PIE等。
    • 值为对应的渲染策略(RenderPolicy)。
    • 这些渲染策略具有中等优先级,用于处理基于图表的模板。
  2. DEFAULT_TEMPLATE_POLICYS
    • 该映射存储基于元模板类的默认渲染策略。
    • 键为元模板类(Class<? extends MetaTemplate>),用于标识元模板的类型。
    • 值为对应的渲染策略(RenderPolicy)。
    • 这些渲染策略具有最低优先级,用于处理基于元模板的模板。

通过这种方式,系统可以根据模板的类型和特征选择相应的渲染策略,并根据优先级来确定使用哪种策略来处理模板。

plugin和customPolicy方法介绍

  1. plugin 方法

    public Configure plugin(char c, RenderPolicy policy) {
        DEFAULT_POLICYS.put(Character.valueOf(c), policy);
        return this;
    }
    
    • 有多个重载形式,分别用于注册不同类型模板的默认渲染策略。但一般使用char来注册就足够。
    • 注册基于**字符(char)**的默认渲染策略。
    • 这些方法将对应类型的模板与其默认的渲染策略关联起来,并将其存储在相应的策略映射中。
  2. customPolicy 方法

    public void customPolicy(String tagName, RenderPolicy policy) {
        CUSTOM_POLICYS.put(tagName, policy);
    }
    
    • 用于注册自定义的模板渲染策略。
    • 注册基于**模板标签(String)**和相应的渲染策略作为参数。
    • 将自定义的模板标签名与其对应的渲染策略关联起来,并存储在自定义策略映射中。

区别:

  • plugin 方法用于注册默认的模板渲染策略,针对预定义的模板类型或特定字符或符号。
  • customPolicy 方法用于注册自定义的模板渲染策略,针对用户自定义的模板标签名。

综合来说,plugin 方法适用于为预定义的模板类型或特定符号注册默认渲染策略,而 customPolicy 方法则适用于为用户自定义的模板标签名注册自定义渲染策略。

Configure RenderPolicy介绍

当Configure类被构造时,默认调用plugin往map增加:

Configure() {
    //文本标签,在模板中可能使用 {{text}} 这样的标签。
    plugin(GramerSymbol.TEXT, new TextRenderPolicy());
    //在模板中,可能会使用 {{text_alias}} 这样的标签来表示文本内容,而其渲染策略可能与普通的文本标签略有不同。
    plugin(GramerSymbol.TEXT_ALIAS, new TextRenderPolicy());
    plugin(GramerSymbol.IMAGE, new PictureRenderPolicy());
    plugin(GramerSymbol.TABLE, new TableRenderPolicy());
    plugin(GramerSymbol.NUMBERING, new NumberingRenderPolicy());
    //暂时没深入了解,可能是特定的渲染策略来处理 DOCX 模板的填充操作。可能涉及段落、表格、图像等元素的处理。
    plugin(GramerSymbol.DOCX_TEMPLATE, new DocxRenderPolicy());

    //用于处理多系列图表模板的填充操作。负责处理多系列图表模板的数据填充和格式化,以生成最终的文档输出。没深入了解
    RenderPolicy multiSeriesRenderPolicy = new MultiSeriesChartTemplateRenderPolicy();
    plugin(ChartTypes.AREA, multiSeriesRenderPolicy);
    plugin(ChartTypes.AREA3D, multiSeriesRenderPolicy);
    plugin(ChartTypes.BAR, multiSeriesRenderPolicy);
    plugin(ChartTypes.BAR3D, multiSeriesRenderPolicy);
    plugin(ChartTypes.LINE, multiSeriesRenderPolicy);
    plugin(ChartTypes.LINE3D, multiSeriesRenderPolicy);
    plugin(ChartTypes.RADAR, multiSeriesRenderPolicy);
    plugin(ChartTypes.SCATTER, multiSeriesRenderPolicy);

    //负责处理单系列图表模板的数据填充和格式化,以生成最终的文档输出。没深入了解
    RenderPolicy singleSeriesRenderPolicy = new SingleSeriesChartTemplateRenderPolicy();
    plugin(ChartTypes.PIE, singleSeriesRenderPolicy);
    plugin(ChartTypes.PIE3D, singleSeriesRenderPolicy);
    plugin(ChartTypes.DOUGHNUT, singleSeriesRenderPolicy);

    //表示图片模板,在文档中用于插入图片的模板。没深入了解
    plugin(PictureTemplate.class, new DefaultPictureTemplateRenderPolicy());
    //表示图片数据模板,在文档中用于描述图片数据的模板。
    plugin(PictImageTemplate.class, new DefaultPictImageTemplateRenderPolicy());
    //表示图表模板,在文档中用于描述图表数据的模板。
    plugin(ChartTemplate.class, new DefaultChartTemplateRenderPolicy());
}

Configure 类的主要功能和特点

  1. 模板标签配置

    • 上述介绍。
    • 支持配置自定义标签和渲染策略,可以根据模板中的特定标签绑定自定义的渲染策略。
    • 提供了默认的模板标签和对应的渲染策略,包括文本、图片、表格、编号列表等。
  2. 模板元素配置

    • 上述介绍。
    • 可以配置模板元素的渲染策略,例如图表模板、图片模板等,根据模板元素的类型绑定对应的渲染策略。
  3. EL 表达式配置

    • setRenderDataComputeFactory(RenderDataComputeFactory factory)
    • 支持 SpringEL 和默认 EL 表达式语言,可以根据需求启用不同的 EL 表达式解析器。
  4. 正则表达式配置

    • DEFAULT_GRAMER_REGEX = "((#)?[\\w\\u4e00-\\u9fa5]+(\\.[\\w\\u4e00-\\u9fa5]+)*)?"
    • 这个正则表达式可以匹配模板中的标签,包括以 # 开头的标签,并且可以包含汉字、字母、数字、下划线,以及用 . 分隔的内容。
    • 可以配置模板标签的正则表达式,用于解析模板中的标签。
  5. 错误处理器配置

    • setValidErrorHandler(ValidErrorHandler handler)
    • 支持自定义错误处理器,用于处理模板中数据渲染时遇到的异常情况。
  6. 模板元素工厂配置

    • setElementTemplateFactory(ElementTemplateFactory factory)
    • 可以配置模板元素工厂,用于创建模板元素对象。
  7. 预渲染数据转换器配置

    • addPreRenderDataCastor(PreRenderDataCastor castor)
    • 支持配置预渲染数据转换器,用于在数据渲染前对数据进行预处理。
  8. 错误处理器接口

    • ValidErrorHandler
    • 提供了几种常见的错误处理器实现,包括丢弃处理器、清除处理器和中止处理器。

ConfigureBuilder介绍

ConfigureBuilder 类是一个构建器模式的实现,用于构建 Configure 对象,该对象用于配置 poi-tl 库的行为。它包含了一系列的方法,每个方法用于配置 Configure 对象的不同属性。以下是 ConfigureBuilder 类的主要功能:

常用方法介绍

addPlugin和bind

addPlugin有多个重载形式,分别用于注册不同类型模板的默认渲染策略。但一般使用char来注册就足够。用来增加自定义的渲染策略。

{{ 自定义char+任意tagName}}

如:{{-var}} {{^var}} ,但因为基本特殊字符有限,需要谨慎使用。

public ConfigureBuilder addPlugin(char c, RenderPolicy policy) {
    config.plugin(c, policy);
    return this;
}

bind我认为重要的有两个重载形式:用来增加自定义的渲染策略。

{{任意tagName}}

场景:当传入{{timestamp}}需要自动转换成指定格式日期输出如:yyyy-mm-dd输出

//one tagName, one policy
public ConfigureBuilder bind(String tagName, RenderPolicy policy) {
    config.customPolicy(tagName, policy);
    return this;
}
//one policy, many tagNames 可以指定多个tagNames使用指定policy处理
public ConfigureBuilder bind(RenderPolicy policy, String... tagNames) {
    Stream.of(tagNames).forEach(tagName -> config.customPolicy(tagName, policy));
    return this;
}
SpringEL 是另一个大坑,还在坑附近徘徊,不知道是否需要深入的(~ ̄▽ ̄)~
  • useSpringEL(): 启用 SpringEL 表达式语言。
  • useSpringEL(boolean isStrict): 启用 SpringEL 表达式语言。
  • useSpringEL(Map<String, Method> spELFunction): 启用 SpringEL,并指定自定义的 SpEL 函数。
  • useDefaultEL(boolean isStrict): 启用默认的 EL 表达式语言。

其他方法介绍

  • buildGramer(String prefix, String suffix): 配置模板标签的前缀和后缀。
  • buidIterableLeft(char c): 配置迭代标签的左分隔符。
  • buildGrammerRegex(String reg): 配置模板标签的正则表达式。默认是{{?var}}
  • setValidErrorHandler(ValidErrorHandler handler): 设置验证错误处理器。
  • setRenderDataComputeFactory(RenderDataComputeFactory renderDataComputeFactory): 设置渲染数据计算工厂。
  • setElementTemplateFactory(ElementTemplateFactory elementTemplateFactory): 设置元素模板工厂。
  • setPreRenderDataCastors(List<PreRenderDataCastor> providers): 设置预渲染数据转换器。
  • addPreRenderDataCastor(PreRenderDataCastor provider): 添加预渲染数据转换器。
  1. 构建方法build() 方法用于根据配置生成 Configure 对象,如果使用了 SpringEL 且未改变正则表达式,则会自动调用 RegexUtils.createGeneral 方法生成通用的正则表达式。

通过 ConfigureBuilder 类,用户可以方便地配置 poi-tl 库的行为,包括模板标签、渲染策略、EL 表达式语言等,从而实现对模板生成和数据渲染的定制化。

结束啦ヾ(≧▽≦*)o

这篇主要介绍XWPFTemplate,Configure,ConfigureBuilder。

往后继续介绍

  1. NiceXWPFDocument类:继承自XWPFDocument,对Word文档进行扩展和处理。
  2. TemplateResolver类:解析Word文档模板,识别模板中的标签等。
  3. DefaultRender类:默认的渲染器,根据数据模型填充模板中的标签。
  4. MetaTemplate类:代表模板中的元素,例如段落、表格等。

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;