zoukankan      html  css  js  c++  java
  • freemarker模板引擎

    一。 freemarker简介

        在互联网软件内容网站中 一般首页的访问量大,为了提供首页的访问效率,一般 首页的内容以及其中的新闻等信息都可以实现html静态化 浏览器访问时 设置浏览器的缓存策略和生成静态页面的周期一致 可以使访问效率大大提升 同时配合cdn处理图片 js css等资源 可以在首页访问时 理论完全脱离数据库  降低应用压力

      原理图:

       

    实际应用案例

      比如 新闻门户网站  后台添加新闻时  通过新闻数据+预定义的模板ftl 生成静态的html  新闻数据插入数据库 绑定该html新闻保存的html位置 如果该新闻被推送到首页 

    生成首页静态html时  将该新闻的超链接指向 该文章的静态html

    下图访问服务(nginx集群+cdn缓存+后台应用服务器  MQ表示队列)



    二 。freeemarker模板语法

     freemarker的模板 ftl为后缀 语法类似于jsp的标签

    添加 hellworld.ftl

    <#---------------------freemarker注释-->
    <#--定义变量-->
    <#assign id=1 name='zs' sex='boy' ifSuc=true>
    我的名字是:${name} 性别是 ${sex}<br/>
    <#---------------------定义数组-->
    <#assign hobbyArr=['篮球','足球','排球']>
    <#---------------------if语句 判断变量是否存在-->
    <#if hobbyArr??>
       hobbyArr变量存在<br/>
    </#if>
    <#--------------------- 循环语句 
     for循环 
     foreach
      临时变量 _index表示当前的下标
      临时变量 _has_next表示是否还有下一个值
      #break表示终止循环
    -->
    <#list 1..9 as i>
       ${i}
    </#list>
    <br/>
    <#list hobbyArr as hobby>
      下标是:${hobby_index} 值:${hobby} <br/>
      <#if !hobby_has_next>已经是最后一个<#break></#if>
    </#list>
    <br/>
    <#----------------------include包含会覆盖当前ftl中相同名字的变量-->
    <#include "inc.ftl">
      ${name}
    <#----------------------import包含模板 使用一个别名来控制包含文件中变量的作用于  
        访问时使用 inc.变量名不会覆盖当前ftl变量-->  
    <#import "inc.ftl" as inc>
    ${inc.name}
    <br/>
    <#----------------------macro宏类似于java中的方法 定义不会执行 调用才会执行 定义参数可以给默认值
        比如 addCalc p1 p2=10  如果调用不传入p2 默认就是10
    -->
    <#macro addCalc p1 p2=10>
     <#if p2=0 && p1=0>
        <#return>
     </#if>
       输出结果为:${p1+p2}
    </#macro>
    <@addCalc p1=100 p2=300/>
    <@addCalc p1=567 p2=123/>
    <@addCalc p1=567/>
    <@addCalc p1=0 p2=0/>
    <br/>
    <#--macro中使用嵌套 #nested将 调用宏 body内容嵌套进入-->
    <#macro myuser name>
      您的姓名是:${name}<br/>
      <#nested name?length>
    </#macro>
    <@myuser name='zs';len>名字长度:${len}</@myuser>
    <br/>
    <#----------------------字符串的转义处理
    -->
    ${"我的名字是"zs""}
    ${r"我的名字是:${name}"}<#--字符串的${}添加了r表示是纯文本 直接输出不解析-->
    

    添加一个包含的ftl  inc.ftl

    <#assign id=2 name='ls' sex='girl'>

    freemarker内置的处理函数(http://freemarker.org/docs/ref_builtins.html)

    通过在一个ftl添加  ${aa?aa} 出错后 在错误堆栈中打印了所有函数

    freemarker.core.ParseException: Syntax error in template "helloworld.ftl" in line 61, column 6:
    Unknown built-in: "aa". Help (latest version): http://freemarker.org/docs/ref_builtins.html; you're using FreeMarker 2.3.26-incubating.
    The alphabetical list of built-ins:
    abs, ancestors, api, 
    boolean, byte, 
    c, cap_first, capitalize, ceiling, children, chop_linebreak, chunk, contains, counter, 
    date, date_if_unknown, datetime, datetime_if_unknown, default, double, 
    ends_with, ensure_ends_with, ensure_starts_with, esc, eval, exists, 
    first, float, floor, 
    groups, 
    has_api, has_content, has_next, html, 
    if_exists, index, index_of, int, interpret, is_boolean, is_collection, is_collection_ex, is_date, is_date_like, is_date_only, is_datetime, is_directive, is_enumerable, is_even_item, is_first, is_hash, is_hash_ex, is_indexable, is_infinite, is_last, is_macro, is_markup_output, is_method, is_nan, is_node, is_number, is_odd_item, is_sequence, is_string, is_time, is_transform, is_unknown_date_like, iso, iso_h, iso_h_nz, iso_local, iso_local_h, iso_local_h_nz, iso_local_m, iso_local_m_nz, iso_local_ms, iso_local_ms_nz, iso_local_nz, iso_m, iso_m_nz, iso_ms, iso_ms_nz, iso_nz, iso_utc, iso_utc_fz, iso_utc_h, iso_utc_h_nz, iso_utc_m, iso_utc_m_nz, iso_utc_ms, iso_utc_ms_nz, iso_utc_nz, item_cycle, item_parity, item_parity_cap, 
    j_string, join, js_string, json_string, 
    keep_after, keep_after_last, keep_before, keep_before_last, keys, 
    last, last_index_of, left_pad, length, long, lower_abc, lower_case, 
    markup_string, matches, 
    namespace, new, next_sibling, no_esc, node_name, node_namespace, node_type, number, number_to_date, number_to_datetime, number_to_time, 
    parent, previous_sibling, 
    remove_beginning, remove_ending, replace, reverse, right_pad, root, round, rtf, 
    seq_contains, seq_index_of, seq_last_index_of, short, size, sort, sort_by, split, starts_with, string, substring, switch, 
    then, time, time_if_unknown, trim, 
    uncap_first, upper_abc, upper_case, url, url_path, 
    values, 
    web_safe, word_list, 
    xhtml, xml
    函数调用 语法为 ${变量?函数名(参数)}

      ${‘  aaa  ’?trim}  
    以下是字符串串函数的用法

    ${'aaa_bbb'?index_of('_')}
    ${'  aaa_bbb  '?trim?length}
    ${'  aaa_bbb  '?upper_case?lower_case}
    ${'aaa_bbb'?split('_')?size}
    ${'aaa_bbb'?replace('_','*')}
    <#if '_aaa'?starts_with('_')>
      _开头
    </#if>

    二 。freeemarker在javase和javaee使用

     1.javase环境下 可以将模板+数据的结果生成html 输出到指定位置

    maven中添加freemarker依赖

    <dependency>
      <groupId>org.freemarker</groupId>
      <artifactId>freemarker</artifactId>
      <version>2.3.26-incubating</version>
    </dependency>
    添加测试类 main方法中添加:

    		Configuration cfg = new Configuration(Configuration.VERSION_2_3_26);
    		cfg.setDirectoryForTemplateLoading(new File("src/main/resources"));
    		cfg.setObjectWrapper(new DefaultObjectWrapper(Configuration.VERSION_2_3_26));
    		Map root = new HashMap();
    		root.put("user", "Big Joe");
    		Template temp = cfg.getTemplate("test.ftl");
    		Writer out = new OutputStreamWriter(System.out);
    		temp.process(root, out);
    		out.flush();
    

    src/main/resources仙剑test.ftl

    <html>
    <head>
      <title>Welcome!</title>
    </head>
    <body>
      <h1>Welcome ${user?default('')}!</h1>
    </body>
    运行main方法发现输出了 对应的网页

     2.javaee环境下 使用freemarkerservlet寻找ftl文件并输出 

    javaee下部署访问页面的结构图 (MVC)


    freemarker也支持上述模型

    maven 添加依赖包  同上

    添加一个servlet   映射路径 /t  web.xml添加:

    <servlet>
        <description></description>
        <display-name>TestSErvlet</display-name>
        <servlet-name>TestSErvlet</servlet-name>
        <servlet-class>webtest.TestSErvlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>TestSErvlet</servlet-name>
        <url-pattern>/t</url-pattern>
      </servlet-mapping>
    配置freemarkerservlet web.xml添加

    <servlet>
        <servlet-name>freemarker</servlet-name>
        <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
        <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;charset=UTF-8</param-value>  <!--响应的数据类型-->
        </init-param>  
        <init-param>  
            <param-name>template_update_delay</param-name>  
            <param-value>0</param-value>  
        </init-param>  
        <init-param>  
            <param-name>default_encoding</param-name>  
            <param-value>UTF-8</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><!--所有ftl都经过该servlet-->
      </servlet-mapping>
    maven项目 /src/main/java/webapps随便添加一个模板 test.ftl

    <html>
    <head>
      <title>Welcome!</title>
    </head>
    <body>
      <h1>Welcome ${user?default('')}!</h1>
      <p>Our latest product:
      <a href="${latestProduct.url?default('')}">${latestProduct.name?default('')}</a>
      ${user}
      <#if sex='0'>
        body
      </#if>
        <#assign id=1><br/>
      ${id}
      
      <#macro users name>
         这是用户:${name}
      </#macro>
      
      <@users name='zs'></@users>
      <@users name='ls'></@users>
    </body>
    </html>  
    自定义的servlet类 /t doGet中添加

    package webtest;
    
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class TestSErvlet
     */
    public class TestSErvlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public TestSErvlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    		Map latest = new HashMap();
    		latest.put("url", "products/greenmouse.html");
    		latest.put("name", "green mouse");
    		request.setAttribute("user", "Big Joe");
    		request.setAttribute("latestProduct", latest);
    		request.setAttribute("sex", "1");
    		request.getRequestDispatcher("/test.ftl").forward(request, response);  
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    

    浏览器访问 http://localhost:端口/上下文路径/t  发现模板内容输出

    可以使用java代码自定义方法和宏 具体参考官方文档

    定义方法 过程:

    添加方法java类MyMethod

    package webtest;
    
    
    import java.util.List;
    
    
    import freemarker.template.SimpleNumber;
    import freemarker.template.TemplateMethodModelEx;
    import freemarker.template.TemplateModelException;
    
    
    public class MyMethod implements TemplateMethodModelEx {
    
    
    	public Object exec(List arguments) throws TemplateModelException {
    		if (arguments.size() != 2) {
                throw new TemplateModelException("Wrong arguments");
            }
    		SimpleNumber p1=(SimpleNumber)arguments.get(0);
    		SimpleNumber p2=(SimpleNumber)arguments.get(1);
    		return p1.getAsNumber().intValue()+p2.getAsNumber().intValue();
    	}
    
    
    }

    在 request设置值时 添加

    request.setAttribute("myAdd", new MyMethod());

    ftl文件中 可以

      ${myAdd(1,2)}

    三。 freemarker插件安装

      freemarkder插件的下载地址为 :https://sourceforge.net/projects/freemarker-ide/files/freemarker-ide/

     下载freemarker-ide-0.9.14.zip (909.6 kB)

      解压后目录 植入 eclipse/plugsin目录即可 



    编辑ftl文件后 会出现提示  




  • 相关阅读:
    c#中this的一种特殊用法(extension method)
    Use a String.Format format and transform its output to its inputs?
    c#项目中遇到的add event 的一个小例子
    抽象类可以定义常量,接口中不可以定义常量
    c# 浅拷贝与深拷贝
    定制Dictionary
    c#中object字节问题
    编译过程知识的小补习
    抽象耦合
    控件集合属性遇到的问题
  • 原文地址:https://www.cnblogs.com/liaomin416100569/p/9331180.html
Copyright © 2011-2022 走看看