之前的项目中用到采用ireport打印,重构的bs架构项目不想重新画打印模板,准备继续沿用,记录springboot集成ireport实现打印。
0.添加maven依赖
<!--jasper框架依赖开始-->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.17.0</version>
</dependency>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports-fonts</artifactId>
<version>6.17.0</version>
</dependency>
<dependency>
<groupId>net.sf.barcode4j</groupId>
<artifactId>barcode4j</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>net.sourceforge.barbecue</groupId>
<artifactId>barbecue</artifactId>
<version>1.5-beta1</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-bridge</artifactId>
<version>1.14</version>
</dependency>
<!--jasper框架依赖结束-->
1.添加配置文件:src/main/resources/jasperreports_extension.properties
net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
net.sf.jasperreports.extension.simple.font.families.lobstertwo=fonts/fonts.xml
net.sf.jasperreports.awt.ignore.missing.font=true
2.添加字体配置src/main/resources/fonts/fonts.xml 以及字体包TTF文件(TTC测试不行)
<?xml version="1.0" encoding="UTF-8"?>
<fontFamilies>
<!--<fontFamily name="Lobster Two">-->
<!--<normal>lobstertwo/LobsterTwo-Regular.otf</normal>-->
<!--<bold>lobstertwo/LobsterTwo-Bold.otf</bold>-->
<!--<italic>lobstertwo/LobsterTwo-Italic.otf</italic>-->
<!--<boldItalic>lobstertwo/LobsterTwo-BoldItalic.otf</boldItalic>-->
<!--<pdfEncoding>Identity-H</pdfEncoding>-->
<!--<pdfEmbedded>true</pdfEmbedded>-->
<!--<!–-->
<!--<exportFonts>-->
<!--<export key="net.sf.jasperreports.html">'Lobster Two', 'Times New Roman', Times, serif</export>-->
<!--</exportFonts>-->
<!--–>-->
<!--</fontFamily>-->
<fontFamily name="华文宋体">
<normal>fonts/stsong.TTF</normal>
<bold>fonts/stsong.TTF</bold>
<italic>fonts/stsong.TTF</italic>
<boldItalic>fonts/stsong.TTF</boldItalic>
<pdfEncoding>Identity-H</pdfEncoding>
<pdfEmbedded>true</pdfEmbedded>
<exportFonts>
<export key="net.sf.jasperreports.html">'华文宋体', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'华文宋体', Arial, Helvetica, sans-serif</export>
</exportFonts>
<!--
<locales>
<locale>en_US</locale>
<locale>de_DE</locale>
</locales>
-->
</fontFamily>
<fontFamily name="宋体">
<normal>fonts/SimSun.ttf</normal>
<bold>fonts/SimSun.ttf</bold>
<italic>fonts/SimSun.ttf</italic>
<boldItalic>fonts/SimSun.ttf</boldItalic>
<pdfEncoding>Identity-H</pdfEncoding>
<pdfEmbedded>true</pdfEmbedded>
<exportFonts>
<export key="net.sf.jasperreports.html">'宋体', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'宋体', Arial, Helvetica, sans-serif</export>
</exportFonts>
<!--
<locales>
<locale>en_US</locale>
<locale>de_DE</locale>
</locales>
-->
</fontFamily>
<fontFamily name="微软雅黑">
<normal>fonts/msyh.ttf</normal>
<bold>fonts/msyh.ttf</bold>
<italic>fonts/msyh.ttf</italic>
<boldItalic>fonts/msyh.ttf</boldItalic>
<pdfEncoding>Identity-H</pdfEncoding>
<pdfEmbedded>true</pdfEmbedded>
<exportFonts>
<export key="net.sf.jasperreports.html">'微软雅黑', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'微软雅黑', Arial, Helvetica, sans-serif</export>
</exportFonts>
<!--
<locales>
<locale>en_US</locale>
<locale>de_DE</locale>
</locales>
-->
</fontFamily>
</fontFamilies>
3.编写公共方法,生成pdf
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.springframework.http.*;
import java.io.InputStream;
import java.util.Collection;
import java.util.Map;
/**
*
* @date 2025年05月12日 下午5:33
*/
public class JasperPrintUtils {
/**
*
* @param is 编译的jasper文件的InputStream
* @param map 全局变量的map
* @param beanCollection 动态扩展的list数据
* @return net.sf.jasperreports.engine.JasperPrint
*/
private static JasperPrint renderTemplates(InputStream is, Map<String, Object> map, Collection<?> beanCollection) throws JRException {
JRBeanCollectionDataSource jrBeanCollectionDataSource = new JRBeanCollectionDataSource(beanCollection);
return JasperFillManager.fillReport(is, map, jrBeanCollectionDataSource);
}
/**
* 封装返回字节文件
*
* @param jasperPrint
* @return net.sf.jasperreports.engine.JasperPrint
*/
private static ResponseEntity<byte[]> exportPdfByte(JasperPrint jasperPrint) throws JRException {
byte[] bytes = JasperExportManager.exportReportToPdf(jasperPrint);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
headers.setContentDisposition(ContentDisposition.inline().filename("report.pdf").build());
headers.setContentLength(bytes.length);
return ResponseEntity
.status(HttpStatus.OK)
.headers(headers)
.body(bytes);
}
/**
* 封装打印模板返回字节文件
*
* @param is 编译的jasper文件的InputStream
* @param t 全局变量的对象
* @param beanCollection 动态扩展的list数据
* @return org.springframework.http.ResponseEntity<byte[]>
*/
public static ResponseEntity<byte[]> getreportToPdf(InputStream is,
Object obj,
Collection<?> beanCollection) {
try {
// 下面对象转map的公共方法
Map<String, Object> map = BeanMapUtils.beanToMap(obj);
return exportPdfByte(renderTemplates(is, map, beanCollection));
}catch (JRException e) {
e.printStackTrace();
}
}
}
//****************将对象属性转化为map集合*********************/
import org.springframework.cglib.beans.BeanMap;
import java.util.HashMap;
import java.util.Map;
public class BeanMapUtils {
/**
* 将对象属性转化为map集合
*/
public static <T> Map<String, Object> beanToMap(T bean) {
Map<String, Object> map = new HashMap<>();
if (bean != null) {
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
map.put(key+"" , beanMap.get(key));
}
}
return map;
}
}
4.调用案例
@PostMapping("/pdfReport")
public ResponseEntity<byte[]> pdfReport() throws Exception {
// 获取模板(工程目录)
// Resource resource = resourceLoader.getResource("classpath:static/jasper/pickingMarkZh_30_Color.jasper");
// InputStream is = resource.getInputStream();
// 获取模板(存储服务器)
String reportName = "pickingMarkZh_30_Color.jasper";
InputStream is = minioService.getFileInputStream(reportName);
//造数据,g 全局数据(需创建全局参数对象)
ExportTestHeadVO exportTestVO = new ExportTestHeadVO();
exportTestVO.setPmax("425W");
exportTestVO.setPalletNo("LRA004131230508762");
exportTestVO.setModuleType("LR5-54HTH-425M");
exportTestVO.setBoxType("PV-LR07A(+1200mm/-1200mm/EV02)-三分体");
exportTestVO.setCellType("Hi-MO4 NEW 6BB");
exportTestVO.setCurrentClass("M");
exportTestVO.setPickSize("1767*1130*1243mm");
exportTestVO.setFrameColor("黑色/Black");
exportTestVO.setTotalWigth("20.8kg");
exportTestVO.setCellColor("中蓝/medium blue");
exportTestVO.setRemark("Test");
exportTestVO.setCode("1");
//造数据,v 局部数据(需创建局部参数对象)
List<ExportTestLineVO> exportTestLineVOList = new ArrayList<>();
for (int i = 0; i < 36; i++) {
ExportTestLineVO exportTestLineVO = new ExportTestLineVO();
exportTestLineVO.setNo(String.valueOf(i+1));
exportTestLineVO.setModuleId("LRP00413123050190649"+(i+1));
exportTestLineVOList.add(exportTestLineVO);
}
return JasperPrintUtils.getreportToPdf(is, exportTestVO, exportTestLineVOList);
}
5.前端调用
export function printTest1() {
return bizRequest({
responseType: 'blob',
url: '/api/biz/demo/pdfReport',
method: 'post'
}).then(response => {
// 提取文件名
const blob = new Blob([response.data], { type: response.data.type });
handleBlobPrint(blob);
});
}
export function handleBlobPrint(blob: Blob) {
const { closeLoading } = useAppStore();
closeLoading();
// 生成临时 URL
const fileURL = window.URL.createObjectURL(blob);
// 创建隐藏的 iframe
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = fileURL;
document.body.appendChild(iframe);
// 等待 iframe 加载完成后再触发打印
iframe.onload = () => {
const contentWindow = iframe.contentWindow as Window;
contentWindow.addEventListener('afterprint', () => {
document.body.removeChild(iframe);
window.URL.revokeObjectURL(fileURL);
});
contentWindow.print();
};
}
6.注意事项
ireport中动态拓展字段的描述必须恢复默认设置,否则会提示找不到该变量