zoukankan      html  css  js  c++  java
  • FreeMarker的用法

    freemark就是一个对静态页面上的标签进行动态解析、填充数据的一个框架。

    • 语法(转:http://zhuyuehua.iteye.com/blog/1975251): 

    1. freemarker获取list的size :
    Java

    ArrayList<String> list = new ArrayList<String>();

    Freemaker

    ${list?size}

    2. list的遍历:

    <#list animals as being>
    <tr>
    <td>${being.name}${being.price}<td>
    </tr>
    </#list>

    3. 遍历MAP 

    <#list map?keys as k>
    <option value="${k}">${map[k]}</option>
    </#list>

    4.list遍历中的下标序号:

    _index是list的一个属性

    <#list list as a>
    ${a_index}
    </#list> 

    5.取LIST中第i个元素的值

    ${list[i]} 

    嵌套时前面要有括号,如下,将字符串变成list,然后取第i个元素的值

    ${(str?split(","))[i]} 

    6. list的嵌套:

    <#list jsskList as jsskVO>
    <#list kcList as kcVO>
    <#if kcVO.kch=jsskVO.kch> (kcVO里有编号和名称,而jsskVO里只有编号)
    ${kcVO.kcm} 
    </#if>
    </#list>
    </#list>

    7. list排序:

    升序 .sort_by()

    <#list list?sort_by("字段") as x>
    </#list>

    降序 .sort_by()?reverse

    <#list list?sort_by("字段")?reverse as x> 
    </#list>

    8.item_has_next,size使用:

    <#list userList as user>
        <#if !user_has_next>
        共有${userList?size}最后一个用户是:${user.userName}
        </#if>
    </#list>
    • 实际项目中的用法:


    My-SSH-BlogWebContentlog emplate emplate.ftl

      1  <!DOCTYPE HTML>
      2 <html lang="zh-CN">
      3 <head>
      4     <meta charset="UTF-8">
      5     <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1,user-scalable=no">
      6     <title>DX博客</title>
      7     <link rel="stylesheet" type="text/css" media="all" href="${contextPath}/style.css" />
      8     <link rel="stylesheet" type="text/css" media="all" href="${contextPath}/style/css/font-awesome.min.css" />
      9     <link href="http://fonts.googleapis.com/css?family=Open+Sans:400,400italic,300italic,300,700,700italic|Open+Sans+Condensed:300,700" rel="stylesheet" type="text/css">
     10     <!--[if IE 7]>
     11     <link rel="stylesheet" type="text/css" href="${contextPath}/style/css/font-awesome-ie7.min.css"/>
     12     <![endif]-->
     13     <!--[if IE 8]>
     14     <link rel="stylesheet" type="text/css" href="${contextPath}/style/css/ie8.css" media="all" />
     15     <![endif]-->
     16     <!--[if IE 9]>
     17     <link rel="stylesheet" type="text/css" href="${contextPath}/style/css/ie9.css" media="all" />
     18     <![endif]-->
     19     <script type="text/javascript" src="${contextPath}/style/js/jquery-1.7.2.min.js"></script>
     20     <script type="text/javascript" src="${contextPath}/style/js/ddsmoothmenu.js"></script>
     21     <script type="text/javascript" src="${contextPath}/style/js/retina.js"></script>
     22     <script type="text/javascript" src="${contextPath}/style/js/selectnav.js"></script>
     23     <script type="text/javascript" src="${contextPath}/style/js/jquery.backstretch.min.js"></script>
     24     <script type="text/javascript">
     25         $.backstretch("${contextPath}/style/images/bg/16.jpg");
     26     </script>
     27 </head>
     28 <body>
     29 <div class="scanlines"></div>
     30 
     31 <div class="header-wrapper opacity">
     32     <div class="header">
     33         <div class="logo">
     34             <a href="${contextPath}">
     35                 <h1>DX博客</h1>
     36             </a>
     37         </div>
     38 
     39         <div id="menu-wrapper">
     40             <div id="menu" class="menu">
     41                 <ul id="tiny">
     42                     <li class="active">
     43                         <a href="${contextPath}">博客</a>
     44                         <ul>
     45                             <li><a href="${contextPath}/listArticle.action">所有博文</a></li>
     46                         </ul>
     47                     </li>
     48                     <li>
     49                         <a href="#" title="进入我的Github">Github</a>
     50                     </li>
     51                     <li>
     52                         <a href="#" title="进入我的CSDN博客">CSDN博客</a>
     53                     </li>
     54                     <li>
     55                         <a href="${contextPath}/commentUI.action" title="给我留言">留言板</a>
     56                     </li>
     57                     <li><a href="">Menu</a>
     58                         <ul>
     59                             <li><a href="/s/">短网址</a></li>
     60                             <li><a href="/WorkUpload/">作业提交系统</a></li>
     61                         </ul>
     62                     </li>
     63                 </ul>
     64             </div>
     65         </div>
     66         <div class="clear"></div>
     67     </div>
     68 </div>
     69 
     70 <div class="wrapper"><!--
     71     <ul class="social">
     72         <li><a class="rss" href="#" title="博客订阅"></a></li>
     73         <li><a class="qq" href="#" title="QQ"></a></li>
     74         <li><a class="weibo" href="#" title="新浪微博"></a></li>
     75         <li><a class="wechat" href="${contextPath}/public/wechat.jsp" title="微信"></a></li>
     76         <li><a class="email" href="#" title="邮件"></a></li>
     77         <li><a class="phone" href="#" title="手机"></a></li>
     78     </ul>
     79     <div class="intro">Intro...</div>
     80 -->
     81     <div class="content box">
     82         <h1 class="title article-title">${title}</h1>
     83         <div class="info">
     84             <div><a href="${listCategoryArticle}" title="查看该类型博文"><i class="icon-folder-open-alt"></i>:${categoryName}</a></div>
     85             <div><a href=""><i class="icon-user"></i>:${author}</a></div>
     86             <div><i class="icon-time"></i>:${time}</div>
     87         </div>
     88         ${typeString}
     89         ${content}
     90         ${typeString}
     91         <div class="record">
     92             <div>
     93                 <a id="looked" href=""><i class="icon-eye-open"></i> ${looked} 已阅</a>
     94             </div>
     95             &nbsp;&nbsp;
     96             <div>
     97                 <a id="likes" href="javascript:like('${contextPath}/likeAction.action?artid=${articleId}')"><i class="icon-heart-empty"></i> ${likes} 喜爱</a>
     98             </div>
     99             <a class="comment-btn" href="javascript:onComment('#')"><i class="icon-comments"></i> 给我留言</a>
    100         </div>
    101         <div class="last-next">
    102             <div>
    103                 <a href="${lastArticle.staticUrl}" title="上一篇">
    104                     <i class="icon-double-angle-left"></i>${lastArticle.title}
    105                 </a>
    106             </div>
    107             <div>
    108                 <a href="${nextArticle.staticUrl}" title="下一篇">
    109                     <i class="icon-double-angle-right"></i>${nextArticle.title}
    110                 </a>
    111             </div>
    112         </div>
    113     </div>
    114 
    115     <div class="sidebar box">
    116         <div class="sidebox widget">
    117             <h3 class="widget-title">最近更新</h3>
    118             <ul class="post-list">
    119                 <#list lastArticlesList as la>
    120                     <li>
    121                         <div class="meta">
    122                             <h5><a href="${contextPath}${la.staticUrl}.html">${la.title}</a></h5>
    123                             <em>${la.createDate?string("yyyy-MM-dd HH:mm:ss")}</em>
    124                         </div>
    125                     </li>
    126                 </#list>
    127                 <li class="more"><a href="${contextPath}/listArticle.action">more</a></li>
    128             </ul>
    129         </div>
    130 
    131         <div class="sidebox widget">
    132             <h3 class="widget-title"><i class="icon-search icon"></i></h3>
    133             <form class="searchform" method="post" action="#">
    134                 <input type="text" name="key" value="输入关键字搜索博客..." onFocus="this.value=''" onBlur="this.value='输入关键字搜索博客...'"/>
    135             </form>
    136         </div>
    137 
    138         <div class="sidebox widget">
    139             <h3 class="widget-title categories">分类</h3>
    140             <ul class="categories">
    141                 <#list categoryList as cl>
    142                     <li><a href="${contextPath}/listArticle.action?categoryId=${cl.id}">${cl.title}</a></li>
    143                 </#list>
    144             </ul>
    145         </div>
    146     </div>
    147 
    148     <div class="clear"></div>
    149 
    150 </div>
    151 
    152 <div class="footer-wrapper">
    153     <div id="footer" class="four">
    154         <a href="/s/">短网址</a>&nbsp;&nbsp;
    155         <a href="/WorkUpload/">作业提交系统</a>&nbsp;&nbsp;
    156     </div>
    157 </div>
    158 <div class="site-generator-wrapper">
    159     <div class="site-generator">
    160         Copyright &copy;2017.DX &nbsp;Design by <a href="http://elemisfreebies.com">elemis.</a> All rights reserved.
    161     </div>
    162 </div>
    163 <script type="text/javascript" src="${contextPath}/style/js/scripts.js"></script>
    164 <script type="text/javascript">
    165     function onComment(url){
    166         var form = document.createElement('form');
    167         form.action = url;
    168         form.method = "post";
    169         form.style.display =  "none";
    170 
    171         var input = document.createElement("input");
    172         input.name = "title";
    173         input.value = "${title}";
    174         form.appendChild(input);
    175 
    176         var input2 = document.createElement("input");
    177         input2.name = "articleId";
    178         input2.value = "${articleId}";
    179         form.appendChild(input2);
    180 
    181         document.body.appendChild(form);
    182         form.submit();
    183     }
    184 </script>
    185 </body>
    186 </html>
    View Code

    我访问的对应网址:http://localhost:8080/My-SSH-Blog/blog/5/5-4.html,呈现效果:

    这里我使用的是一个url重写的方式实现的,因此这里博客文章页面的template.ftl的解析过程是在filter中实现的。

    web.xml中定义了filter过滤规则:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3     xmlns="http://java.sun.com/xml/ns/javaee"
     4     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     5     id="WebApp_ID" version="3.0">
     6     <display-name>My-SSH-Blog</display-name>
     7 
     8     <welcome-file-list>
     9         <welcome-file>/index.jsp</welcome-file>
    10     </welcome-file-list>
    11 
    12     <error-page>
    13         <error-code>404</error-code>
    14         <location>/public/404.html</location>
    15     </error-page>
    16     <error-page>
    17         <error-code>500</error-code>
    18         <location>/public/500.html</location>
    19     </error-page>
    20 
    21     <!-- html请求过滤器 -->
    22     <filter>
    23         <filter-name>articleFilter</filter-name>
    24         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    25         <init-param>
    26             <param-name>targetFilterLifecycle</param-name>
    27             <param-value>true</param-value>
    28         </init-param>
    29     </filter>
    30     <filter-mapping>
    31         <filter-name>articleFilter</filter-name>
    32         <url-pattern>*.html</url-pattern>
    33     </filter-mapping>
    34     <filter-mapping>
    35         <filter-name>articleFilter</filter-name>
    36         <url-pattern>*.htm</url-pattern>
    37     </filter-mapping>
    38 
    39     <context-param>
    40         <param-name>contextConfigLocation</param-name>
    41         <param-value>classpath:applicationContext*.xml</param-value>
    42     </context-param>
    43 
    44     <!-- 监听session,在线人员信息(登录账户,不包括访客和前台在线用户) -->
    45     <listener>
    46         <listener-class>com.dx.ssh.listener.SessionListener</listener-class>
    47     </listener>
    48     <!-- Bootstraps the root web application context before servlet initialization -->
    49     <listener>
    50         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    51     </listener>
    52 
    53     <!-- Struts2 filter -->
    54     <filter>
    55         <filter-name>struts2</filter-name>
    56         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    57     </filter>
    58 
    59     <filter-mapping>
    60         <filter-name>struts2</filter-name>
    61         <url-pattern>/*</url-pattern>
    62     </filter-mapping>
    63 
    64     <session-config>
    65         <session-timeout>30</session-timeout>
    66     </session-config>
    67 </web-app>
    View Code

    ArticleFilter.java

      1 package com.dx.ssh.filter;
      2 
      3 import java.io.File;
      4 import java.io.IOException;
      5 import java.util.Map;
      6 import java.util.regex.Matcher;
      7 import java.util.regex.Pattern;
      8 
      9 import javax.servlet.*;
     10 import javax.servlet.http.HttpServletRequest;
     11 import javax.servlet.http.HttpServletResponse;
     12 import javax.servlet.http.HttpSession;
     13 
     14 import org.springframework.web.context.WebApplicationContext;
     15 import org.springframework.web.context.support.WebApplicationContextUtils;
     16 
     17 import com.dx.ssh.service.ArticleService;
     18 import com.dx.ssh.utils.TemplateUtils;
     19 import com.opensymphony.xwork2.ActionContext;
     20 
     21 public class ArticleFilter implements Filter {
     22     public static final String ARTICLE_TOKEN = "view";
     23     private ArticleService articleService;
     24 
     25     public ArticleService getArticleService() {
     26         return articleService;
     27     }
     28 
     29     public void setArticleService(ArticleService articleService) {
     30         this.articleService = articleService;
     31     }
     32 
     33     // protected Object getBean(ServletContext servletContext, String id) {
     34     // WebApplicationContext context =
     35     // WebApplicationContextUtils.getWebApplicationContext(servletContext);
     36     // return context.getBean(id);
     37     // }
     38 
     39     @Override
     40     public void init(FilterConfig filterConfig) throws ServletException {
     41     }
     42 
     43     @Override
     44     public void destroy() {
     45     }
     46 
     47     @Override
     48     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
     49             throws IOException, ServletException {
     50         HttpServletRequest request = (HttpServletRequest) servletRequest;
     51         HttpServletResponse response = (HttpServletResponse) servletResponse;
     52 
     53         // ArticleService articleService = (ArticleService)
     54         // this.getBean(request.getServletContext(), "articleService");
     55 
     56         String path = request.getRequestURL().toString();
     57         // 模式匹配
     58         Pattern pattern = Pattern.compile("/blog/([0-9]+)/([0-9]+)-([0-9]+)");
     59         Matcher matcher = pattern.matcher(path);
     60 
     61         // 不匹配,路径不正确
     62         if (!matcher.find()) {
     63             // 路径不对,报错404
     64             response.sendError(404, "您输入路径的不存在!");
     65             return;
     66         }
     67         // 模版文件绝对路径
     68         String realPath = request.getServletContext().getRealPath("/");
     69         // 文件路径
     70         String filePath = realPath + matcher.group() + ".ftl";
     71 
     72         filePath = realPath + matcher.group() + ".ftl";
     73         filePath = realPath + "blog/template/template.ftl";
     74         filePath = filePath.replace("/", "\");
     75         filePath = filePath.replace("\\", "\");
     76 
     77         System.out.println(filePath);
     78         // 查看服务器资源是否存在
     79         File file = new File(filePath);
     80         if (!file.exists()) {
     81             // 路径不对,报错404
     82             response.sendError(404, "您输入路径的不存在!");
     83             return;
     84         }
     85         // 解析路径中的文章id
     86         int articleId = Integer.parseInt(matcher.group(3));
     87         System.out.println("articleId = " + articleId);
     88 
     89         // 防止同一用户session添加多次访问量
     90         boolean isNew = false;
     91         // 获取当前用户session
     92         HttpSession session = request.getSession();
     93         // 还没看过就能添加访问量
     94         if (session.getAttribute(ARTICLE_TOKEN + articleId) == null) {
     95             isNew = true;
     96             // 设置当前的用户session已经看过文章了
     97             session.setAttribute(ARTICLE_TOKEN + articleId, "true");
     98         }
     99 
    100         // 填充模版信息
    101         Map<String, Object> params = null;
    102         try {
    103             // 得到freemarker模版文件所需参数
    104             params = this.getArticleService().getTemplateParams(articleId, request.getContextPath(), isNew);
    105             params.put("contextPath", request.getContextPath());
    106         } catch (Exception e) {
    107             e.printStackTrace();
    108         }
    109 
    110         String templateDir = realPath + File.separator + "blog";
    111         String templateFile = matcher.group(1) + "/" + matcher.group(2) + "-" + matcher.group(3) + ".ftl";
    112         templateFile = "template/template.ftl";
    113         boolean result = TemplateUtils.parserTemplate(templateDir, templateFile, params, response.getOutputStream());
    114 
    115         if (!result) {
    116             // 服务器异常
    117             response.sendError(500, "服务器未知异常!");
    118         }
    119         response.getOutputStream().close();
    120     }
    121 
    122 }
    View Code

    TemplateUtils.java

     1 package com.dx.ssh.utils;
     2 
     3 import java.io.File;
     4 import java.io.IOException;
     5 import java.io.OutputStream;
     6 import java.io.OutputStreamWriter;
     7 import java.util.Map;
     8 
     9 import freemarker.template.Configuration;
    10 import freemarker.template.Template;
    11 
    12 public class TemplateUtils {
    13     private static Configuration configuration = null;
    14 
    15     private TemplateUtils() {
    16     }
    17 
    18     public static Configuration getConfiguration(String templateDir) throws IOException {
    19         if (configuration == null) {
    20             configuration = new Configuration();
    21             configuration.setDirectoryForTemplateLoading(new File(templateDir));
    22         }
    23         return configuration;
    24     }
    25 
    26     /**
    27      * 向ftl模版中的数据替换
    28      * */ 
    29     public static boolean parserTemplate(String templateDir, String ftlPath, Map<String, Object> map, OutputStream os) {
    30         try {
    31             Template template = getConfiguration(templateDir).getTemplate(ftlPath, "UTF-8");
    32             template.process(map, new OutputStreamWriter(os, "UTF-8"));
    33             return true;
    34         } catch (Exception e) {
    35             e.printStackTrace();
    36             return false;
    37         }
    38     }
    39 }

    模版填充数据类型整理方法:

     1 /**
     2      * 得到freemarker模版文件所需参数
     3      */
     4     @Override
     5     public Map<String, Object> getTemplateParams(int articleId, String contextPath, boolean isNew) {
     6         System.out.println("articleId=" + articleId);
     7         // 要看的文章
     8         ArticleEntity article = getArticleDao().findById(articleId);
     9 
    10         if (article == null || article.getId() <= 0)
    11             return null;
    12 
    13         // 最新三篇文章
    14         List<ArticleEntity> lastArticles = getArticleDao().findAllLastArticle(3);
    15 
    16         // 所有类别
    17         List<ArticleCategoryEntity> categories = getArticleCategoryDao().findAll();
    18 
    19         // 下一篇
    20         ArticleEntity next = null;
    21         List<ArticleEntity> nextArticles = articleDao.findNextArticle(3, article.getCreateDate());
    22         if (nextArticles == null || nextArticles.size() <= 0) {
    23             next = new ArticleEntity();
    24             next.setStaticUrl("#");
    25             next.setTitle("这是最后一篇了哦!");
    26         } else {
    27             next = nextArticles.get(0);
    28             next.setStaticUrl(contextPath + next.getStaticUrl() + ".html");
    29         }
    30 
    31         // 上一篇文章
    32         ArticleEntity last = null;
    33         List<ArticleEntity> lastAs = articleDao.findLastArticle(3, article.getCreateDate());
    34         if (lastAs == null || lastAs.size() <= 0) {
    35             last = new ArticleEntity();
    36             last.setStaticUrl("#");
    37             last.setTitle("这是第一篇哦!");
    38         } else {
    39             last = lastAs.get(0);
    40             last.setStaticUrl(contextPath + last.getStaticUrl() + ".html");
    41         }
    42 
    43         java.text.SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    44         // 封装模版所需参数
    45         Map<String, Object> params = new HashMap<String, Object>();
    46         params.put("looked", article.getLooks());
    47         params.put("articleId", article.getId());
    48         params.put("time", format.format(article.getCreateDate()));
    49         params.put("title", article.getTitle());
    50         params.put("content", article.getContent());
    51         params.put("typeString", "------------------------------------------------------");
    52         params.put("author", article.getAuthor());
    53         params.put("categoryName", getArticleCategoryDao().findById(article.getCategoryId()).getTitle());
    54         params.put("likes", article.getLikes());
    55         params.put("listCategoryArticle", contextPath + "/listArticle.action?categoryId=" + article.getCategoryId());
    56         params.put("lastArticlesList", lastArticles);
    57         params.put("categoryList", categories);
    58         params.put("likesURL", contextPath + "/likeAction.action?articleId=" + article.getId());
    59         params.put("nextArticle", next);
    60         params.put("lastArticle", last);
    61         params.put("staticURL", article.getStaticUrl());
    62 
    63         return params;
    64     }
  • 相关阅读:
    python调用c/c++库函数方法小结(c++和python的整合)
    一个机器学习的好网站
    Notepad++支持列选择模式
    awk的效率和python split 效率对比
    python 中的反射,装饰器,with语句
    hierarchy 在大数据上聚类的利弊
    shell 某个日期前的某一天(待补充)
    通过 cgi 运行 python 在lighttp上
    (译)Node.js的全局变量
    (译)Node.js的模块-exports和module.exports
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/7244426.html
Copyright © 2011-2022 走看看