《FreeMarker教程-笔录》

今天我们学习一下FreeMarker模板引擎。它是基于模板文件生成其他文本的通用工具。本章我们主要讲使用FreeMarker模板引擎生成 .html 文件和生成 .java 类文件。

简介

FreeMarker是一款用java语言编写的模版引擎,它虽然不是web应用框架,但它很适合作为web应用框架的一个组件。
特点:

  • 轻量级模版引擎,不需要Servlet环境就可以很轻松的嵌入到应用程序中
  • 能生成各种文本,如html,xml,java,等
  • 入门简单,它是用java编写的,很多语法和java相似

环境配置

首先我们需要配置FreeMarker环境,两种方式任选其一(推荐maven):
1.下载它的依赖jar包
2.用maven配置。

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.20</version>
</dependency>

--------------好了,环境配好了我们开始搞点事情吧!

通过FreeMarker的模板文件生成java类文件

1.新建一个javaweb工程(eclipse/idea都可以)
2.在资源目录下新建一个templates目录(用来存放我们所有的FreeMarker模板文件xxx.ftl,模板文件的后缀名称为 ".ftl")
3.新建一个模板文件 hello.ftl (文件内容):

package ${classPath};//模板中变量引用(动态赋值)

public class ${className} {

    public static void main(String[] args) {
        System.out.println("${helloWorld}");
    }

}

4.在java类的src目录包下(包名随便【不过需要注意的是要和代码里生成的包位置一致】)新建FreemarkerTest.java (文件内容):

package com.yu.scloud.baseframe.frame.freemarker;

import com.yu.scloud.baseframe.frame.pojo.User;
import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.*;
import java.util.*;

public class FreemarkerTest {

    private static final String TEMPLATE_PATH = "src/main/resources/templates";//模板路径【指向你自己的模板文件存放路径】

    public static void main(String[] args) {

        autoGenJAVATest();//通过.ftl模板生成java类

    }
    //根据模板自动创建java类-示例
    private static void autoGenJAVATest()
    {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("classPath", "com.yu.scloud.baseframe.frame.freemarker");
        dataMap.put("className", "AutoGenHello");
        dataMap.put("helloWorld", "通过<代码自动生成程序> 演示 FreeMarker的HelloWorld!");

        String DEST_PATH = "src/main/java/com/yu/scloud/baseframe/frame/freemarker";//目标路径【指向你自己的类文件存放路径】
        genFileWithTemplate(TEMPLATE_PATH,DEST_PATH,"hello.ftl","AutoGenHello.java",dataMap);
    }

