激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 使用Java進行FreeMarker的web模板開發的基礎教程

使用Java進行FreeMarker的web模板開發的基礎教程

2020-04-07 11:44rensanning JAVA教程

這篇文章主要介紹了使用Java進行FreeMarker模板引擎開發的基礎教程,文中針對FreeMarker的網頁標簽用法給出了一些例子,需要的朋友可以參考下

一、概述

FreeMarker 是一個模板引擎,一個基于模板生成文本輸出的通用工具,使用純 Java 編寫,FreeMarker 被設計用來生成 HTML Web 頁面,特別是基于 MVC 模式的應用程序,雖然 FreeMarker 具有一些編程的能力,但通常由 Java 程序準備要顯示的數據,由FreeMarker 生成頁面,通過模板顯示準備的數據(如下圖)

使用Java進行FreeMarker的web模板開發的基礎教程

FreeMarker 不是一個 Web 應用框架,而適合作為 Web 應用框架一個組件。FreeMarker 與容器無關,因為它并不知道 HTTP 或 Servlet;FreeMarker 同樣可以應用于非Web應用程序環境,FreeMarker 更適合作為 Model2 框架(如 Struts)的視圖組件,你也可以在模板中使用 JSP標記庫。另外,FreeMarker是免費的。

二、Freemarker的準備條件

    freemarker.2.3.16.jar,下載地址這里就不貼了..(這個jar包其實在struts2里面)


三、Freemarker生成靜態頁面的原理

    Freemarker 生成靜態頁面,首先需要使用自己定義的模板頁面,這個模板頁面可以是最最普通的html,也可以是嵌套freemarker中的 取值表達式, 標簽或者自定義標簽等等,然后后臺讀取這個模板頁面,解析其中的標簽完成相對應的操作, 然后采用鍵值對的方式傳遞參數替換模板中的的取值表達式,做完之后 根據配置的路徑生成一個新的html頁面, 以達到靜態化訪問的目的。


四、Freemarker提供的標簽

Freemarker提供了很多有用 常用的標簽,Freemarker標簽都是<#標簽名稱>這樣子命名的,${value} 表示輸出變量名的內容 ,具體如下:

1、list:該標簽主要是進行迭代服務器端傳遞過來的List集合,比如:

?
1
2
3
<#list nameList as names> 
 ${names} 
</#list>

name是list循環的時候取的一個循環變量,freemarker在解析list標簽的時候,等價于:

?
1
2
3
for (String names : nameList) {
  System.out.println(names);
}

2、if:該標簽主要是做if判斷用的,比如:

?
1
2
3
<#if (names=="陳靖仇")>
 他的武器是: 十五~~
</#if>

這個是條件判斷標簽,要注意的是條件等式必須用括號括起來, 等價于:

?
1
2
3
if(names.equals("陳靖仇")){
  System.out.println("他的武器是: 十五~~");
}


3、include:該標簽用于導入文件用的。

?
1
<#include "include.html"/>

這個導入標簽非常好用,特別是頁面的重用。

另外在靜態文件中可以使用${} 獲取值,取值方式和el表達式一樣,非常方便。

下面舉個例子(static.html):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
 
描述:${description}
<br/>
集合大小:${nameList?size}
<br/>
迭代list集合:
<br/>
<#list nameList as names>
這是第${names_index+1}個人,叫做:<label style="color:red">${names}</label>
if判斷:
<br/>
<#if (names=="陳靖仇")>
 他的武器是: 十五~~
<#elseif (names=="宇文拓")>    <#--注意這里沒有返回而是在最后面--> 
 他的武器是: 軒轅劍~·
<#else>
她的絕招是:蠱毒~~
</#if>
<br/>
</#list>
迭代map集合:
<br/>
<#list weaponMap?keys as key>
key--->${key}<br/>
value----->${weaponMap[key]!("null")}
<#-- 
fremarker 不支持null, 可以用! 來代替為空的值。
其實也可以給一個默認值 
value-----${weaponMap[key]?default("null")}
還可以 在輸出前判斷是否為null
<#if weaponMap[key]??></#if>都可以
-->
 
<br/>
</#list>
include導入文件:
<br/>
<#include "include.html"/>
 
