项目准备:先去down个freemarker.jar包, http://freemarker.org/freemarkerdownload.html
上篇讨论了代码生成器的原理,输出=模板+数据,那么现在就生成一个Student.java文件做个简单例子。
首先先写出模板,先解决一个问题,上篇有讲到属性名首字母大写的问题
由于freemarker中不支持将首字母大写(属性名中用到),那么自己先写一个自定义宏如下:
package com; import java.io.IOException; import java.io.Writer; import java.util.Map; import freemarker.core.Environment; import freemarker.template.TemplateDirectiveBody; import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateException; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; public class UpperFirstCharacter implements TemplateDirectiveModel { public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { // Check if no parameters were given: if (!params.isEmpty()) { throw new TemplateModelException( "This directive doesn't allow parameters."); } if (loopVars.length != 0) { throw new TemplateModelException( "This directive doesn't allow loop variables."); } // If there is non-empty nested content: if (body != null) { // Executes the nested body. Same as <#nested> in FTL, except // that we use our own writer instead of the current output writer. body.render(new UpperCaseFilterWriter(env.getOut())); } else { throw new RuntimeException("missing body"); } } /** * A {@link Writer} that transforms the character stream to upper case * and forwards it to another {@link Writer}. */ private static class UpperCaseFilterWriter extends Writer { private final Writer out; UpperCaseFilterWriter (Writer out) { this.out = out; } public void write(char[] cbuf, int off, int len) throws IOException { // char[] transformedCbuf = new char[len]; // for (int i = 0; i < len; i++) { // transformedCbuf[i] = Character.toUpperCase(cbuf[i + off]); // } // out.write(transformedCbuf); cbuf[0] = Character.toUpperCase(cbuf[0]); out.write(String.valueOf(cbuf).trim());///把右边空格去掉 } public void flush() throws IOException { out.flush(); } public void close() throws IOException { out.close(); } } }
下面呢就可以编写模板了,代码如下:
package ${package}; //这个地方可以事先定义好需要的类 import java.util.Date; import java.io.Serializable; public class ${className} implements Serializable{ <#list properties as pro> private ${pro.proType} ${pro.proName}; </#list> <#list properties as pro> public void set<@upperFC>${pro.proName}</@upperFC>(${pro.proType} ${pro.proName}){ this.${pro.proName}=${pro.proName}; } public ${pro.proType} get<@upperFC>${pro.proName}</@upperFC>(){ return this.${pro.proName}; } </#list> }
模板文件取名为javabean.html,在com包下
下面编写测试类:
package com; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; public class Test { /** * @param args */ public static void main(String[] args) { //System.out.println(System.getProperty("user.dir")+"============"); Configuration cfg = new Configuration(); try { cfg.setClassForTemplateLoading(Test.class, "/com");//指定模板所在的classpath目录 cfg.setSharedVariable("upperFC", new UpperFirstCharacter());//添加一个"宏"共享变量用来将属性名首字母大写 Template t = cfg.getTemplate("javabean.html");//指定模板 FileOutputStream fos = new FileOutputStream(new File("d:/Student.java"));//java文件的生成目录 //模拟数据源 Map data = new HashMap(); data.put("package", "edu");//包名 data.put("className", "Student"); List pros = new ArrayList(); Map pro_1 = new HashMap(); pro_1.put("proType", String.class.getSimpleName()); pro_1.put("proName", "name"); pros.add(pro_1); Map pro_2 = new HashMap(); pro_2.put("proType", String.class.getSimpleName()); pro_2.put("proName", "sex"); pros.add(pro_2); Map pro_3 = new HashMap(); pro_3.put("proType", Integer.class.getSimpleName()); pro_3.put("proName", "age"); pros.add(pro_3); data.put("properties", pros); t.process(data, new OutputStreamWriter(fos,"utf-8"));// fos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); } catch (TemplateException e) { e.printStackTrace(); } } }
运行一下测试类,在D盘可以找到一个Student.java的文件,打开看看对不对
package freemarker;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;
public class Test1 {
private Configuration cfg;
public Configuration getCfg() {
return cfg;
}
public void init() throws Exception {
cfg = new Configuration();
cfg.setDirectoryForTemplateLoading(new File("bin/freemaker"));
}
public static void main(String[] args) throws Exception {
Test1 obj = new Test1();
obj.init();
Map root = new HashMap();
Template t = obj.getCfg().getTemplate("Test.ftl");
Writer out = new OutputStreamWriter(new FileOutputStream("Test.html"), "GBK");
t.process(root, out);
System.out.println("Successfull................");
}
}
4 使用到的'静态'模板 Test.ftl
<#macro greet person,website>
Hello ${person}! Your Website is ${website}.
</#macro>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<@greet person="fff" website="www.ffff.com"/>
</body>
</html>
5 运行结果
<html>
<head>
<title>Hello World</title>
</head>
<body>
HelloYour Website is <a target="_blank" href="www.ffff.com">www.ffff.com</a>
</body>
</html>
======================================================================
步骤:
1、在工程中引入freemark的jar包。
2、写一个freemark页面模板,如:freemarkForWebTemplate.ftl,该文件以ftl为后缀。我就以一个最简单的为例子:
freemarkForWebTemplate.ftl内容为:
hello ,${name}
3、在struts的action里写转载的逻辑:
//得到配置对象
Configuration configuration = new Configuration();
//设置生成模板加载方式(由servletcontext生成)
configuration.setServletContextForTemplateLoading(this.getServletContext(), "WEB-INF/template(你模板的位置)");
//生成数据模型
Map root = new HashMap();
root.put("name(你模板中的变量以上面模板为例)", "world");
//得到模板
Template template = configuration.getTemplate("freemarkForWebTemplate.ftl(你的模板名)");
try {
//输出模板
template.process(root, resp.getWriter());
} catch (TemplateException e) {
e.printStackTrace();
}
这样你就行了,否用的struts1,如果是strus2的话更简单。