Java使用POI-TL实现生成有个性的简历

 更新时间:2024年11月29日 08:33:23   作者:HBLOG  
POI-TL 是一个基于 Apache POI 的 Java 库,专注于在 Microsoft Word 文档(.docx 格式)中进行模板填充和动态内容生成,下面我们看看如何使用POI-TL生成有个性的简历吧

1.介绍

POI-TL 是一个基于 Apache POI 的 Java 库,专注于在 Microsoft Word 文档(.docx 格式)中进行模板填充和动态内容生成。它的全称是 “POI Template Language”,旨在简化文档生成过程,特别是在需要根据动态数据生成复杂文档的场景中。POI-TL 通过提供一种简单而强大的模板引擎,使开发者能够轻松地将数据嵌入到 Word 文档中,从而自动化生成报告、合同、发票等文档。

2.原理

POI-TL 的核心原理是将 Word 文档视为模板,并在其中定义占位符。占位符通常以 {{key}} 的形式出现,代表需要动态替换的内容。开发者通过 Java 代码提供一个数据模型,其中包含占位符对应的实际值。POI-TL 使用这些数据来替换模板中的占位符,从而生成最终的文档。

POI-TL 基于 Apache POI 构建,利用 POI 提供的对 Word 文档的低级别操作能力,实现了对文档的高效处理。它支持复杂的文档结构,包括表格、图片、段落等,使得生成的文档不仅内容准确,还能保持良好的格式和样式。

3.代码工程

目标

利用word模版生成简历

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>Java-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>poi-tl</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.12.2</version>
        </dependency>
        <!-- Log4j dependencies for logging -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</project>

模版

在代码仓库的测试包下面

src/test/resources/resume.docx

代码

ExperienceData.java

package com.et;

import com.deepoove.poi.data.NumberingRenderData;

public class ExperienceData {
    private String company;
    private String department;
    private String time;
    private String position;
    private NumberingRenderData responsibility;

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

    public NumberingRenderData getResponsibility() {
        return responsibility;
    }

    public void setResponsibility(NumberingRenderData responsibility) {
        this.responsibility = responsibility;
    }

}

ResumeDataV2.java

package com.et;

import java.util.List;

import com.deepoove.poi.data.NumberingRenderData;
import com.deepoove.poi.data.PictureRenderData;

public class ResumeDataV2 {

    private PictureRenderData portrait;
    private String name;
    private String job;
    private String sex;
    private String phone;
    private String birthday;
    private String province;
    private String email;
    private String address;
    private String english;
    private String University;
    private String rank;
    private String education;
    private String profession;
    private NumberingRenderData stack;
    private String hobbies;
    private List<ExperienceData> experiences;

    public void setPortrait(PictureRenderData portrait) {
        this.portrait = portrait;
    }

