前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >rayin使用与学习

rayin使用与学习

作者头像
路行的亚洲
发布2023-10-08 09:34:02
2390
发布2023-10-08 09:34:02
举报
文章被收录于专栏:后端技术学习后端技术学习

一、背景

基于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来看:

代码语言:javascript
复制
  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构件字符串过程
代码语言:javascript
复制
 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) 字体的设置
代码语言:javascript
复制
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的正是使用了这个构建器。

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

代码语言:javascript
复制
    void init(String customizeFontPathDirectory);

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

代码语言:javascript
复制
 void init(int minIdle,int maxIdle,int maxTotal, String customizeFontPathDirectory);
6) rayin提供生成PDF的相关方式

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

代码语言:javascript
复制
基于html+json数据生成PDF
基于html+json数据+excel生成PDF

还有基于groovy规则生成PDF。

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-01 22:11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端技术学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、背景
  • 二、使用场景
  • 三、基于html+json数据生成效果
  • 四、基于html+json数据+excel生成效果
  • 五、如何实现上面效果
    • 1)快速开始
      • 2)调用生成pdf文件的核心方法
        • 3)填充html构件字符串过程
          • 4)样式渲染处理
            • 5) 字体的设置
              • 6) rayin提供生成PDF的相关方式
              相关产品与服务
              腾讯电子签
              弹指间,放心签。腾讯电子签(E-Sign Service)致力为企业及个人提供极简且高效的电子合同管理工具。您只需要一部手机即可完成合同签约及常见的合同管理操作;电子签将对签约全程进行区块链记录,为您的业务与生活保驾护航。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档