您的当前位置:首页正文

关于Freemarker生成静态html文件及中文乱码的问题

2020-08-17 来源:钮旅网


关于Freemarker生成静态html文件及中文乱码的问题

先看生成静态html文件:

FreeMarker允许Java servlet保持图形设计同应用程序逻辑的分离,这是通过在模板中密封HTML完成的。模板用servlet提供的数据动态地生成 HTML。模板语言是强大的直观的,编译器速度快,输出接近静态HTML页面的速度。

FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写

FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序

虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据

FreeMarker不是一个Web应用框架,而适合作为Web应用框架一个组件

FreeMarker与容器无关,因为它并不知道HTTP或Servlet;FreeMarker同样可以应用于非Web应用程序环境

FreeMarker更适合作为Model2框架(如Struts)的视图组件,你也可以在模板中使用JSP标记库

FreeMarker是免费的

模板:

查看文章: ${newsitem.title}

cellspacing=\"0\"

cellpadding=\"2\"

${newsitem.title} ( ${newsitem.addtime} )

返回

        


${newsitem.showContent}


代码:

import java.io.*;

import java.util.HashMap;

import java.util.Map;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import freemarker.template.*;

/*

* Created on 2005-4-7

*

*/

/**

* 测试FreeMarker.

*

* @author scud

*

*/

public class FreeMarkerTest

