rayin使用与学习

简介: rayin使用与学习

一、背景

      基于html生成pdf的使用场景比较多,我在的上家公司做电子合同需求的时候,是我这边完成的,当时是基于itext生成PDF的。电子合同作为一个电签中必不可少的一部分,如何高效实现html生成pdf,是我们必须要解决的问题。如果使用电子合同,此时必然需要对接相关的电子合同厂家,比如E签宝、法大大、上上签、电子牵等。当时生成的pdf没有作者想的这么周到,不过这次做需求,再次看到这个项目,还是很开心很乐意和大家分享这个项目的,也感谢rayin的作者开源了这么好的项目。

项目地址:https://gitee.com/Rayin/rayin

二、使用场景

各种电子合同、病历模板、动态模板、各种结算单、各种账单、发票等等,使用场景非常广泛。

当然本次我这边需要完成一个财务那边的结算单电子存档,此时由于涉及图片、表单、二维码、相关结算金额问题。起初我打算使用基于itext直接生成。我之前做过电子合同的需求,知道itext对于样式的兼容不是很好。因此本次,我这边使用rayin来进行pdf生成,主要开源的这个项目很好的满足了我的需求。

之所以推荐rayin来生成pdf,在于rayin的便利性。有快速上手的example,对样式进行了兼容,不会出现截断,同时快速生成的效率。

三、基于html+json数据生成效果


四、基于html+json数据+excel生成效果


从上面生成的效果可以出生成的效果,样式得到了很好的渲染,同时支持图片的插入。看起来很精美。

五、如何实现上面效果

我们看到了效果,那它是怎么实现上面的效果的呢?

1)快速开始

可以看到excel里面基于excel+json数据+html生成、基于html+json数据、基于模板+规则groovy生成,除此之外,还有性能测试。


可以看到作者很贴心的准备了很多的example,让我们可以快速开始,了解使用rayin生成不同的pdf。

根据example5来看:

public void exp05ComplexElementBindDataGenerateTest() throws Exception {
        //获取数据路径信息
        String jsonDataFilePath = ResourceUtil.getResourceAbsolutePathByClassPath("examples/example5/data.json");
        // 将json数据进行解析
        JsonNode jsonDataNode = JsonSchemaValidator.getJsonNodeFromFile(jsonDataFilePath);
        //依据单个构建配置生成PDF
        JSONObject jsonData = JSONObject.parseObject(jsonDataNode.toString());
        String outputFileClass = ResourceUtil.getResourceAbsolutePathByClassPath("");
        // 生成pdf路径
        String outputFile = new File(outputFileClass)
                .getParentFile().getParent()
                + "/tmp/"
                + "example05_openhtmltopdf_"+System.currentTimeMillis() + ".pdf";
        StopWatch watch = StopWatch.createStarted();
        // 生成PDF: html的路径、json数据、输出pdf文件的路径
  pdfGenerator.generatePdfFileByHtmlAndData(ResourceUtil.getResourceAbsolutePathByClassPath("examples/example5/element1.html"),jsonData,outputFile);
        watch.stop();
    }

2)调用生成pdf文件的核心方法

pdfGenerator.generatePdfFileByHtmlAndData(ResourceUtil.getResourceAbsolutePathByClassPath("examples/example5/element1.html"),jsonData,outputFile); 这个方法中,可以看到需要html的路径,json数据,输出文件路径。

也即基于html和jsonData,来构建pdf,从而生成PDF。从resource中,我们可以看到里面包含html和json数据,当然这里的json数据是为了测试方便,在真实的业务场景下,json数据来源于业务中。


此时我们关心的是json数据如何填充到html中,然后渲染相关样式,然后生成PDF。

3)填充html构件字符串过程

public String templateEngineProcessByString(String htmlStr, JSONObject jsonData){
        // 创建上下文对象,如果json数据不为空,则设置变量
         Context context  = new Context();
        if(jsonData != null){
            context.setVariables(JSON.parseObject(jsonData.toJSONString(), Map.class));
        }
        String r = null;
        try{
            // 通过模板引擎处理,拿到json的字符串
            r = templateEngine.process(htmlStr, context);
        }catch(Exception e){
            r = e.getCause().toString().replace("org.attoparser.ParseException: Exception evaluating OGNL expression:","The Data paraeter error:");
        }
        return r;
    }

而这个过程是通过模板引擎thyemleaf进行处理得到的。核心方法:templateEngine.process(htmlStr, context),调用模板引擎处理从而完成数据的填充工作。

4)样式渲染处理

完成数据填充之后,还需要考虑样式的问题。因此在这个方法中,进行数据样式相关信息的处理:generatePdfStreamByHtmlStr(String htmlContent, Set markKeys),下面是对相关标签的渲染处理:


可以看到最终生成PDF的渲染工作借助了openhtmltopdf这个开源项目。不得不说这个框架也是够强大的。

到这里,html完成了向PDF的过渡,最终FileUtils.writeByteArrayToFile(new File(outputFile), generatePdfStreamByHtmlStr(htmlStr).toByteArray())生成PDF。

当然这里涉及到这个字体的问题:

5) 字体的设置

public static void init() {
        synchronized(OpenhttptopdfRendererObjectFactory.class) {
            // 进行字体缓存
            factory.FontCache();
            //设置对象池的相关参数
            GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
            //最大空闲数
            poolConfig.setMaxIdle(MaxIdle);
            //最大线程数
            poolConfig.setMaxTotal(MaxTotal);
            //最小线程数
            poolConfig.setMinIdle(MinIdle);
            poolConfig.setSoftMinEvictableIdleTimeMillis(SoftMinEvictableIdleTimeMillis);
            //新建一个对象池,传入对象工厂和配置
            objectPool = new GenericObjectPool<OpenhttptopdfRenderBuilder>(factory, poolConfig);
        }
    }

可以看到对象池中存放了对象池的池配置信息和字体信息。方便后续的渲染使用,因为后续使用渲染成PDF的正是使用了这个构建器。

如果想自定义字体可以调用:

void init(String customizeFontPathDirectory);

除此之外,还可以自定义设置对象池的配置:

void init(int minIdle,int maxIdle,int maxTotal, String customizeFontPathDirectory);

6) rayin提供生成PDF的相关方式

从PdfGenerator接口,生成PDF的方式包含两种:

基于html+json数据生成PDF
基于html+json数据+excel生成PDF

还有基于groovy规则生成PDF。

当然除此之外,还有很多开源项目是基于html生成pdf的,比如经典的itext,openpdf、openhtmltopdf、jasper、x-easypdf等。

参考:https://gitee.com/Rayin/rayin

目录
相关文章
|
2月前
|
算法 开发者 Python
pyton 学习技巧
【9月更文挑战第2天】pyton 学习技巧
36 2
|
1月前
学习putpixel画点
学习putpixel画点。
54 20
|
2月前
|
存储 编解码 算法
ans介绍学习
【9月更文挑战第5天】
79 13
|
2月前
|
Linux
RISCV学习
RISCV学习
|
程序员
学习学习再学习
学习学习再学习
110 0
|
数据安全/隐私保护
实用分享-学习资料下载器
实用分享-学习资料下载器
|
机器学习/深度学习 设计模式 算法
|
NoSQL Java jenkins
【学习总结】总结
【学习总结】总结
|
前端开发 NoSQL Java
如何学习?今天聊聊关于学习
如何学习?今天聊聊关于学习
166 0
|
算法 Oracle Java
IT学习深入学习必备的技术网站
IT学习深入学习必备的技术网站
88 0