    //通过.flt模板生成file(封装了一下 方便统一调用)
    private static void genFileWithTemplate(String templateDir,String destDir,String templateFileName,String destFileName,Map<String,Object> dataMap)
    {
        //创建freeMarker配置实例
        Configuration configuration = new Configuration();
        Writer out = null;
        try {
            //设置模版路径
            configuration.setDirectoryForTemplateLoading(new File(templateDir));
            //加载模版文件
            Template template = configuration.getTemplate(templateFileName);
            //生成数据
            File docFile = new File(destDir + "\\" + destFileName);
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
            //输出文件
            template.process(dataMap, out);
            System.out.println(destFileName+" 模板文件创建成功 !");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != out) {
                    out.flush();
                    out.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
}

5.执行 FreemarkerTest.java的main方法,成功后会在上面代码中指定的DEST_PATH指向的目录下生成一个 AutoGenHello.java 文件,(文件内容):

package com.yu.scloud.baseframe.frame.freemarker;

public class AutoGenHello {

    public static void main(String[] args) {
        System.out.println("通过<代码自动生成程序> 演示 FreeMarker的HelloWorld!");
    }

}

以上就是使用FreeMarker模板引擎生成.java类文件的全部过程。我们可以对生成的文件简单分析一下:

  • hello.ftl模板文件中 package ${classPath}; 被替换成了
    package com.yu.scloud.baseframe.frame.freemarker;
  • public class ${className} { 被替换成了
    public class AutoGenHello {
    ......
我们通过模板可以生成多种多样更加复杂的类文件,对于我们日常开发很有帮助。比如Spring框架中的 Controller、Dao、Service以及ServiceImpl,这些类文件我们反复会去创建,并且好多文件格式、方法都是差不多的,这样我们就可以通过模板引擎去一键创建,方便的不要不要滴~~~

接下来我们将使用FreeMarker模板生成html文件

通过FreeMarker的模板文件生成Html文件

其实很简单

  • 新建 hello-html.ftl 文件(用来生成html的模板文件---示例代码中包含了FreeMarker基本的语法使用,东西相对比较多仔细阅读)
  • 我们对上面生成java的那个类改造一下:替换一下你生成html文件的路径以及生成的文件名称:

FreemarkerTest.java类(文件内容):

package com.yu.scloud.baseframe.frame.freemarker;

import com.yu.scloud.baseframe.frame.pojo.User;
import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.*;
import java.util.*;

public class FreemarkerTest {

    private static final String TEMPLATE_PATH = "src/main/resources/templates";//模板路径

    //通过.ftl模板生成java类
    public static void main(String[] args) {
        
        autoGenHTMLTest();
//        autoGenJAVATest();

    }
    //根据模板自动创建html-示例
    private static void autoGenHTMLTest()
    {
        //给模板文件组装数据
        Map<String, Object> dataMap = new HashMap<String, Object>();
        User user=new User();
        user.setName("Template-FreeMarker");
        user.setId("123456789");
        dataMap.put("user",user);
        dataMap.put("title","FreeMarker自动生成HTML");
        dataMap.put("datetime",new Date());
        //设置列表数据
        List<User> peoples=new ArrayList<>();
        for(int i=0;i<3;i++)
        {
            User user2=new User();
            user2.setName("A"+i);
            user2.setId("a"+i);
            peoples.add(user2);
        }
        dataMap.put("peoples",peoples);
        //设置map数据
        HashMap<String,User> employees=new HashMap<>();
        for(int m=0;m<6;m++)
        {
            User user3=new User();
            user3.setName("雇员"+m);
            user3.setId("emp"+m);
            employees.put(user3.getId(),user3);
        }
        dataMap.put("employees",employees);

        String DEST_PATH = "src/main/resources/static/demo";//目标路径
        genFileWithTemplate(TEMPLATE_PATH,DEST_PATH,"hello-html.ftl","hello.html",dataMap);
    }

    //通过.flt模板生成file
    private static void genFileWithTemplate(String templateDir,String destDir,String templateFileName,String destFileName,Map<String,Object> dataMap)
    {
        //创建freeMarker配置实例
        Configuration configuration = new Configuration();
        Writer out = null;
        try {
            //设置模版路径
            configuration.setDirectoryForTemplateLoading(new File(templateDir));
            //加载模版文件
            Template template = configuration.getTemplate(templateFileName);
            //生成数据
            File docFile = new File(destDir + "\\" + destFileName);
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
            //输出文件
            template.process(dataMap, out);
            System.out.println(destFileName+" 模板文件创建成功 !");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != out) {
                    out.flush();
                    out.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
}
hello-html.ftl 文件内容:
<html>
<head>
    <meta charset="UTF-8"/>
    <style>
        body{
            color: #666666;
        }
        .title{
            font-weight: bold;
            color:#000;
        }
    </style>

</head>
<bod>
    <div style="width: 50%;margin: auto;">
        <h3>${title}</h3>
        <p style="color:#ff0000;">名称:${user.name}</p>
        <div style="color:#ff0000;">年龄:${user.id}</div>
        <br/>
        <div>《FreeMarker语法汇总》</div>
        <!--FreeMarker语法汇总-->
        <!--声明变量cdate="自定义变量"-->
        <div class="title">声明变量cdate="自定义变量"</div>
    <#assign cdate="自定义变量"/>
        <!--条件判断-->
        <div class="title">条件判断</div>
    <#if cdate??>
        <div>${cdate}</div>
    <#else>
       <div>变量未声明</div>
    </#if>
        <!--字符串截取(原始字符串:"字符串截取Demo")-->
        <div class="title">字符串截取(原始字符串:"字符串截取Demo"</div>
    <#assign str="字符串截取Demo"/>
        <div>截取索引为2的字符:${str[2]}</div>
        <div>截取区间2-5字符串:${str[2..5]}</div>
        <br/>
        <!--算数运算(声明了两个变量a=5,b=8)-->
        <div class="title">算数运算(声明了两个变量a=5,b=8)</div>
    <#assign a=5/>
    <#assign b=8/>
        <div>"+":${a+b}</div>
        <div>"-":${a-b}</div>
        <div>"*":${a*b}</div>
        <div>"/":${a/b}</div>
        <div>"%":${a%b}</div>
        <br/>
        <!--比较运算符-->
        <div class="title">比较运算符</div>
        <!--gte大于等于-->
        <div><#if a gte b>a大于等于b</#if></div>
        <!--lt小于-->
        <div><#if a lt b>a小于b</#if></div>
        <br/>
        <!--内建函数-->
        <div class="title">内建函数</div>
    <#assign HELLO="helloMari"/>
        <div>第一个字母大写:${HELLO?cap_first}</div>
        <div>所有字母小写:${HELLO?lower_case}</div>
        <div>所有字母大写:${HELLO?upper_case}</div>
    <#assign fnum=3.1415926/>
        <div>数值取整(3.1415926):${fnum?int}</div>
        <div>日期格式化:${datetime?string("yyyy-MM-dd")}</div>
        <div>获取列表长度:${peoples?size}</div>
        <br/>
        <!--列表-->
        <div class="title">遍历列表项:</div>
        <ul>
        <#list peoples as people>
            <li>人:${people.name}</li>
        </#list>
        </ul>
        <!--map-->
        <div class="title">遍历Map项key:</div>
        <ul>
        <#list employees?keys as key>
            <li>键:${key}--值:${employees[key].name}</li>
        </#list>
        </ul>
        <div class="title">遍历Map项value:</div>
        <ul>
        <#list employees?values as value>
            <li>值:${value.name}</li>
        </#list>
        </ul>
        <!--声明list集合-->
        <#assign listData=["ITDragon", "blog", "is", "cool"]>

        <!--引入其它ftl模板文件-->
        <div class="title">引入其它ftl模板文件:</div>
        <#include "hello-other-html.ftl"/>

        <!--宏命令(自定义标签)-->
        <div class="title">宏命令(自定义不带参数的标签)</div>
        <#macro customtag>
            <div>不带参数宏:${title}</div>
        </#macro>
        <!--使用自定义不带参数的宏(标签)-->
        <@customtag/>
        <div class="title">宏命令(自定义带参数的标签)</div>
        <#macro customtagp p0 p1 p2>
            <div>带参数宏:${title}--${p0}--${p1}--${p2}</div>
        </#macro>
        <@customtagp p0="参数0" p1="参数1" p2="参数2"/>

        <!--命名空间-->
        <#import "hello-other-html.ftl" as other/>
        <div style="color: peru;">${other.otherftl}</div>
        
    </div>

</bod>
</html>
hello-other-html.ftl 文件内容:
<!--被引入的ftl-->
<div style="color: #00aa00;">我是被include的模板内容</div>
<#assign otherftl="另一个ftl文件定义的变量"/>
User.java类内容:
package com.yu.scloud.baseframe.frame.pojo;

import java.io.Serializable;

public class User implements Serializable{

    String id;
    String name;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
执行 FreemarkerTest.java中的main方法,会在目录下生成 hello.html 文件内容(对比一下模板文件):
<html>
<head>
    <meta charset="UTF-8"/>
    <style>
        body{
            color: #666666;
        }
        .title{
            font-weight: bold;
            color:#000;
        }
    </style>

</head>
<bod>
    <div style="width: 50%;margin: auto;">
        <h3>FreeMarker自动生成HTML</h3>
        <p style="color:#ff0000;">名称:Template-FreeMarker</p>
        <div style="color:#ff0000;">年龄:123456789</div>
        <br/>
        <div>《FreeMarker语法汇总》</div>
        <!--FreeMarker语法汇总-->
        <!--声明变量cdate="自定义变量"-->
        <div class="title">声明变量cdate="自定义变量"</div>
        <!--条件判断-->
        <div class="title">条件判断</div>
        <div>自定义变量</div>
        <!--字符串截取(原始字符串:"字符串截取Demo")-->
        <div class="title">字符串截取(原始字符串:"字符串截取Demo"</div>
        <div>截取索引为2的字符:串</div>
        <div>截取区间2-5字符串:串截取D</div>
        <br/>
        <!--算数运算(声明了两个变量a=5,b=8)-->
        <div class="title">算数运算(声明了两个变量a=5,b=8)</div>
        <div>"+":13</div>
        <div>"-":-3</div>
        <div>"*":40</div>
        <div>"/":0.625</div>
        <div>"%":5</div>
        <br/>
        <!--比较运算符-->
        <div class="title">比较运算符</div>
        <!--gte大于等于-->
        <div></div>
        <!--lt小于-->
        <div>a小于b</div>
        <br/>
        <!--内建函数-->
        <div class="title">内建函数</div>
        <div>第一个字母大写:HelloMari</div>
        <div>所有字母小写:hellomari</div>
        <div>所有字母大写:HELLOMARI</div>
        <div>数值取整(3.1415926):3</div>
        <div>日期格式化:2018-04-14</div>
        <div>获取列表长度:3</div>
        <br/>
        <!--列表-->
        <div class="title">遍历列表项:</div>
        <ul>
            <li>人:A0</li>
            <li>人:A1</li>
            <li>人:A2</li>
        </ul>
        <!--map-->
        <div class="title">遍历Map项key:</div>
        <ul>
            <li>键:emp5--值:雇员5</li>
            <li>键:emp4--值:雇员4</li>
            <li>键:emp3--值:雇员3</li>
            <li>键:emp2--值:雇员2</li>
            <li>键:emp1--值:雇员1</li>
            <li>键:emp0--值:雇员0</li>
        </ul>
        <div class="title">遍历Map项value:</div>
        <ul>
            <li>值:雇员5</li>
            <li>值:雇员4</li>
            <li>值:雇员3</li>
            <li>值:雇员2</li>
            <li>值:雇员1</li>
            <li>值:雇员0</li>
        </ul>
        <!--声明list集合-->

        <!--引入其它ftl模板文件-->
        <div class="title">引入其它ftl模板文件:</div>
<!--被引入的ftl-->
<div style="color: #00aa00;">我是被include的模板内容</div>

        <!--宏命令(自定义标签)-->
        <div class="title">宏命令(自定义不带参数的标签)</div>
        <!--使用自定义不带参数的宏(标签)-->
            <div>不带参数宏:FreeMarker自动生成HTML</div>
        <div class="title">宏命令(自定义带参数的标签)</div>
            <div>带参数宏:FreeMarker自动生成HTML--参数0--参数1--参数2</div>

        <!--命名空间-->
        <div style="color: peru;">另一个ftl文件定义的变量</div>

    </div>

</bod>
</html>

以上是使用FreeMarker模板引擎生成Html文件的全部过程。
下面列一下FreeMarker的基本语法(以下为转载勿喷):

数据类型
和java不同,FreeMarker不需要定义变量的类型,直接赋值即可。
字符串: value = "xxxx" 。如果有特殊字符 string = r"xxxx" 。单引号和双引号是一样的。
数值:value = 1.2。数值可以直接等于,但是不能用科学计数法。
布尔值:true or false。
List集合:list = [1,2,3] ; list=[1..100] 表示 1 到 100 的集合,反之亦然。
Map集合:map = {"key" : "value" , "key2" : "value2"},key 必须是字符串哦!
实体类:和EL表达式差不多,直接点出来。

字符串操作
字符串连接:可以直接嵌套${"hello , ${name}"} ; 也可以用加号${"hello , " + name}

字符串截取:string[index]。index 可以是一个值,也可以是形如 0..2 表示下标从0开始,到下标为2结束。一共是三个数。

比较运算符
== (等于),!= (不等于),gt(大于),gte(大于或者等于),lt(小于),lte(小于或者等于)。不建议用 >,< 可能会报错!
一般和 if 配合使用

内建函数
FreeMarker 提供了一些内建函数来转换输出,其结构:变量?内建函数,这样就可以通过内建函数来转换输出变量。
html: 对字符串进行HTML编码;
cap_first: 使字符串第一个字母大写;
lower_case: 将字符串转成小写;
upper_case: 将字符串转成大写;
size: 获得集合中元素的个数;
int: 取得数字的整数部分。

变量空判断
!   指定缺失变量的默认值;一般配置变量输出使用
??  判断变量是否存在。一般配合if使用 <#if value??></#if>

宏指令
可以理解为java的封装方法,供其他地方使用。宏指令也称为自定义指令,macro指令
语法很简单:<#macro val > 声明macro </#macro>; 使用macro <@val />

命名空间
可以理解为java的import语句,为避免变量重复。一个重要的规则就是:路径不应该包含大写字母,使用下划线_分隔词语,myName --> my_name
语法很简单:<#import "xxx.ftl" as val>

其他没有说明的语法是因为和java一样,没什么特别之处。所以没有列出来。

SpringMVC整合FreeMarker

  • 1.SpringMVC环境配置(这里就不展开了,不会的百度一下吧)
  • 2.Maven配置:
    <dependency>
         <groupId>org.freemarker</groupId>
         <artifactId>freemarker</artifactId>
         <version>2.3.20</version>
     </dependency>
     <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
          <version>4.1.4.RELEASE</version>
      </dependency>
  • 3.springmvc的配置文件:
    <!-- 整合Freemarker -->
    <!-- 放在InternalResourceViewResolver的前面,优先找freemarker -->  
    <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">  
        <property name="templateLoaderPath" value="/WEB-INF/views/templates"/>  
    </bean>  
    <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">  
        <property name="prefix" value=""/>  
        <property name="suffix" value=".ftl"/>  
        <property name="contentType" value="text/html; charset=UTF-8"/>
    </bean>
  • 4.Controller 层
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloFreeMarkerController {
    
    @RequestMapping("/helloFreeMarker")
    public String helloFreeMarker(Model model) {
        model.addAttribute("name","ITDragon博客");  
        return "helloFreeMarker";
    }

}
  • 5.最后是Freemarker文件
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<title>FreeMarker Web</title>  
</head>  
<body>  
    <h1>Hello ${name} !</h1>  
</body>  
</html>

小结

1 知道了FreeMarker是一块模版引擎,可以生产xml,html,java等文件

2 知道了FreeMarker文件提供占位符,java文件提供数据,通过FreeMarker模版引擎生产有数据的页面,文中是将数据放在Map中。web应用可以用setter/getter 方法

3 知道了FreeMarker语法中字符串的显示特殊字符,截取的操作。以及一些内置方法的使用

4 重点了解FreeMarker的空判断知识点。判断变量是否为空用 "??" ,如果变量为空设置默认值。如果不注意空问题,可能会出现黄色页面的提示哦!

5 FreeMarker的宏概念,命名空间,引入文件,给变量赋值,集合的遍历等。

6 Freemarker 整合SpringMVC。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容

  • FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: 1...
    年轻小伙程序员阅读 2,967评论 0 5
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,778评论 6 342
  • 近日,联合国世界旅游组织发布一则报告:中国游客成全球旅游业引擎,已承包全球出境消费逾两成。事实上,中国旅游...
    拾景旅行阅读 119评论 0 0
  • 文/赵浩 食不在多,好吃就行。厅不在大,干净则名。斯是饭堂,唯厨艺高。 饭菜扑鼻香,粥声入耳鸣。 吃喝有营养,点餐...
    稼轩李德智阅读 1,326评论 3 5
  • This method is of no value in debugging memory management...
    終于阅读 1,181评论 0 0