CMS-静态化技术

Beetl

一、简介

Beetl和JS语法很像,也能支持html 标签,引擎性能5-6倍与freemaker,2倍于JSP,使得开发CMS系统做静态化页面性价比高

二、语法

1、定界符与占位符号
	定界符:<%   %>: 写一些 for循环 if判断  变量赋值 等操作
	占位符:${ }:占位符用于静态文本里嵌入占位符用于输出

如下是正确例子

<%
var a = 2;
var b = 3;
var result = a+b;
%>
hello 2+3=${result}

注意点:千万不要在定界符里使用占位符号,因为占位符仅仅嵌在静态文本里,如下例子是错误例子

<%
var a = "hi";
var c = ${a}+"beetl"; //应该是var c = a+"beetl"
%>
2、注释
单行注释采用// 注释内容
多行注视采用/*注释内容*/
3、临时变量定义

在模板中定义的变量成为临时变量,这类似js中采用var 定义的变量,如下例子

<%
var a = 3;
var b = 3,c = "abc",d=true,e=null;
var f = [1,2,3];
var g = {key1:a,key2:c};
var i = a+b;
%>
4、全局变量定义

全局变量是通过template.binding传入的变量,这些变量能在模板的任何一个地方,包括子模板都能访问到

//此处是java代码,给模板赋值
template.binding("list",service.getUserList());

//在模板里
<%
for(user in list){
%>
用户名称:,${user.name};
<% } %>

因为我们使用的是3.0版本所以,自从2.8.0版本后,有一个特殊的变量成为root变量,当模板找不到变量的时候,会寻找root变量的属性来作为变量的值,这个root变量必须绑定为"_root"

//此处是java代码,给模板赋值
template.binding("_root",new User());

//在模板里
${name}
${wife.name}

这里name 和 wife都是User对象的属性

5、共享变量

共享变量指在所有模板中都可以引用的变量,可通过groupTemplate.setSharedVars(Map<String, Object> sharedVars)传入变量,这些变量能用在 所有模板 的任何一个地方

