SpringBoot快速集成jxls-poi(自定義模板,支持本地文件導(dǎo)出,在線文件導(dǎo)出)
在項(xiàng)目持續(xù)集成的過程中,有時(shí)候需要實(shí)現(xiàn)報(bào)表導(dǎo)出和文檔導(dǎo)出,類似于excel中這種文檔的導(dǎo)出,在要求不高的情況下,有人可能會(huì)考慮直接導(dǎo)出csv文件來簡(jiǎn)化導(dǎo)出過程。但是導(dǎo)出xlsx文件,其實(shí)過程相對(duì)更復(fù)雜。解決方案就是使用poi的jar包。使用源生的poi來操作表格,代碼冗余,處理復(fù)雜,同時(shí)poi的相關(guān)聯(lián)的依賴還會(huì)存在版本兼容問題。所以直接使用poi來實(shí)現(xiàn)表格導(dǎo)出,維護(hù)成本大,不易于拓展。
我們需要學(xué)會(huì)站在巨人的肩膀上解決問題,jxls-poi這個(gè)就很好解決這個(gè)excel表格導(dǎo)出的多樣化的問題。類似jsp和thymealf的模板定義,使得表格導(dǎo)出變得簡(jiǎn)單可控。
不多BB上代碼
1.引入關(guān)鍵依賴包
<!-- jxls-api依賴 --> <dependency> <groupId>org.jxls</groupId> <artifactId>jxls-poi</artifactId> <version>1.0.15</version> </dependency> <dependency> <groupId>org.jxls</groupId> <artifactId>jxls</artifactId> <version>2.4.6</version> </dependency>
這里只需要兩個(gè)依賴便操作excel表格了。
2.定義模板文件

