freemarker自定义标签并生成html静态页面

利用freemarker标签生成静态页面时,有时候没有静态页面处理 需要自定义标签来简化处理;

实现步骤:

  主要通过实现TemplateDirectiveModel接口来实现

repeat.ftl标签代码:

-----------要求后台返回一个字符串-----------
 <@repeat1 returnType='string'>
   ${returnParam}
</@repeat1>

-----------要求后台返回一个指定大小的的list-----------
<@repeat1 returnType='list' size=5>

   <#list returnParam as param>
     ===${param.name}
  </#list>
</@repeat1> 

-----------要求后台返回一个map-----------
<@repeat1 returnType='map' >
    ${returnParam.name}
</@repeat1>  

java代码:

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.core.Environment;   
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateDirectiveBody;   
import freemarker.template.TemplateDirectiveModel;   
import freemarker.template.TemplateException;   
import freemarker.template.TemplateModel;   
/**  
 * FreeMarker 自定义标签实现重复输出内容体。  
 */  
public class RepeatDirective implements TemplateDirectiveModel {   

	
    public void execute(Environment env, Map params, TemplateModel[] loopVars,   
            TemplateDirectiveBody body) throws TemplateException, IOException {   
    	env.setAutoFlush(true);
        String returnType=""+params.get("returnType");
        if(returnType.equals("string")){
        	env.setVariable("returnParam", new DefaultObjectWrapper().wrap("自定义标签返回的字符串 "));
        }
        if(returnType.equals("list")){
            Map<String, TemplateModel> paramWrap = new HashMap<String, TemplateModel>(params);
            List list = new ArrayList();
            int size =Integer.parseInt(params.get("size")+"");
            for(int i=0;i<size;i++){
           	  Map root = new HashMap();
        	  root.put("name", "return list item "+i);
        	  list.add(root);
            }
        	env.setVariable("returnParam", new DefaultObjectWrapper().wrap(list));
        }
        
        if(returnType.equals("map")){
        	Map root = new HashMap();
        	root.put("name", "return map===========");
        	
        	env.setVariable("returnParam", new DefaultObjectWrapper().wrap(root));
        }
        body.render(env.getOut());
    }   
    
    
    /**  
     * @param templatePath 模板文件存放目录 
     * @param htmlPath html路径  
     * @param templateName 模板文件名称   
     * @param root 数据模型根对象  
     * @param templateEncoding 模板文件的编码方式  
     *  
     */  
    public static void processTemplate(String templatePath,String htmlPath, String templateName, String templateEncoding, Map<?,?> root){   
        try {   
            Configuration config=new Configuration();   
            // 设置要解析的模板所在的目录,并加载模板文件  
            File file=new File(templatePath);   
            // 设置包装器,并将对象包装为数据模型   
            config.setDirectoryForTemplateLoading(file); 
            // 获取模板,并设置编码方式,这个编码必须要与页面中的编码格式一致   
            config.setObjectWrapper(new DefaultObjectWrapper());   
            // 合并数据模型与模板   
            Template template=config.getTemplate(templateName,templateEncoding);   
          
            OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(htmlPath),"UTF-8");    
            template.process(root, out);   
            out.flush();   
            out.close();  
        } catch (IOException e) {   
            e.printStackTrace();   
        }catch (TemplateException e) {   
            e.printStackTrace();   
        }   
    } 
    
    public static void main(String[] args) {
    	Map<String,Object> root=new HashMap<String, Object>();   
        root.put("repeat1", new RepeatDirective());  // repeat1为页面上需要访问的标签名称        
    	processTemplate(
    			"WebRoot\\WEB-INF\\template",//模板路径
    			"WebRoot\\WEB-INF\\template\\repeat.html",//html保存路径
    			"repeat.ftl", "gb2312", 
    			root);
    }
}  



执行main方法后输出的html内容为:

