傳統報表直連資料庫寫 SQL,缺點明顯:
解決方案:Java Bean → XML (Betwixt) → JasperReport,實現純內存、面向對象、可測試的報表數據準備。
public class Person {
private String name;
private String gender;
private int age;
// getter/setter 省略
}
public class NameList {
private List list;
// getter/setter
}
import org.apache.commons.betwixt.io.BeanWriter;
import java.io.*;
public class BeanToXMLConverter {
private static final String FILE_PATH = "c:/test.xml";
public static void main(String[] args) throws Exception {
// 構建對象圖
Person p1 = new Person(); p1.setName("張三"); p1.setGender("男"); p1.setAge(35);
Person p2 = new Person(); p2.setName("李四"); p2.setGender("女"); p2.setAge(25);
NameList nameList = new NameList();
nameList.setList(Arrays.asList(p1, p2));
// 轉換並寫文件
new BeanToXMLConverter().writeToXMLFile(nameList);
}
private void writeToXMLFile(Object obj) throws Exception {
StringWriter outputWriter = new StringWriter();
outputWriter.write("\n");
BeanWriter beanWriter = new BeanWriter(outputWriter);
// 配置:基本類型輸出為元素而非屬性、不生成 id、美化縮進
beanWriter.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(false);
beanWriter.getBindingConfiguration().setMapIDs(false);
beanWriter.enablePrettyPrint();
beanWriter.write(obj); // 核心轉換
// 寫入文件
File xmlFile = new File(FILE_PATH);
if (!xmlFile.exists()) xmlFile.createNewFile();
try (FileWriter fw = new FileWriter(xmlFile)) {
fw.write(outputWriter.toString());
}
System.out.println(outputWriter.toString()); // 控制台輸出預覽
}
}
<dependency>
<groupId>commons-betwixt</groupId>
<artifactId>commons-betwixt</artifactId>
0.8
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils-core</artifactId>
1.8.3
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
3.2.2
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
1.2
</dependency>
JDK 1.5+ (需泛型支援)
張三
男
35
李四
女
25
| 優點 | 缺點/關注點 |
|---|---|
| 面向對象開發,業務邏輯集中在 Java 代碼 | 增加對象→XML 序列化開銷 (CPU/內存) |
| 數據可讀、可版本控制、可單元測試 | 大數據量時 XML 文件過大、解析慢 |
| 報表模板與數據源解耦,易於 Mock 測試 | Betwixt 老舊項目,現代可用 Jackson/JAXB/XStream |
| 無需資料庫環境,適合離線/嵌入式場景 | 複雜對象圖 (循環引用) 需額外配置 |
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
2.15.2
</dependency>
// 使用
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
String xml = xmlMapper.writeValueAsString(nameList);
// 更快、更標準、支援注解 (@JsonProperty, @JacksonXmlRootElement 等)
「對象 → XML → 報表」模式讓報表開發回歸面向對象本質:業務邏輯在 Java 中完成,XML 只是中間傳遞格式。Betwixt 雖屬老牌庫,但原理通用。現代項目推薦 Jackson XML 或 JAXB 替代,性能更優、生態更活。核心思想不變:報表數據準備層與報表渲染層分離,數據源標準化為 XML/JSON。