新建一個(gè)excel文件,后綴名為.xlsx,在resources目錄下新增一個(gè)jxls的文件夾,把模板文件放在這個(gè)文件夾下,便于后續(xù)的spring-boot的集成。
3.導(dǎo)出工具類
/**
* @author machenike
*/
public class ExcelUtils {
/***
* excel導(dǎo)出到response
* @param fileName 導(dǎo)出文件名
* @param templateFile 模板文件地址
* @param params 數(shù)據(jù)集合
* @param response response
*/
public static void exportExcel(String fileName, InputStream templateFile, Map<String, Object> params,
HttpServletResponse response) throws IOException {
response.reset();
response.setHeader("Accept-Ranges", "bytes");
OutputStream os = null;
response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName));
response.setContentType("application/octet-stream;charset=UTF-8");
try {
os = response.getOutputStream();
exportExcel(templateFile, params, os);
} catch (IOException e) {
throw e;
}
}
/**
* 導(dǎo)出excel到輸出流中
* @param templateFile 模板文件
* @param params 傳入?yún)?shù)
* @param os 輸出流
* @throws IOException
*/
public static void exportExcel(InputStream templateFile, Map<String, Object> params, OutputStream os) throws IOException {
try {
Context context = new Context();
Set<String> keySet = params.keySet();
for (String key : keySet) {
//設(shè)置參數(shù)變量
context.putVar(key, params.get(key));
}
Map<String, Object> myFunction = new HashMap<>();
myFunction.put("fun", new ExcelUtils());
// 啟動(dòng)新的jxls-api 加載自定義方法
Transformer trans = TransformerFactory.createTransformer(templateFile, os);
JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) trans.getTransformationConfig().getExpressionEvaluator();
evaluator.getJexlEngine().setFunctions(myFunction);
// 載入模板、處理導(dǎo)出
AreaBuilder areaBuilder = new XlsCommentAreaBuilder(trans);
List<Area> areaList = areaBuilder.build();
areaList.get(0).applyAt(new CellRef("sheet1!A1"), context);
trans.write();
} catch (IOException e) {
throw e;
} finally {
try {
if (os != null) {
os.flush();
os.close();
}
if (templateFile != null) {
templateFile.close();
}
} catch (IOException e) {
throw e;
}
}
}
/**
* 格式化時(shí)間
*/
public Object formatDate(Date date) {
if (date != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = sdf.format(date);
return dateStr;
}
return "--";
}
/**
* 設(shè)置超鏈接方法
*/
public WritableCellValue getLink(String address, String title) {
return new WritableHyperlink(address, title);
}
}
這個(gè)工具類中我定義兩個(gè)導(dǎo)出用的方法
一個(gè)是直接是HttpServletResponse 導(dǎo)出在線下載文件
一個(gè)使用輸入流導(dǎo)出
同時(shí)模板中還支持方法傳入。
4.定義導(dǎo)出服務(wù)類
全局配置jxls模板的基礎(chǔ)路徑
#jxls模板的基礎(chǔ)路徑 jxls.template.path: classpath:jxls/
定義服務(wù)接口
/**
* excel用service
*/
public interface ExcelService {
/**
* 導(dǎo)出excel,寫入輸出流中
* @param templateFile
* @param params
* @param os
* @return
*/
boolean getExcel(String templateFile,Map<String,Object> params, OutputStream os);
/**
* 導(dǎo)出excel,寫入response中
* @param templateFile
* @param fileName
* @param params
* @param response
* @return
*/
boolean getExcel(String templateFile,String fileName, Map<String,Object> params, HttpServletResponse response);
/**
* 導(dǎo)出excel,寫入文件中
* @param templateFile
* @param params
* @param outputFile
* @return
*/
boolean getExcel(String templateFile, Map<String,Object> params, File outputFile);
}
excel導(dǎo)出用服務(wù)實(shí)現(xiàn)類
/**
* excel用serviceImpl
*/
@Service
public class ExcelServiceImppl implements ExcelService {
private static final Logger logger = LoggerFactory.getLogger(ExcelServiceImppl.class);
/**
* 模板文件的基礎(chǔ)路徑
*/
@Value("${jxls.template.path}")
private String templatePath;
@Override
public boolean getExcel(String templateFile, Map<String, Object> params, OutputStream os) {
FileInputStream inputStream = null;
try {
//獲取模板文件的輸入流
inputStream = new FileInputStream(ResourceUtils.getFile(templatePath + templateFile));
//導(dǎo)出文件到輸出流
ExcelUtils.exportExcel(inputStream, params, os);
} catch (IOException e) {
logger.error("excel export has error" + e);
return false;
}
return true;
}
@Override
public boolean getExcel(String templateFile, String fileName, Map<String, Object> params, HttpServletResponse response) {
FileInputStream inputStream = null;
try {
//獲取模板文件的輸入流
inputStream = new FileInputStream(ResourceUtils.getFile(templatePath + templateFile));
//導(dǎo)出文件到response
ExcelUtils.exportExcel(fileName,inputStream,params,response);
} catch (IOException e) {
logger.error("excel export has error" + e);
return false;
}
return true;
}
@Override
public boolean getExcel(String templateFile, Map<String, Object> params, File outputFile) {
FileInputStream inputStream = null;
try {
//獲取模板文件的輸入流
inputStream = new FileInputStream(ResourceUtils.getFile(templatePath + templateFile));
File dFile = outputFile.getParentFile();
//文件夾不存在時(shí)創(chuàng)建文件夾
if(dFile.isDirectory()){
if(!dFile.exists()){
dFile.mkdir();
}
}
//文件不存在時(shí)創(chuàng)建文件
if(!outputFile.exists()){
outputFile.createNewFile();
}
//導(dǎo)出excel文件
ExcelUtils.exportExcel(inputStream, params, new FileOutputStream(outputFile));
} catch (IOException e) {
logger.error("excel export has error" + e);
return false;
}
return true;
}
}
如上,服務(wù)類提供了,三種導(dǎo)出的實(shí)現(xiàn)方法
- 導(dǎo)出excel寫入response中
- 導(dǎo)出excel寫入輸出流中
- 導(dǎo)出excel寫入文件中
這三種方法足以覆蓋所有的業(yè)務(wù)需求
5.編輯jxls模板
這里為方便導(dǎo)出最好定義與模板匹配的實(shí)體類,便于數(shù)據(jù)的裝載和導(dǎo)出
public class UserModel {
private Integer id;
private String name;
private String sex;
private Integer age;
private String remark;
private Date date;
private String link;
}

插入標(biāo)注定義模板,定義迭代對(duì)象jx:each
jx:each(items="list" var="item" lastCell="G3")
上面G3 模板中迭代的結(jié)束位置,然后用類似EL表達(dá)式的方式填充到模板當(dāng)中

填寫范圍jx:area
jx:area(lastCell="G3")
模板編輯完成后保存即可,
6.代碼測(cè)試使用
導(dǎo)出為本地文件
@SpringBootTest
class BlogJxlsApplicationTests {
@Autowired
ExcelService excelService;
@Test
void contextLoads() {
Map<String, Object> params = new HashMap();
List<UserModel> list = new ArrayList<>();
list.add(new UserModel(1, "test01", "男", 25, "tttttttttt",new Date(),"htpp://wwww.baidu.com"));
list.add(new UserModel(2, "test02", "男", 20, "tttttttttt",new Date(),"htpp://wwww.baidu.com"));
list.add(new UserModel(3, "test04", "女", 25, "ttttddddasdadatttttt",new Date(),"htpp://wwww.baidu.com"));
list.add(new UserModel(4, "test08", "男", 20, "ttttttdasdatttt",new Date(),"htpp://wwww.baidu.com"));
list.add(new UserModel(5, "test021", "女", 25, "ttttdatttttt",new Date(),"htpp://wwww.baidu.com"));
list.add(new UserModel(7, "test041", "男", 25, "ttdadatttttttt",new Date(),"htpp://wwww.baidu.com"));
params.put("list", list);
excelService.getExcel("t1.xlsx", params, new File("D:\\test05.xlsx"));
}
}
導(dǎo)出成功