-----------要求后台返回一个字符串-----------
    自定义标签返回的字符串 

-----------要求后台返回一个指定大小的的list-----------

     ===return list item 0
     ===return list item 1
     ===return list item 2
     ===return list item 3
     ===return list item 4

-----------要求后台返回一个map-----------
    return map===========

-----------要求后台返回一个map-----------
    return map===========
  


以上只是一个简单的demo;

在实际生成环境使用中,一般将freemarker与spring结合使用,可以将自定义的标签交给spring容器进行管理,然后在业务层注入自定义的标签;

spring配置文件参考配置方法:

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

	<!-- freemarker标签配置 --><!-- 此处配置freemarker标签 -->
	<!-- 文章列表标签 -->
	<bean id="data_list"
		class="自定义标签的包名">
	</bean>

	<!-- freemarker 控制上下文方式加载。(可自定义编写) -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
		<property name="prefix" value="" />
		<property name="suffix" value=".ftl" />
		<property name="exposeSpringMacroHelpers" value="true" />
		<property name="contentType" value="text/html;charset=UTF-8" />
	</bean>
	<!-- freemarker 配置文件加载 -->
	<bean id="freeMarkerConfigurer"
		class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
		<property name="freemarkerVariables">
			<map>
				<!-- 此处映射freemarker标签 与配置标签时的id名相同 -->
				<entry key="data_list" value-ref="data_list" />
			</map>
		</property>
		<property name="templateLoaderPath" value="" />
		<!-- freemarker格式管理 -->
		<property name="freemarkerSettings">
			<props>
				<prop key="tag_syntax">auto_detect</prop><!-- 此处配置模版里标签的显示方式为<>或[] ,注意模版内标签显示方式不可混用。此处设置为自动匹配 -->
				<prop key="template_update_delay">5</prop>
				<prop key="defaultEncoding">UTF-8</prop>
				<prop key="url_escaping_charset">UTF-8</prop>
				<prop key="locale">zh_CN</prop>
				<prop key="boolean_format">true,false</prop>
				<prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
				<prop key="date_format">yyyy-MM-dd</prop>
				<prop key="time_format">HH:mm:ss</prop>
				<prop key="number_format">0.######</prop>
				<prop key="whitespace_stripping">true</prop>
			</props>
		</property>
	</bean>
</beans>

spring service代码结构:

@Component("staticPageSvc")
public class StaticPageSvcImpl implements StaticPageSvc, InitializingBean {
	@Resource(name = "freeMarkerConfigurer") //与spring配置文件中beanId保持一致
	private FreeMarkerConfigurer freeMarkerConfigurer;

	public Configuration getFreeMarkerConfigurer() {
		return freeMarkerConfigurer.getConfiguration();
	}
	public void setFreeMarkerConfigurer(FreeMarkerConfigurer freeMarkerConfigurer) {
		this.freeMarkerConfigurer = freeMarkerConfigurer;
	}
	public void html(String tempPath, String htmlPath, Map<String, Object> data) throws IOException, TemplateException {
		long time = System.currentTimeMillis();
		if (data == null)
			data = new HashMap<String, Object>();
		File f = new File(htmlPath.substring(0, htmlPath.lastIndexOf("/") + 1));
		if (!f.exists())
			f.mkdirs();
		f = new File(htmlPath);
		if (!f.exists())
			f.createNewFile();
		Writer out = null;
		try {
			out = new OutputStreamWriter(new FileOutputStream(f), "UTF-8");
			Template template = getFreeMarkerConfigurer().getTemplate(tempPath);//spring 注入getFreeMarkerConfigurer()
			template.process(data, out);
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
		}
		
	}
}


ftl中使用方法:

	  <@data_list param1="xx" param2="8">
	         <#list tag_list as article>
		                
	          </#list>
	     </@data_list>


data_list为spring文件中配置 ,tag_list 为标签返回的参数,相当于demo中的returnParam


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值