• FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写
  • Template + data model = output

     Hello world
           FreeMarkerTest.java
import java.io.StringWriter;import java.util.HashMap;import java.util.Locale;
 
import freemarker.template.Configuration;import freemarker.template.Template;
publicclass FreeMarkerTest 
{
    publicstaticvoid main(String[] args)
{
        FreeMarkerTest test 
= new FreeMarkerTest();
        test.sayHello(
"Hermit");
    }

 
    publicvoid sayHello(String name)
{
        Configuration freemarkerCfg 
= new Configuration();
        freemarkerCfg.setClassForTemplateLoading(
this.getClass(), "/");
 
        freemarkerCfg.setEncoding(Locale.getDefault(), 
"UTF-8");
        Template template;
        Locale.setDefault(Locale.ENGLISH);
        
try{
            template 
= freemarkerCfg.getTemplate("Hello.ftl");
            template.setEncoding(
"UTF-8");
            HashMap root 
= newHashMap();
            root.put(
"user", name);
 
            StringWriter writer 
= newStringWriter();
            template.process(root, writer);
            System.out.println(writer.toString());
        }
catch(Exception e){
            e.printStackTrace();
        }
}

 
 
 
}

 


Hello.ftl
Hello ${user}!

输出 :

Hello Hermit!

空值的处理
在我们的程序中难免会碰到值为空的时候,如果用一个空值直接去替换模板中的标记,freemarker会毫不犹豫的抛出异常,并把错误信息直接写到
输出结果里。为了对付这种情况我们有几种写法

Hello ${user!}!
Hello ${user?if_exists}
Hello ${user!'your name'}!
Hello ${user?default('your name')}

  输入:test.sayHello(null);
  输出:
Hello !
Hello 
Hello your name!
Hello your name

freemarker国际化模板

freemarker支持多语言国际化,只要把模板名称按照java资源文件的写法就可以了,也就是name_语言_国家地区.ftl 如果找不到对应的语言,就会用默
认语言的模板。

import java.io.StringWriter;import java.util.HashMap;import java.util.Locale;
 
import freemarker.template.Configuration;import freemarker.template.Template; 
publicclass FreeMarkerTest 
{
    publicstaticvoid main(String[] args)
{
        FreeMarkerTest test 
= new FreeMarkerTest();
        test.sayHello(
"hermit",Locale.CHINA);
        test.sayHello(
"hermit",Locale.ENGLISH);
    }

 
    publicvoid sayHello(String name,Locale locale)
{
        Configuration freemarkerCfg 
= new Configuration();
        freemarkerCfg.setClassForTemplateLoading(
this.getClass(), "/");
 
        freemarkerCfg.setEncoding(Locale.getDefault(), 
"UTF-8");
        Template template;
        Locale.setDefault(Locale.ENGLISH);
        
try{
            template 
= freemarkerCfg.getTemplate("Hello.ftl",locale);
            template.setEncoding(
"UTF-8");
            HashMap root 
= newHashMap();
            root.put(
"user", name);
 
            StringWriter writer 
= newStringWriter();
            template.process(root, writer);
            System.out.println(writer.toString());
        }
catch(Exception e){
            e.printStackTrace();
        }
}

 
 
 
}

  • 默认语言模版:Hello.ftl --Hello ${user!}!
  • 中文模版:Hello_zh_CN.ftl    -你好 ${user!}!

输出:
你好 hermit!
Hello hermit!


在struts项目中使用freemarker
       1、引入freemarker.jar
       2、web.xml加入

<!-- FreeMarker view servlet (to replace JSP) -->
<servlet>
   
<servlet-name>freemarker</servlet-name>
   
<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
      
<!-- FreemarkerServlet settings: -->
      
<init-param>
           
<param-name>TemplatePath</param-name>
           
<param-value>/</param-value>
     
</init-param>
     
<init-param>
         
<param-name>NoCache</param-name>
     
<param-value>true</param-value>
     
</init-param>
     
<init-param>
          
<param-name>ContentType</param-name>
      
<param-value>text/html</param-value>
     