@Test
    void mapVariableFile() throws IOException, ParseException {
//模板目录
        String root = "D:\\wyx\\beetl\\template";
        //文件模板加载器
        FileResourceLoader resourceLoader = new FileResourceLoader(root);
        Configuration cfg = Configuration.defaultConfiguration();
        GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
        // 设置共享变量
        Map<String,Object> shared = new HashMap<String,Object>();
        shared.put("share", "我是beetl共享变量");
        gt.setSharedVars(shared);
        Template t = gt.getTemplate("/shareOneTemplate.html");
        t.binding("shareTitleOne","我是共享变量模板一");
        String str = t.render();
        logger.info("共享一输出结果:\n" + str);
        t = gt.getTemplate("/shareTwoTemplate.html");
        t.binding("shareTitleTwo","我是共享变量模板二");
        str = t.render();
        logger.info("共享二输出结果:\n" + str);
//t1.txt
hi,${name}
//t2.txt
hello,${name}
6、引用属性

①Beetl支持通过”.”号来访问对象的的属性,如果javascript一样。如果User对象有个getName()方法,那么在模板中,可以通过$ {xxx.name}来访问
②如果模板变量是数组或者List类,这可以通过[] 来访问,如$ {userList[0]}
③如果模板变量是Map类,这可以通过[]来访问,如$ {map[“name”]},如果key值是字符串类型,也可以使用$ {map.name}.但不建议这么使用,因为会让模板阅读者误以为是一个Pojo对象
④Beetl也支持Generic Get方式,即如果对象有一个public Object get(String key)方法,可以通过”.”号或者[]来访问,譬如 $ {activityRecord.name}或者$ {activityRecord[“name”] }都将调用activityRecord的 get(String key)方法。如果对象既有具体属性,又有Generic get(这种模型设计方式是不值得鼓励),则以具体属性优先级高.
⑤Beetl也可以通过[]来引用属性,如$ {user[“name”]} 相当于$ {user.name}.这跟javascript保持一致。但建议不这么做,因为容易让阅读模板的人误认为这是一个Map类型
⑥Beetl 还可以定义额外的对象属性,而无需更改java对象,这叫着虚拟属性,如,对于所有集合,数组,都有共同的虚拟属性size.虚拟属性是“.~”+虚拟属性名

template.binding("list",service.getUserList());
template.binding("pageMap",service.getPage());

//在模板里
总共 ${list.~size}
<%
for(user in list){
%>
hello,${user.name};
<% } %>

当前页${pageMap['page']},总共${pageMap["total"]}
7、算数表达式

Beetl支持类似javascript的算术表达式和条件表达式,如+ - * / % 以及(),以及自增++,自减–

<%
var a = 1;
var b = "hi";
var c = a++;
var d = a+100.232;
var e = (d+12)*a;
var f = 122228833330322.1112h //h以表示这是长精度BigDecimal
%>
8、逻辑表达式

Beetl支持类似Javascript,java的条件表达式 如>,<,==,!=,>= , <= 以及 !, 还有&&和 || ,还有三元表达式等,如下例子

<%
var a = 1;
var b="good";
var c = null;

<%
 var  a = 1 ;
%>
 ${a==1?"ok":''}
 ${a==1?"ok"}
%>
9、循环语句

Beetl支持丰富的循环方式,如for-in,for(exp;exp;exp),以及while循环,以及循环控制语句break;continue; 另外,如果没有进入for循环体,还可以执行elsefor指定的语句。

for-in

<%
for(user in userList){
        print(userLP.index);//userLP.index *当前的索引,从1开始
        print(user.name);
}
%>

*userLP.index *当前的索引,从1开始
userLP.dataIndex 索引,从0开始
*userLP.size *集合的长度
userLP.first 是否是第一个
userLP.last 是否是最后一个
userLP.even 索引是否是偶数
userLP.odd 索引是否是奇数

for(exp;exp;exp)
对于渲染逻辑更为常见的是经典的for循环语句,如下例子

<%
var a = [1,2,3];
for(var i=0;i<a.~size;i++){
        print(a[i]);
}
%>
10、条件语句

if else
同js一样,支持if else,如下例子

<%
var a =true;
var b = 1;
if(a&&b==1){

}else if(a){

}else{

}
%>
11、try-catch

通常模板渲染逻辑很少用到try-catch 但考虑到渲染逻辑复杂性,以及模板也有不可控的地方,所以提供try catch,在渲染失败的时候仍然能保证输出正常

<%
try{
        callOtherSystemView()
}catch(error){
        print("暂时无数据");
}
%>

error代表了一个异常,你可以通过error.message 来获取可能的错误信息

也可以省略catch部分,这样出现异常,不做任何操作

<%
var date = date();
var len = strutil.length("cbd");
println("len="+len);
%>
12、函数调用

Beetl内置了少量实用函数,可以在Beetl任何地方调用。如下例子是调用date 函数,不传参数情况下,返回当前日期
Beetl内置函数请参考附录,以下列出了常用的函数

①date 返回一个java.util.Date类型的变量,如 date() 返回一个当前时间(对应java的java.util.Date); ${date( “2011-1-1” , “yyyy-MM-dd” )} 返回指定日期,date(ms),指定一个毫秒数。相当于调用java.util.Date(ms)
②print 打印一个对象 print(user.name);
③println 打印一个对象以及回车换行符号,回车换号符号使用的是模板本身的,而不是本地系统的.如果仅仅打印一个换行符,则直接调用println() 即可
④nvl 函数nvl,如果对象为null,则返回第二个参数,否则,返回自己 nvl(user,“不存在”)
⑤isEmpty 判断变量或者表达式是否为空,变量不存在,变量为null,变量是空字符串,变量是空集合,变量是空数组,此函数都将返回true
⑥isNotEmpty 同上,判断对象是否不为空
⑦has 变量名为参数,判断是否存在此"全局变量",如 has(userList),类似于1.x版本的exist(“userList”),但不需要输入引号了.注意,has和isEmpety 判断的是从java传到模板的全局变量,而不是临时变量
⑧hasAttrbiute 测试目标对象是否有此属性,hasAttribute(user,“name”)
⑨assert 如果表达式为false,则抛出异常
trim 截取数字或者日期,返回字符,如trim(12.456,2)返回"12.45",trim(date,‘yyyy’)返回"2017"
⑩trunc 截取数字,保留指定的小数位,如trunc(12.456,2) 输出是12.45.不推荐使用,因为处理float有问题,兼容原因保留了
①②、decode 一个简化的if else 结构,如 decode(a,1,“a=1”,2,“a=2”,“不知道了”),如果a是1,这decode输出"a=1",如果a是2,则输出"a==2", 如果是其他值,则输出"不知道了"
①③debug 在控制台输出debug指定的对象以及所在模板文件以及模板中的行数,如debug(1),则输出1 [在3行@/org/beetl/core/lab/hello.txt],也可以输出多个,如debug(“hi”,a),则输出hi,a=123,[在3行@/org/beetl/core/lab/hello.txt]
①④parseInt 将数字或者字符解析为整形 如 parseInt(“123”);
①⑤parseLong 将数字或者字符解析为长整形,parseInt(123.12);
①⑥parseDouble 将数字或者字符解析为浮点类型 如①⑦parseDouble(“1.23”)
①⑧range 接收三个参数,初始值,结束值,还有步增(可以不需要,则默认为1),返回一个Iterator,常用于循环中,如for(var i in range(1,5)) {print(i)},将依次打印1234.
①⑨flush 强制io输出。
②〇json,将对象转成json字符串,如 var data = json(userList) 可以跟一个序列化规则 如,var data = json(userList,"[*].id:i"),具体参考 https://git.oschina.net/xiandafu/beetl-json
②①pageCtx ,仅仅在web开发中,设置一个变量,然后可以在页面渲染过程中,调用此api获取,如pageCtx(“title”,“用户添加页面”),在其后任何地方,可以pageCtx(“title”) 获取该变量
②②type.new 创建一个对象实例,如 var user = type.new(“com.xx.User”); 如果配置了IMPORT_PACKAGE,则可以省略包名,type.new(“User”)
②③type.name 返回一个实例的名字,var userClassName = type.name(user),返回"User"
②④global 返回一个全局变量值,参数是一个字符串,如 var user = global(“user_”+i);
②⑤cookie 返回指定的cookie对象 ,如var userCook = ②⑥cookie(“user”),allCookies = cookie();

13、安全输出

安全输出是任何一个模板引擎必须重视的问题,否则,将极大困扰模板开发者。Beetl中,如果要输出的模板变量为null,则beetl将不做输出,这点不同于JSP,JSP输出null,也不同于Freemarker,如果没有用!,它会报错.

模板中还有俩种情况会导致模板输出异常

有时候模板变量并不存在(譬如子模板里)
模板变量为null,但输出的是此变量的一个属性,如${user.wife.name}
针对前俩种情况,可以在变量引用后加上!以提醒beetl这是一个安全输出的变量。

如${user.wife.name! },即使user不存在,或者user为null,或者user.wife为null,或者user.wife.name为null beetl都不将输出

14、格式化
<% var date = date(); %>
Today is ${date,dateFormat="yyyy-MM-dd"}.
Today is ${date,dateFormat}
salary is ${salary,numberFormat="##.##"}

//简写
${date,“yyyy-MM-dd”}
15、标签函数

所谓标签函数,即允许处理模板文件里的一块内容,功能等于同jsp tag。如Beetl内置的layout标签

index.html

<%
//变量title来自于layout标签函数的参数
layout("/inc/layout.html",{title:'主题'}){
%>
Hello,this is main part
<% } %>

layout.html

title is ${title}
body content ${layoutContent}
footer

三、使用

整合springboot

pom文件

<dependency>
    <groupId>com.ibeetl</groupId>
    <artifactId>beetl-framework-starter</artifactId>
    <version>1.2.28.RELEASE</version>
</dependency>

yml文件
把Beetl的btl后缀改为html后缀文件

beetl:
  suffix: html
模板基础配置
从GroupTemplate开始

Beetl的核心是GroupTemplate,创建GroupTemplate需要俩个参数,一个是模板资源加载器,一个是配置类

①、字符串模板加载器

//字符串模板加载器
        StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader();
        //模板基础配置
        Configuration cfg = Configuration.defaultConfiguration();
        //Beetl的核心是GroupTemplate,创建GroupTemplate需要俩个参数,一个是模板资源加载器,一个是配置类
        GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
        //获取模板
        Template t = gt.getTemplate("hello,${name},${title}");
        //渲染数据
        t.binding("name", "我是名称");
        t.binding("title", "我是标题");
        //渲染结果
        String str = t.render();
        logger.info("输出结果:\n" + str);

②文件资源模板加载器(多变量赋值)

//模板文件目录
        String root = "D:\\wyx\\beetl\\template";
        //文件模板加载器
        FileResourceLoader resourceLoader = new FileResourceLoader(root);
        //配置类
        Configuration cfg = Configuration.defaultConfiguration();
        GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
        //获取模板
        Template t = gt.getTemplate("/muchVariableTemplate.html");
        //渲染数据
        t.binding("title", "beetl多变量变量页面");
        t.binding("name", "beetl");
        t.binding("age", 18);
        t.binding("time", new Date());
        String str = t.render();
        logger.info("输出结果:\n" + str);

③文件资源模板加载器(map类型变量赋值)

 //模板文件目录
        String root = "D:\\wyx\\beetl\\template";
        //文件模板加载器
        FileResourceLoader resourceLoader = new FileResourceLoader(root);
        //配置类
        Configuration cfg = Configuration.defaultConfiguration();
        GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
        //获取模板文件
        Template t = gt.getTemplate("/muchVariableTemplate.html");
        //组装模板数据
        Map<String, Object> map = new HashMap<>();
        map.put("title", "beetl map变量页面");
        map.put("name", "我是map");
        t.binding("age", 20);
        t.binding("time", new SimpleDateFormat("yyyy-MM-dd").parse("2021-01-01"));
        //模板赋值
        t.binding(map);
        String str = t.render();
        logger.info("输出结果:\n" + str);

④共享变量 并生成html页面

 //模板目录
        String root = "D:\\wyx\\beetl\\template";
        //文件模板加载器
        FileResourceLoader resourceLoader = new FileResourceLoader(root);
        Configuration cfg = Configuration.defaultConfiguration();
        GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
        // 设置共享变量
        Map<String,Object> shared = new HashMap<String,Object>();
        shared.put("share", "我是beetl共享变量");
        gt.setSharedVars(shared);
        //获取模板一
        Template t = gt.getTemplate("/shareOneTemplate.html");
        //渲染模板一自己的数据
        t.binding("shareTitleOne","我是共享变量模板一");
        //创建生成的html页面路径
        File fileOne = new File("D:\\wyx\\beetl\\page\\shareOnePage.html");
        if(!fileOne.exists()) {
            fileOne.createNewFile();
        }
        Writer writer = new FileWriter(fileOne);
        //将渲染结果写入html中
        t.renderTo(writer);

        //获取模板二
        t = gt.getTemplate("/shareTwoTemplate.html");
        t.binding("shareTitleTwo","我是共享变量模板二");
        File fileTwo = new File("D:\\wyx\\beetl\\page\\shareTwoPage.html");
        if(!fileTwo.exists()) {
            fileTwo.createNewFile();
        }
        Writer writerTwo = new FileWriter(fileTwo);
        t.renderTo(writerTwo);
        logger.info("生成页面成功-----");

FTP 文件传输

作用:将生成的html代码传到服务器上
pom文件

<!-- ftp文件上传-->
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.3</version>
        </dependency>
public static void main(String[] args) {
        String htmlUrl = "D:\\wyx\\beetl\\page\\a.html";
        ftpUploadFile(htmlUrl);
    }

    /**
     *
     * @param htmlUrl : 文件地址
     */
    public static void ftpUploadFile(String htmlUrl){
        //创建客户端对象
        FTPClient ftp = new FTPClient();
        InputStream local=null;
        try {
            //连接ftp服务器
            ftp.connect("47.110.152.159", 21);
            //登录
            ftp.login("wyxftp", "wei123..");
            //设置上传路径
            String path="/home/wyxftp/a";
            //检查上传路径是否存在 如果不存在返回false
            boolean flag = ftp.changeWorkingDirectory(path);
            if(!flag){
                //创建上传的路径  该方法只能创建一级目录,在这里如果/home/ftpuser存在则可创建image
                ftp.makeDirectory(path);
            }
            //指定上传路径
            ftp.changeWorkingDirectory(path);
            //指定上传文件的类型  二进制文件
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            //读取本地文件
            File file = new File(htmlUrl);
            local = new FileInputStream(file);
            //第一个参数是文件名
            ftp.storeFile(file.getName(), local);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                //关闭文件流
                local.close();
                //退出
                ftp.logout();
                //断开连接
                ftp.disconnect();
                logger.info("上传成功");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

FastDFS 文件存储

作用:存储文件,返回地址,根据地址获取文件

pom文件依赖

<!-- fastdfs -->
        <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
            <version>1.26.7</version>
        </dependency>

yml文件

fdfs:
  so-timeout: 2500       # 读取时间
  connect-timeout: 600   # 连接超时时间
  tracker-list:          # tracker服务配置地址列表
    - 47.110.152.159:22122
upload:
  base-url: http://47.110.152.159:84/
String path = "D:\\wyx\\beetl\\page\\b.html";
        File file = new File(path);

        InputStream inputStream = new FileInputStream(file);
        //上传到FastDFS
        // 1、获取扩展名
        String extension = StringUtils.substringAfterLast(file.getName(), ".");
        // 2、上传
        StorePath storePath = storageClient.uploadFile(inputStream, file.length(), extension, null);
        // 返回路径
        String fullPath = storePath.getFullPath();
        logger.info("url:" + prop.getBaseUrl() + fullPath);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值