在線導(dǎo)出文件
@RestController
public class TestController {
@Autowired
ExcelService excelService;
@RequestMapping("test")
public void testFile(HttpServletResponse response){
Map<String, Object> params = new HashMap();
List<UserModel> list = new ArrayList<>();
list.add(new UserModel(1, "test01", "男", 25, "tttttttttt",new Date(),"htpp://wwww.baidu.com"));
list.add(new UserModel(2, "test02", "男", 20, "tttttttttt",new Date(),"htpp://wwww.baidu.com"));
list.add(new UserModel(3, "test04", "女", 25, "ttttddddasdadatttttt",new Date(),"htpp://wwww.baidu.com"));
list.add(new UserModel(4, "test08", "男", 20, "ttttttdasdatttt",new Date(),"htpp://wwww.baidu.com"));
list.add(new UserModel(5, "test021", "女", 25, "ttttdatttttt",new Date(),"htpp://wwww.baidu.com"));
list.add(new UserModel(7, "test041", "男", 25, "ttdadatttttttt",new Date(),"htpp://wwww.baidu.com"));
params.put("list", list);
excelService.getExcel("t1.xlsx",System.currentTimeMillis()+".xlsx", params,response);
}
}

導(dǎo)出成功


源碼地址
https://github.com/DavidLei08/BlogJxls.git
到此這篇關(guān)于SpringBoot快速集成jxls-poi(自定義模板,支持本地文件導(dǎo)出,在線文件導(dǎo)出)的文章就介紹到這了,更多相關(guān)SpringBoot集成jxls-poi內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Java8中接口的默認(rèn)方法和靜態(tài)方法
Java 8是Java語(yǔ)言的一個(gè)重要版本,其中引入了許多新特性和改進(jìn),其中一個(gè)值得關(guān)注的特性是接口的默認(rèn)方法和靜態(tài)方法,本文就來和大家簡(jiǎn)單講講吧2023-05-05
使用Java將字符串在ISO-8859-1和UTF-8之間相互轉(zhuǎn)換
大家都知道在一些情況下,我們需要特殊的編碼格式,如:UTF-8,但是系統(tǒng)默認(rèn)的編碼為ISO-8859-1,遇到這個(gè)問題,該如何對(duì)字符串進(jìn)行兩個(gè)編碼的轉(zhuǎn)換呢,下面小編給大家分享下java中如何在ISO-8859-1和UTF-8之間相互轉(zhuǎn)換,感興趣的朋友一起看看吧2021-12-12
Java任務(wù)調(diào)度的常見實(shí)現(xiàn)方法與比較詳解
這篇文章主要介紹了Java任務(wù)調(diào)度的常見實(shí)現(xiàn)方法與比較,結(jié)合實(shí)例形式分析了Java任務(wù)調(diào)度的四種常見實(shí)現(xiàn)方法,使用區(qū)別及相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-08-08
MybatisPlus的MetaObjectHandler與@TableLogic使用
這篇文章主要介紹了MybatisPlus的MetaObjectHandler與@TableLogic使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
淺談SpringSecurity注解與AOP切面執(zhí)行順序
這篇文章主要介紹了淺談SpringSecurity注解與AOP切面執(zhí)行順序,引入Spring Security后,在Controller的方法中會(huì)出現(xiàn)Spring Security的方法注解與AOP同時(shí)存在的問題,這是就會(huì)設(shè)計(jì)順序問題,需要的朋友可以參考下2023-10-10
Opencv實(shí)現(xiàn)身份證OCR識(shí)別的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何使用Opencv實(shí)現(xiàn)身份證OCR識(shí)別功能,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起了解一下2024-03-03
關(guān)于maven使用過程中無法導(dǎo)入依賴的一些總結(jié)
這篇文章主要介紹了關(guān)于maven使用過程中無法導(dǎo)入依賴的一些總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
java使用FFmpeg合成視頻和音頻并獲取視頻中的音頻等操作(實(shí)例代碼詳解)
這篇文章主要介紹了java使用FFmpeg合成視頻和音頻并獲取視頻中的音頻等操作,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02