</init-param>
       
<!-- FreeMarker settings: -->
      
<init-param>
           
<param-name>template_update_delay</param-name>
       
<param-value>0</param-value>
       
<!-- 0 is for development only! Use higher value otherwise. -->
      
</init-param>
      
<init-param>
           
<param-name>default_encoding</param-name>
       
<param-value>utf-8</param-value>
    
</init-param>
      
<init-param>
          
<param-name>locale</param-name>
      
<param-value>en_US</param-value>
      
</init-param>
      
<init-param>
          
<param-name>number_format</param-name>
          
<param-value>0.##########</param-value>
       
</init-param>
       
<load-on-startup>1</load-on-startup>
   
</servlet>
    
<servlet-mapping>
       
<servlet-name>freemarker</servlet-name>
       
<url-pattern>*.ftl</url-pattern>
    
</servlet-mapping>

 

3、一个示例页面
<html>
<head><title>Say Hello</title>
<METAHTTP-EQUIV="Content-Type"CONTENT="text/html; charset=utf-8">
</head>
<body>
<h1>Hello ${user}!</h1>
</body>
</html>


我们完全可以用freemarker的模板取代JSP页面。用freemarker的模板看起更简洁,可读性更强。比如现在struts2的UI标签就是用freemarker做的。

freemarker用struts标签做国际化

  • 示例模板
 
<#assign  html =JspTaglibs["/WEB-INF/struts-html.tld"]>
<#assign  bean =JspTaglibs["/WEB-INF/struts-bean.tld"]>
<#assign  logic =JspTaglibs["/WEB-INF/struts-logic.tld"]>
<html>
<head><title> FreeMarker Struts Example </title>
<metahttp-equiv ="Content-type"content ="text/html; charset=utf-8">
</ head >
<body>
<@bean.message key ="hello"  arg0 ="hermit"/>
</body>
</html> 
 
主要是引入标签的时候要这样写: <#assign html =JspTaglibs["/WEB-INF/struts-html.tld"]>
 
freemarker直接使用资源文件进行多语言国际化
 
publicclass FreeMarkerTest 
{
    publicstaticvoid main(String[] args)
{
        FreeMarkerTest test 
= new FreeMarkerTest();
        test.sayHello(
"hermit",Locale.CHINA);
        test.sayHello(
"hermit",Locale.ENGLISH);
    }

 
    publicvoid sayHello(String name,Locale locale)
{
        Configuration freemarkerCfg 
= new Configuration();
        freemarkerCfg.setClassForTemplateLoading(
this.getClass(), "/");
 
        freemarkerCfg.setEncoding(Locale.getDefault(), 
"UTF-8");
        Template template;
        Locale.setDefault(Locale.ENGLISH);
        
try{
            template 
= freemarkerCfg.getTemplate("Hello.ftl");
            template.setEncoding(
"UTF-8");
            HashMap root 
= newHashMap();
            root.put(
"user", name);
            ResourceBundle RESOURCE_BUNDLE 
= ResourceBundle.getBundle("ApplicationResources",locale);
            ResourceBundleModel rsbm 
= new ResourceBundleModel(RESOURCE_BUNDLE,new BeansWrapper());
            root.put(
"bundle", rsbm);
            StringWriter writer 
= newStringWriter();
            template.process(root, writer);
            System.out.println(writer.toString());
        }
catch(Exception e){
            e.printStackTrace();
        }
}

}

  • 模板
    ${bundle("hello","hermit")}
  • 默认语言资源文件
 
hello=Hello {0}\!
 
  • 中文资源文件
 
hello=你好 {0}\!
  • 输出
 
你好 hermit!
Hello hermit!
 

关键的地方就是用ResourceBundleModel把ResourceBundle转换一下。

常用的2种加载模板的方式

  • 普通java类根据当前class上下文环境加载模板
 
cfg.setClassForTemplateLoading(this.getClass(), "/");
 
  • 在web项目中根据servlet上下文环境加载模板
 
cfg.setServletContextForTemplateLoading(this.getServlet().getServletContext(), "/");