<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Terry.Li-彬

    虛其心,可解天下之問;專其心,可治天下之學;靜其心,可悟天下之理;恒其心,可成天下之業(yè)。

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      143 隨筆 :: 344 文章 :: 130 評論 :: 0 Trackbacks

    FreeMarker 自定義標簽 收藏

    Directives

    Java programmers can implement user-defined directives in Java using the TemplateDirectiveModel interface. See in the API documentation.

    Note

    TemplateDirectiveModel was introduced in FreeMarker 2.3.11, replacing the soon to be depreciated TemplateTransformModel.

    Example 1

    We will implement a directive which converts all output between its start-tag and end-tag to upper case. Like, this template:

    foo
    <@upper>
    bar
    <#-- All kind of FTL is allowed here -->
    <#list ["red", "green", "blue"] as color>
    ${color}
    </#list>
    baaz
    </@upper>
    wombat?

    will output this:

    foo
    BAR
    RED
    GREEN
    BLUE
    BAAZ
    wombat?

    This is the source code of the directive class:

    package com.example;
    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;

    /**
    * FreeMarker user-defined directive that progressively transforms
    * the output of its nested content to upper-case.
    *
    *
    * <p><b>Directive info</b></p>
    *
    * <p>Directive parameters: None
    * <p>Loop variables: None
    * <p>Directive nested content: Yes
    */
    public class UpperDirective 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);
    }

    public void flush() throws IOException {
    out.flush();
    }

    public void close() throws IOException {
    out.close();
    }
    }

    }?

    Now we still need to create an instance of this class, and make this directive available to the template with the name "upper" (or with whatever name we want) somehow. A possible solution is to put the directive in the data-model:

    root.put("upper", new com.example.UpperDirective());?

    But typically it is better practice to put commonly used directives into the Configuration as shared variables.

    It is also possible to put the directive into an FTL library (collection of macros and like in a template, that you include or import in other templates) using the new built-in:

    <#-- Maybe you have directives that you have implemented in FTL -->
    <#macro something>
    ...
    </#macro>

    <#-- Now you can't use <#macro upper>, but instead you can: -->
    <#assign upper = "com.example.UpperDirective"?new()>?

    Example 2

    我們將創(chuàng)建一個指令的執(zhí)行指定的次數(shù)(同樣列出指令)隨意分隔與一個<hr> - S的repetations輸出,其嵌套的內(nèi)容,再學習。 讓我們把這種指令“重復”。 例如模板:

    <#assign x = 1>

    <@repeat count=4>
    Test ${x}
    <#assign x = x + 1>
    </@repeat>

    <@repeat count=3 hr=true>
    Test
    </@repeat>

    <@repeat count=3; cnt>
    ${cnt}. Test
    </@repeat>?

    Output:

      Test 1
    Test 2
    Test 3
    Test 4

    Test
    <hr> Test
    <hr> Test

    1. Test
    2. Test
    3. Test
    ?

    The class:

    package com.example;
    import java.io.IOException;
    import java.io.Writer;
    import java.util.Iterator;
    import java.util.Map;

    import freemarker.core.Environment;
    import freemarker.template.SimpleNumber;
    import freemarker.template.TemplateBooleanModel;
    import freemarker.template.TemplateDirectiveBody;
    import freemarker.template.TemplateDirectiveModel;
    import freemarker.template.TemplateException;
    import freemarker.template.TemplateModel;
    import freemarker.template.TemplateModelException;
    import freemarker.template.TemplateNumberModel;

    /**
    * FreeMarker user-defined directive for repeating a section of a template,
    * optionally with separating the output of the repetations with
    * <tt>&lt;hr></tt>-s.
    *
    *
    * <p><b>Directive info</b></p>
    *
    * <p>Parameters:
    * <ul>
    * <li><code>count</code>: The number of repetations. Required!
    * Must be a non-negative number. If it is not a whole number then it will
    * be rounded <em>down</em>.
    * <li><code>hr</code>: Tells if a HTML "hr" element could be printed between
    * repetations. Boolean. Optional, defaults to <code>false</code>.
    * </ul>
    *
    * <p>Loop variables: One, optional. It gives the number of the current
    * repetation, starting from 1.
    *
    * <p>Nested content: Yes
    */
    public class RepeatDirective implements TemplateDirectiveModel {

    private static final String PARAM_NAME_COUNT = "count";
    private static final String PARAM_NAME_HR = "hr";

    public void execute(Environment env,
    Map params, TemplateModel[] loopVars,
    TemplateDirectiveBody body)
    throws TemplateException, IOException {

    // ---------------------------------------------------------------------
    // Processing the parameters:

    int countParam = 0;
    boolean countParamSet = false;
    boolean hrParam = false;

    Iterator paramIter = params.entrySet().iterator();
    while (paramIter.hasNext()) {
    Map.Entry ent = (Map.Entry) paramIter.next();

    String paramName = (String) ent.getKey();
    TemplateModel paramValue = (TemplateModel) ent.getValue();

    if (paramName.equals(PARAM_NAME_COUNT)) {
    if (!(paramValue instanceof TemplateNumberModel)) {
    throw new TemplateModelException(
    "The \"" + PARAM_NAME_HR + "\" parameter "
    + "must be a number.");
    }
    countParam = ((TemplateNumberModel) paramValue)
    .getAsNumber().intValue();
    countParamSet = true;
    if (countParam < 0) {
    throw new TemplateModelException(
    "The \"" + PARAM_NAME_HR + "\" parameter "
    + "can't be negative.");
    }
    } else if (paramName.equals(PARAM_NAME_HR)) {
    if (!(paramValue instanceof TemplateBooleanModel)) {
    throw new TemplateModelException(
    "The \"" + PARAM_NAME_HR + "\" parameter "
    + "must be a boolean.");
    }
    hrParam = ((TemplateBooleanModel) paramValue)
    .getAsBoolean();
    } else {
    throw new TemplateModelException(
    "Unsupported parameter: " + paramName);
    }
    }
    if (!countParamSet) {
    throw new TemplateModelException(
    "The required \"" + PARAM_NAME_COUNT + "\" paramter"
    + "is missing.");
    }

    if (loopVars.length > 1) {
    throw new TemplateModelException(
    "At most one loop variable is allowed.");
    }

    // Yeah, it was long and boring...

    // ---------------------------------------------------------------------
    // Do the actual directive execution:

    Writer out = env.getOut();
    if (body != null) {
    for (int i = 0; i < countParam; i++) {
    // Prints a <hr> between all repetations if the "hr" parameter
    // was true:
    if (hrParam && i != 0) {
    out.write("<hr>");
    }

    // Set the loop variable, if there is one:
    if (loopVars.length > 0) {
    loopVars[0] = new SimpleNumber(i + 1);
    }

    // Executes the nested body (same as <#nested> in FTL). In this
    // case we don't provide a special writer as the parameter:
    body.render(env.getOut());
    }
    }
    }

    }?

    Notices

    這是非常重要的一TemplateDirectiveModel對象通常不應該有狀態(tài)。 典型的錯誤是對在該對象的字段指令調(diào)用執(zhí)行狀態(tài)儲存。 對同一指令,或者指令嵌套調(diào)用看成是由多個線程同時訪問共享變量使用的對象。

    可惜的是,TemplateDirectiveModel,就做不支持傳遞參數(shù)按位置(而不是名稱)。 這是固定的起價FreeMarker的2.4。

    posted on 2010-08-07 18:11 禮物 閱讀(5324) 評論(3)  編輯  收藏 所屬分類: Freemarker

    評論

    # re: FreeMarker 自定義標簽[未登錄] 2013-05-09 19:40 selina
    copy 別人文章也不帶個鏈接.  回復  更多評論
      

    # re: FreeMarker 自定義標簽 2013-06-20 17:55 四海
    感謝!  回復  更多評論
      

    # re: FreeMarker 自定義標簽 2014-12-18 14:55 zuidaima
    freemarker demo教程源代碼下載:http://zuidaima.com/share/kfreemarker-p1-s1.htm  回復  更多評論
      


    只有注冊用戶登錄后才能發(fā)表評論。

    網(wǎng)站導航:
     
    主站蜘蛛池模板: 成年男女男精品免费视频网站 | aa级一级天堂片免费观看| 久久精品亚洲AV久久久无码| 永久免费bbbbbb视频| 中文字幕在线免费看| 亚洲冬月枫中文字幕在线看| 国产一级一片免费播放i| 丝袜足液精子免费视频| 亚洲中文字幕在线无码一区二区| 免费国产a国产片高清网站| 久久香蕉国产线看免费| 亚洲爆乳无码精品AAA片蜜桃| 国产AV无码专区亚洲AV手机麻豆| 最近免费中文字幕大全免费| 国产亚洲视频在线播放大全| 久久精品国产亚洲av麻豆小说| 国产精品色午夜视频免费看| 午夜不卡久久精品无码免费 | 亚洲av高清在线观看一区二区 | 久久久久久久久亚洲| 2021免费日韩视频网| 无码一区二区三区免费| 亚洲国产精品综合福利专区| 久久精品国产亚洲av水果派| 国产亚洲美女精品久久久| 免费夜色污私人影院在线观看| 国产最新凸凹视频免费| 免费观看a级毛片| 最新69国产成人精品免费视频动漫| 免费观看的毛片大全 | 亚洲国产精品lv| 亚洲国产精品久久久久网站| 亚洲精品在线观看视频| 亚洲AV无码专区亚洲AV伊甸园| 国产V亚洲V天堂无码| 亚洲成AV人片在线观看无| 午夜亚洲国产理论秋霞| 亚洲国语精品自产拍在线观看| 久久久久久a亚洲欧洲AV| 亚洲资源在线视频| 性xxxx黑人与亚洲|