</body>
</html>

實際代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.chenghui.test;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
 
public class CreateHtml {
  public static void main(String[] args) {
    try {
      //創建一個合適的Configration對象
      Configuration configuration = new Configuration();
      configuration.setDirectoryForTemplateLoading(new File("D:\\project\\webProject\\WebContent\\WEB-INF\\template"));
      configuration.setObjectWrapper(new DefaultObjectWrapper());
      configuration.setDefaultEncoding("UTF-8");  //這個一定要設置,不然在生成的頁面中 會亂碼
      //獲取或創建一個模版。
      Template template = configuration.getTemplate("static.html");
      Map<String, Object> paramMap = new HashMap<String, Object>();
      paramMap.put("description", "我正在學習使用Freemarker生成靜態文件!");
       
      List<String> nameList = new ArrayList<String>();
      nameList.add("陳靖仇");
      nameList.add("玉兒");
      nameList.add("宇文拓");
      paramMap.put("nameList", nameList);
       
      Map<String, Object> weaponMap = new HashMap<String, Object>();
      weaponMap.put("first", "軒轅劍");
      weaponMap.put("second", "崆峒印");
      weaponMap.put("third", "女媧石");
      weaponMap.put("fourth", "神農鼎");
      weaponMap.put("fifth", "伏羲琴");
      weaponMap.put("sixth", "昆侖鏡");
      weaponMap.put("seventh", null);
      paramMap.put("weaponMap", weaponMap);
       
      Writer writer = new OutputStreamWriter(new FileOutputStream("success.html"),"UTF-8");
      template.process(paramMap, writer);
       
      System.out.println("恭喜,生成成功~~");
    } catch (IOException e) {
      e.printStackTrace();
    } catch (TemplateException e) {
      e.printStackTrace();
    }
     
  }
}


    這樣子基本上可以算的上可以簡單的去做一點簡單的生成了,但是要在實際中去運用,還是差的很遠的,因為freemarker給的標簽完全滿足不了我們的需要,這時候就需要自定義標簽來完成我們的需求了。。
五、Freemarker自定義標簽

Freemarker自定義標簽就是自己寫標簽,然后自己解析,完全由自己來控制標簽的輸入輸出,極大的為程序員提供了很大的發揮空間。

基于步驟:

       以前寫標簽需要在<后加# ,但是freemarker要識別自定義標簽需要在后面加上@,然后后面可以定義一些參數,當程序執行template.process(paramMap, out);,就會去解析整個頁面的所有的freemarker標簽。

     自定義標簽 需要自定義一個類,然后實現TemplateDirectiveModel,重寫execute方法,完成獲取參數,根據參數do something等等。。

    將自定義標簽與解析類綁定在一起需要在paramMap中放入該解析類的實例,存放的key與自定義標簽一致即可。。

    注意:在自定義標簽中,如果標簽內什么也沒有,開始標簽和結束標簽絕對不能再同一行,不然會報錯 

?
1
freemarker.log.JDK14LoggerFactory$JDK14Logger error

  我曾經上當過,這是freemarker 存在的bug。

下面是static.html的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#--自定義變量-->
<#assign num='hehe'/>
${num}
<br/>
自定義標簽
 <@content name="chenghui" age="120">
  ${output}
  ${append}
 </@content>
  
</body>
</html>


下面是上面的static.html模板的解析類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package com.chenghui.test;
 
import static freemarker.template.ObjectWrapper.DEFAULT_WRAPPER;
 
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;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
 
/**
 * 自定義標簽解析類
 * @author Administrator
 *
 */
public class ContentDirective implements TemplateDirectiveModel{
 
  private static final String PARAM_NAME = "name";
  private static final String PARAM_AGE = "age";
   