    public PictureRenderData getPortrait() {
        return this.portrait;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public String getJob() {
        return this.job;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getSex() {
        return this.sex;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getPhone() {
        return this.phone;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public String getBirthday() {
        return this.birthday;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getProvince() {
        return this.province;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getEmail() {
        return this.email;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getAddress() {
        return this.address;
    }

    public void setEnglish(String english) {
        this.english = english;
    }

    public String getEnglish() {
        return this.english;
    }

    public void setUniversity(String University) {
        this.University = University;
    }

    public String getUniversity() {
        return this.University;
    }

    public void setRank(String rank) {
        this.rank = rank;
    }

    public String getRank() {
        return this.rank;
    }

    public void setEducation(String education) {
        this.education = education;
    }

    public String getEducation() {
        return this.education;
    }

    public void setProfession(String profession) {
        this.profession = profession;
    }

    public String getProfession() {
        return this.profession;
    }

    public void setStack(NumberingRenderData stack) {
        this.stack = stack;
    }

    public NumberingRenderData getStack() {
        return this.stack;
    }

    public void setHobbies(String hobbies) {
        this.hobbies = hobbies;
    }

    public String getHobbies() {
        return this.hobbies;
    }

    public List<ExperienceData> getExperiences() {
        return experiences;
    }

    public void setExperiences(List<ExperienceData> experiences) {
        this.experiences = experiences;
    }

}

ResumeIterableExample.java

package com.et;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.Numberings;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.data.TextRenderData;
import com.deepoove.poi.data.style.Style;

@DisplayName("Foreach resume example")
public class ResumeIterableExample {

    ResumeDataV2 datas = new ResumeDataV2();

    @BeforeEach
    public void init() {
        datas.setPortrait(Pictures.ofLocal("src/test/resources/sayi.png").size(100, 100).create());
        datas.setName("卅一");
        datas.setJob("BUG工程师");
        datas.setPhone("18080809090");
        datas.setSex("男");
        datas.setProvince("杭州");
        datas.setBirthday("2000.08.19");
        datas.setEmail("adasai90@gmail.com");
        datas.setAddress("浙江省杭州市西湖区古荡1号");
        datas.setEnglish("CET6 620");
        datas.setUniversity("美国斯坦福大学");
        datas.setProfession("生命工程");
        datas.setEducation("学士");
        datas.setRank("班级排名 1/36");
        datas.setHobbies("音乐、画画、乒乓球、旅游、读书\nhttps://github.com/Sayi");

        // 技术栈部分
        TextRenderData textRenderData = new TextRenderData("SpringBoot、SprigCloud、Mybatis");
        Style style = Style.builder().buildFontSize(10).buildColor("7F7F7F").buildFontFamily("微软雅黑").build();
        textRenderData.setStyle(style);
        datas.setStack(Numberings.of(textRenderData, textRenderData, textRenderData).create());

        /*
         * {{?experiences}} {{company}} {{department}} {{time}} {{position}}
         * {{*responsibility}} {{/experiences}}
         */
        List<ExperienceData> experiences = new ArrayList<ExperienceData>();
        ExperienceData data0 = new ExperienceData();
        data0.setCompany("香港微软");
        data0.setDepartment("Office 事业部");
        data0.setTime("2001.07-2020.06");
        data0.setPosition("BUG工程师");
        textRenderData = new TextRenderData("负责生产BUG,然后修复BUG,同时有效实施招聘行为");
        textRenderData.setStyle(style);
        data0.setResponsibility(Numberings.of(textRenderData, textRenderData).create());
        ExperienceData data1 = new ExperienceData();
        data1.setCompany("自由职业");
        data1.setDepartment("OpenSource 项目组");
        data1.setTime("2015.07-2020.06");
        data1.setPosition("研发工程师");
        textRenderData = new TextRenderData("开源项目的迭代和维护工作");
        textRenderData.setStyle(style);
        TextRenderData textRenderData1 = new TextRenderData("持续集成、Swagger文档等工具调研");
        textRenderData1.setStyle(style);
        data1.setResponsibility(Numberings.of(textRenderData, textRenderData1, textRenderData).create());
        experiences.add(data0);
        experiences.add(data1);
        experiences.add(data0);
        experiences.add(data1);
        datas.setExperiences(experiences);
    }

    @Test
    public void testResumeExample() throws Exception {
        XWPFTemplate template = XWPFTemplate.compile("src/test/resources/resume.docx").render(datas);

        FileOutputStream out = new FileOutputStream("target/out_example_resume_iterable.docx");
        template.write(out);
        out.flush();
        out.close();
        template.close();
    }

}

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

github.com/Harries/Java-demo(POI-TL )

4.测试

运行测试代码,打开生成的文件(target/out_example_resume_iterable.docx)如下图展示

以上就是Java使用POI-TL实现生成有个性的简历的详细内容,更多关于Java POI-TL生成简历的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot中@ControllerAdvice注解的使用方法

    SpringBoot中@ControllerAdvice注解的使用方法

    这篇文章主要介绍了SpringBoot中@ControllerAdvice注解的使用方法,这是一个增强的 Controller,对controller层做异常处理、数据预处理、全局数据绑定, springboot 会自动扫描到,不需要调用,这个注解是spring MVC提供的,在springboot中也可以使用,需要的朋友可以参考下
    2024-01-01
  • 深入了解Java线程池的原理和监控

    深入了解Java线程池的原理和监控

    这篇文章主要介绍了深入了解Java线程池的原理和监控,创建Java线程需要给线程分配堆栈内存以及初始化内存,还需要进行系统调用,频繁地创建和销毁线程会大大降低系统的运行效率,这时候就要用到线程池,需要的朋友可以参考下
    2023-07-07
  • 流式图表拒绝增删改查之kafka核心消费逻辑下篇

    流式图表拒绝增删改查之kafka核心消费逻辑下篇

    这篇文章主要为大家介绍了流式图表拒绝增删改查之kafka核心消费逻辑讲解的下篇,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • SpringBoot+netty-socketio实现服务器端消息推送

    SpringBoot+netty-socketio实现服务器端消息推送

    这篇文章主要介绍了SpringBoot+netty-socketio实现服务器端消息推送,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Java中ReentrantLock4种常见的坑

    Java中ReentrantLock4种常见的坑

    本文主要介绍了Java中ReentrantLock 4种常见的坑,ReentrantLock默认情况下为非公平锁,下文关于其更多详情需要的小伙伴可以参考一下
    2022-05-05
  • Java实现数据库连接池简易教程

    Java实现数据库连接池简易教程

    这篇文章主要为大家介绍了Java实现数据库连接池简易教程,感兴趣的小伙伴们可以参考一下
    2016-01-01
  • Spring的自定义扩展标签NamespaceHandler解析

    Spring的自定义扩展标签NamespaceHandler解析

    这篇文章主要介绍了Spring的自定义扩展标签NamespaceHandler解析,在很多情况下,我们需要为系统提供可配置化支持,简单的做法可以直接基于Spring的标准Bean来配置,Spring提供了可扩展Schema的支持,这是一个不错的折中方案,需要的朋友可以参考下
    2023-12-12
  • Java中LinkedHashSet的源码分析

    Java中LinkedHashSet的源码分析

    这篇文章主要介绍了Java中LinkedHashSet的源码分析,LinkedHashSet 是 Java 中的一个集合类,它是 HashSet 的子类,同时也实现了 Set 接口,与 HashSet 不同的是,LinkedHashSet 保留了元素插入的顺序,并且具有 HashSet 的快速查找特性,需要的朋友可以参考下
    2023-09-09
  • 几道java循环练习题(适合新人)

    几道java循环练习题(适合新人)

    这篇文章主要给大家介绍了几道java循环练习题,非常适合刚入门的java新人,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Jrebel启动失败解决方案详解

    Jrebel启动失败解决方案详解

    这篇文章主要介绍了Jrebel启动失败解决方案详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07

最新评论