{

private final Log logger = LogFactory.getLog(getClass());

private Configuration freemarker_cfg = null;

public static void main(String[] args)

{

//@todo 自己的一个类

NewsItem aItem = null;

//@todo 装入新闻

//NewsItem = loadNewsItem(1);

FreeMarkerTest test = new FreeMarkerTest();

Map root = new HashMap();

root.put(\"newsitem\", aItem);

String sGeneFilePath = \"/tpxw/\";

String sFileName = \"1.htm\";

boolean bOK = test.geneHtmlFile(\"/tpxw/view.ftl\",root,

sGeneFilePath,sFileName);

}

/**

* 获取freemarker的配置. freemarker本身支持classpath,目录和从ServletContext获取.

*/

protected Configuration getFreeMarkerCFG()

{

if (null == freemarker_cfg)

{

// Initialize the FreeMarker configuration;

// - Create a configuration instance

freemarker_cfg = new Configuration();

// - FreeMarker支持多种模板装载方式,可以查看API文档,都很简单:路径,根据Servlet上下文,classpath等等

//htmlskin是放在classpath下的一个目录

freemarker_cfg.setClassForTemplateLoading(this.getClass(), \"/htmlskin\");

}

return freemarker_cfg;

}

/**

* 生成静态文件.

*

* @param templateFileName 模板文件名,相对htmlskin路径,例如\"/tpxw/view.ftl\"

* @param propMap 用于处理模板的属性Object映射

* @param htmlFilePath 要生成的静态文件的路径,相对设置中的根路径,例如 \"/tpxw/1/2005/4/\"

* @param htmlFileName 要生成的文件名,例如 \"1.htm\"

*/

public boolean geneHtmlFile(String templateFileName,Map propMap, String htmlFilePath,String htmlFileName )

{

//@todo 从配置中取得要静态文件存放的根路径:需要改为自己的属性类调用

String sRootDir = \"e:/webtest/htmlfile\" ;

try

{

Template t = getFreeMarkerCFG().getTemplate(templateFileName);

//如果根路径存在,则递归创建子目录

creatDirs(sRootDir,htmlFilePath);

File afile = new File(sRootDir +\"/\" +htmlFilePath + \"/\" + htmlFileName);

Writer out = new FileOutputStream(afile)));

t.process(propMap, out);

}

catch (TemplateException e)

{

logger.error(\"Error while templateFileName,e);

return false;

}

catch (IOException e)

new OutputStreamWriter(new

processing FreeMarker template \" +

BufferedWriter(

{

logger.error(\"Error while generate Static Html File \" + htmlFileName,e);

return false;

}

return true;

}

/**

* 创建多级目录

*

* @param aParentDir String

* @param aSubDir 以 / 开头

* @return boolean 是否成功

*/

public static boolean creatDirs(String aParentDir, String aSubDir)

{

File aFile = new File(aParentDir);

if (aFile.exists())

{

File aSubFile = new File(aParentDir + aSubDir);

if (!aSubFile.exists())

{

return aSubFile.mkdirs();

}

else

{

return true;

}

}

else

{

return false;

}

}

}

编码的问题

这里说的是编码的问题。项目使用的都是UTF-8编码,生成的文件在UTF-8编码下察看是乱码,而GBK正常(后来发现因为我用的中文操作系统所以用GBK查看正常)。

当然我把Freemarker的配置都改成了UTF-8,我的模版文件也是UTF-8编码的。下面是原来的代码

public void setTemplatePath(Resource templatePath) {

this.templatePath = templatePath; //设置freemarker的参数 freemarkerCfg = new Configuration(); try { freemarkerCfg.setDirectoryForTemplateLoading(this.templatePath.getFile()); freemarkerCfg.setObjectWrapper(new DefaultObjectWrapper()); freemarkerCfg.setDefaultEncoding(\"UTF-8\"); } catch (IOException ex) { throw new SystemException(\"No Directory found,please check you config.\"); } } /** * 生成静态文件

* @param templateFileName 模版名称eg:(biz/order.ftl) * @param propMap 用于处理模板的属性Object映射 * @param htmlFilePath 要生成的静态文件的路径,相对设置中的根路径,例如 \"/biz/2006/5/\" * @param htmlFileName 要生成的文件名,例如 \"123.htm\" * @return */ private boolean buildHtml(String templateFileName,Map propMap, String htmlFilePath,String htmlFileName){ try { Template template = freemarkerCfg.getTemplate(templateFileName); template.setEncoding(\"UTF-8\"); //创建生成文件目录 creatDirs(buildPath.getFilename(),htmlFilePath);

File htmlFile = new File(buildPath + htmlFilePath + htmlFileName); Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile))); template.process(propMap,out); out.flush(); return true; } catch (TemplateException ex){ log.error(\"Build Error\"+templateFileName,ex); return false; } catch (IOException e) { log.error(\"Build Error\"+templateFileName,e); return false; } }

下面是修改之后的代码

/** * 生成静态文件 * @param templateFileName 模版名称eg:(biz/order.ftl) * @param propMap 用于处理模板的属性Object映射 * @param htmlFilePath 要生成的静态文件的路径,相对设置中的根路径,例如 \"/biz/2006/5/\" * @param htmlFileName 要生成的文件名,例如 \"123.htm\" * @return */ private boolean buildHtml(String templateFileName,Map propMap, String htmlFilePath,String htmlFileName){ try { Template template = freemarkerCfg.getTemplate(templateFileName);

template.setEncoding(\"UTF-8\"); //创建生成文件目录 creatDirs(buildPath.getFilename(),htmlFilePath); File htmlFile = new File(buildPath + htmlFilePath + htmlFileName); Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile),\"UTF-8\")); template.process(propMap,out); out.flush(); return true; } catch (TemplateException ex){ log.error(\"Build Error\"+templateFileName,ex); return false; } catch (IOException e) { log.error(\"Build Error\"+templateFileName,e);

return false; } } 原因就在于OutputStreamWriter的不同构造方法

OutputStreamWriter(OutputStream out) 创建使用默认字符编码的 OutputStreamWriter。 OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的 OutputStreamWriter。 这个是中文JDK的文档说明,刚开始我使用默认的构造函数,所以使用了系统默认的编码,GBK,所以在生成静态文件的时候把UTF-8内容用GBK编码写入了,所以在UTF-8下浏览就有问题。

还有关于修改模版文件同样也要注意这个问题。

public String loadTemplate(String templateName) { StringBuffer sb = new StringBuffer();

try { File file = new File(templatePath+\"/\"+templateName); BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),\"UTF-8\")); String line = reader.readLine(); while(line != null) { sb.append(line); sb.append(\"/r/n\"); line = reader.readLine(); } reader.close(); } catch (IOException e) { throw new SystemException(\"Loading template Error:\}

return sb.toString(); } public void saveTemplate(String templateName, String templateContent) {

try {

File file = new File(templatePath + \"/\" + templateName);

Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),\"UTF-8\"));

out.write(templateContent);

out.flush();

//扔出templatesave事件

TemplateSaveEvent evt = new TemplateSaveEvent();

evt.setTemplateName(templateName);

dispatchTemplateEvent(evt);

} catch (IOException e) {

throw new SystemException(\"Write template Error\

}

}

因篇幅问题不能全部显示,请点此查看更多更全内容