  @Override
  public void execute(Environment env, Map params,TemplateModel[] loopVars,
      TemplateDirectiveBody body) throws TemplateException, IOException {
    if(body==null){
      throw new TemplateModelException("null body");
    }else{
      String name = getString(PARAM_NAME, params);
      Integer age = getInt(PARAM_AGE, params);
      //接收到參數之后可以根據做具體的操作,然后將數據再在頁面中顯示出來。
      if(name!=null){
        env.setVariable("output", DEFAULT_WRAPPER.wrap("從ContentDirective解析類中獲得的參數是:"+name+", "));
      }
      if(age!=null){
        env.setVariable("append", DEFAULT_WRAPPER.wrap("年齡:"+age));
      }
      Writer out = env.getOut();
      out.write("從這里輸出可以再頁面看到具體的內容,就像document.writer寫入操作一樣。<br/>");
      body.render(out);
       
      /*
      如果細心的話,會發現頁面上是顯示out.write()輸出的語句,然后再輸出output的內容,
      可見 在body在解析的時候會先把參數放入env中,在頁面遇到對應的而來表單時的才會去取值
      但是,如果該表單時不存在,就會報錯, 我覺得這里freemarker沒有做好,解析的時候更加會把錯誤暴露在頁面上。
      可以這樣子彌補${output!"null"},始終感覺沒有el表達式那樣好。
      */
    }
  }
   
  /**
   * 獲取String類型的參數的值
   * @param paramName
   * @param paramMap
   * @return
   * @throws TemplateModelException
   */
  public static String getString(String paramName, Map<String, TemplateModel> paramMap) throws TemplateModelException{
    TemplateModel model = paramMap.get(paramName);
    if(model == null){
      return null;
    }
    if(model instanceof TemplateScalarModel){
      return ((TemplateScalarModel)model).getAsString();
    }else if (model instanceof TemplateNumberModel) {
      return ((TemplateNumberModel)model).getAsNumber().toString();
    }else{
      throw new TemplateModelException(paramName);
    }
  }
   
  /**
   *
   * 獲得int類型的參數
   * @param paramName
   * @param paramMap
   * @return
   * @throws TemplateModelException
   */
  public static Integer getInt(String paramName, Map<String, TemplateModel> paramMap) throws TemplateModelException{
    TemplateModel model = paramMap.get(paramName);
    if(model==null){
      return null;
    }
    if(model instanceof TemplateScalarModel){
      String str = ((TemplateScalarModel)model).getAsString();
      try {
        return Integer.valueOf(str);
      } catch (NumberFormatException e) {
        throw new TemplateModelException(paramName);
      }
    }else if(model instanceof TemplateNumberModel){
      return ((TemplateNumberModel)model).getAsNumber().intValue();
    }else{
      throw new TemplateModelException(paramName);
    }
  }
}

然后再前面的實際代碼中加上:

?
1
2
//自定義標簽解析
paramMap.put("content", new ContentDirective());

這樣子基本上可以使用,freemarker完成自定義標簽了,解決一寫簡單的業務邏輯, 但是在實際的項目中不可能這樣子去做,因為還沒有和spring進行集成使用,每次都需要在解析的時候把解析類的實例放進去。。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 91情侣在线偷精品国产 | 欧美国产一区二区三区 | 最新av网址在线观看 | 天天躁狠狠躁夜躁2020挡不住 | 国产一级性生活视频 | 久久久久久久久久性 | 91午夜少妇三级全黄 | 爱爱视频天天干 | 欧美视频一二三区 | 91九色网址 | 亚洲影视在线观看 | 最新在线黄色网址 | 久久性生活免费视频 | 爱逼爱操综合网 | 亚洲精品无码不卡在线播放he | 一级电影在线观看 | 久久久一区二区三区四区 | 91精品国产综合久久久欧美 | 国产羞羞网站 | 羞羞答答影院 | 精品国产高清一区二区三区 | 免费a级观看 | 免费在线性爱视频 | 91精品国产综合久久久动漫日韩 | 成年免费视频黄网站在线观看 | 欧美成人三级大全 | 国产精品久久久久久久久久东京 | 免费a级毛片永久免费 | 天天操天天看 | av观看国产 | 毛片一级网站 | 91精品国产92久久久久 | 亚洲综人网 | 免费一级欧美大片视频 | 91免费视频版 | 蜜桃传免费看片www 一本色道精品久久一区二区三区 | 国产免费看 | 国产精品久久久久久久久久iiiii | 亚洲网站在线播放 | 操操操日日日干干干 | 91久久国产综合精品女同国语 |