JasperReports入門教程(二):中文打印
背景
在上一篇中我們介紹了JasperReport的基本入門,也展示了一個報表。但是我們的示例都是使用的英文,如果我們把需要打印的數據改為中文會怎么樣?下面我們就測試一下
HashMap<String, Object> parameters = new HashMap<String, Object>();
parameters.put("name", "小明");
預覽的pdf界面會發現原來打印name的地方不顯示任何數據了
為什么會出現這個問題呢?我們查找net.sf.jasperreports的jar包源碼發現它並不包含中文的字體庫。那么就好辦了,我們只需要加上中文字體庫就可以了。
給JasperReport Studio工具增加字體
1.我們可以在本地電腦的 C:\Windows\Fonts下找到你想要的字體文件,也可以使用我提供的字體文件微軟雅黑
msyh.ttf文件下載,提取碼: bvmn
2.在JasperReport Studio工具的Window -> Preferences-> font 中add一個微軟雅黑的字體
3.修改模板中需要顯示中文的元素的字體為微軟雅黑
給JasperReport增加擴展的字體資源文件
1.在resources資源文件下增加fonts.xml和msyh.ttf字體文件
- fonts.xml配置微軟雅黑的字體
<?xml version="1.0" encoding="UTF-8"?>
<fontFamilies>
<fontFamily name="微軟雅黑">
<normal>jaspers/fonts/msyh.ttf</normal>
<bold>jaspers/fonts/msyh.ttf</bold>
<italic>jaspers/fonts/msyh.ttf</italic>
<boldItalic>jaspers/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>
</fontFamily>
</fontFamilies>
2.在resources資源文件下增加讀取擴展字體的配置文件 jasperreports_extension.properties
- 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.dejavu=jaspers/fonts/fonts.xml
配置好的代碼結構如下
3.訪問地址 http://localhost:8080/test/jasper?type=pdf 可以看到中文打印出來了
實現原理
下面我們來分析下為什么需要按照上面來配置。因為JasperReport的jar包並未提供微軟雅黑的字體的支持,所以我們需要通過提供的字體擴展的接口把我們需要的微軟雅黑的字體在程序運行時可以讀取到。
其中核心的類就是SimpleFontExtensionsRegistryFactory
,我們查看下這個類的源碼
public class SimpleFontExtensionsRegistryFactory implements ExtensionsRegistryFactory
{
public final static String SIMPLE_FONT_FAMILIES_PROPERTY_PREFIX =
DefaultExtensionsRegistry.PROPERTY_REGISTRY_PREFIX + "simple.font.families.";
public final static String PROPERTY_SIMPLE_FONT_FAMILIES_REGISTRY_FACTORY =
DefaultExtensionsRegistry.PROPERTY_REGISTRY_FACTORY_PREFIX + "simple.font.families";
@Override
public ExtensionsRegistry createRegistry(String registryId, JRPropertiesMap properties)
{
List<PropertySuffix> fontFamiliesProperties = JRPropertiesUtil.getProperties(properties, SIMPLE_FONT_FAMILIES_PROPERTY_PREFIX);
List<String> fontFamiliesLocations = new ArrayList<String>();
for (Iterator<PropertySuffix> it = fontFamiliesProperties.iterator(); it.hasNext();)
{
PropertySuffix fontFamiliesProp = it.next();
//String fontFamiliesName = fontFamiliesProp.getSuffix();
String fontFamiliesLocation = fontFamiliesProp.getValue();
//fontFamiliesLocations.addAll(SimpleFontExtensionHelper.getInstance().loadFontFamilies(fontFamiliesLocation));
fontFamiliesLocations.add(fontFamiliesLocation);
}
return new FontExtensionsRegistry(fontFamiliesLocations);
}
}
這個類比較簡單只有一個方法,這個createRegistry
方法就是讀取配置文件中net.sf.jasperreports.extension.simple.font.families
開頭的配置項的字體文件。
那么追溯這個createRegistry
方法在什么地方使用的,可以追溯到類DefaultExtensionsRegistry
中的instantiateRegistry
方法
查看這個方法可以發現它是加載實現了ExtensionsRegistryFactory
接口的某一個類,並且調用instantiateRegistry
方法來讀取的配置項,這里就是上面提到的SimpleFontExtensionsRegistryFactory
類。
繼續向上追溯到類DefaultExtensionsRegistry
中的loadRegistries
方法,這個方法是加載所有的通過擴展注冊進來配置,當然也包括通過擴展注冊的字體。
這個方法的代碼行較多,我就不貼出來了,那么我們關注下這個方法其中一行代碼
List<ClassLoaderResource> extensionResources = loadExtensionPropertyResources();
這行代碼是獲取所有需要加載的配置文件資源,通過代碼我們可以發現它最終是加載所有名稱是jasperreports_extension.properties
的文件,然后解析文件中的配置項並注冊到JasperReport中
protected List<ClassLoaderResource> loadExtensionPropertyResources()
{
return JRLoader.getClassLoaderResources(EXTENSION_RESOURCE_NAME);
}
/**
* The name of property file resources that are used to load JasperReports
* extensions.
*/
public final static String EXTENSION_RESOURCE_NAME = "jasperreports_extension.properties";
到這里我們應該理解上面配置文件jasperreports_extension.properties中的配置項的意義。
##這行配置項是說明需要使用哪個注冊工廠類來解析下面的配置項
net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
##這行配置是配置了需要加載的字體文件的位置,配合上面的```SimpleFontExtensionsRegistryFactory```類來加載字體文件。
net.sf.jasperreports.extension.simple.font.families.dejavu=jaspers/fonts/fonts.xml
結束語
因為方便后續教程的演示,我們把公用的代碼包括中文字體的支持都提起到一個公共的模塊common,其他模塊只引用即可使用,這樣可以更好的專注本章節的代碼。