Java使用POI-TL實現(xiàn)生成有個性的簡歷
1.介紹
POI-TL 是一個基于 Apache POI 的 Java 庫,專注于在 Microsoft Word 文檔(.docx 格式)中進(jìn)行模板填充和動態(tài)內(nèi)容生成。它的全稱是 “POI Template Language”,旨在簡化文檔生成過程,特別是在需要根據(jù)動態(tài)數(shù)據(jù)生成復(fù)雜文檔的場景中。POI-TL 通過提供一種簡單而強(qiáng)大的模板引擎,使開發(fā)者能夠輕松地將數(shù)據(jù)嵌入到 Word 文檔中,從而自動化生成報告、合同、發(fā)票等文檔。
2.原理
POI-TL 的核心原理是將 Word 文檔視為模板,并在其中定義占位符。占位符通常以 {{key}} 的形式出現(xiàn),代表需要動態(tài)替換的內(nèi)容。開發(fā)者通過 Java 代碼提供一個數(shù)據(jù)模型,其中包含占位符對應(yīng)的實際值。POI-TL 使用這些數(shù)據(jù)來替換模板中的占位符,從而生成最終的文檔。
POI-TL 基于 Apache POI 構(gòu)建,利用 POI 提供的對 Word 文檔的低級別操作能力,實現(xiàn)了對文檔的高效處理。它支持復(fù)雜的文檔結(jié)構(gòu),包括表格、圖片、段落等,使得生成的文檔不僅內(nèi)容準(zhǔn)確,還能保持良好的格式和樣式。
3.代碼工程
目標(biāo)
利用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("浙江省杭州市西湖區(qū)古蕩1號");
datas.setEnglish("CET6 620");
datas.setUniversity("美國斯坦福大學(xué)");
datas.setProfession("生命工程");
datas.setEducation("學(xué)士");
datas.setRank("班級排名 1/36");
datas.setHobbies("音樂、畫畫、乒乓球、旅游、讀書\nhttps://github.com/Sayi");
// 技術(shù)棧部分
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 事業(yè)部");
data0.setTime("2001.07-2020.06");
data0.setPosition("BUG工程師");
textRenderData = new TextRenderData("負(fù)責(zé)生產(chǎn)BUG,然后修復(fù)BUG,同時有效實施招聘行為");
textRenderData.setStyle(style);
data0.setResponsibility(Numberings.of(textRenderData, textRenderData).create());
ExperienceData data1 = new ExperienceData();
data1.setCompany("自由職業(yè)");
data1.setDepartment("OpenSource 項目組");
data1.setTime("2015.07-2020.06");
data1.setPosition("研發(fā)工程師");
textRenderData = new TextRenderData("開源項目的迭代和維護(hù)工作");
textRenderData.setStyle(style);
TextRenderData textRenderData1 = new TextRenderData("持續(xù)集成、Swagger文檔等工具調(diào)研");
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();
}
}
以上只是一些關(guān)鍵代碼,所有代碼請參見下面代碼倉庫
代碼倉庫
github.com/Harries/Java-demo(POI-TL )
4.測試
運行測試代碼,打開生成的文件(target/out_example_resume_iterable.docx)如下圖展示

以上就是Java使用POI-TL實現(xiàn)生成有個性的簡歷的詳細(xì)內(nèi)容,更多關(guān)于Java POI-TL生成簡歷的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot中@ControllerAdvice注解的使用方法
這篇文章主要介紹了SpringBoot中@ControllerAdvice注解的使用方法,這是一個增強(qiáng)的?Controller,對controller層做異常處理、數(shù)據(jù)預(yù)處理、全局?jǐn)?shù)據(jù)綁定,?springboot?會自動掃描到,不需要調(diào)用,這個注解是spring?MVC提供的,在springboot中也可以使用,需要的朋友可以參考下2024-01-01
SpringBoot+netty-socketio實現(xiàn)服務(wù)器端消息推送
這篇文章主要介紹了SpringBoot+netty-socketio實現(xiàn)服務(wù)器端消息推送,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Java實現(xiàn)數(shù)據(jù)庫連接池簡易教程
這篇文章主要為大家介紹了Java實現(xiàn)數(shù)據(jù)庫連接池簡易教程,感興趣的小伙伴們可以參考一下2016-01-01
Spring的自定義擴(kuò)展標(biāo)簽NamespaceHandler解析
這篇文章主要介紹了Spring的自定義擴(kuò)展標(biāo)簽NamespaceHandler解析,在很多情況下,我們需要為系統(tǒng)提供可配置化支持,簡單的做法可以直接基于Spring的標(biāo)準(zhǔn)Bean來配置,Spring提供了可擴(kuò)展Schema的支持,這是一個不錯的折中方案,需要的朋友可以參考下2023-12-12

