Spring Boot 2.0 读书笔记_05:Beetl

版权声明:未经博主本人同意,请勿私自转发分享。 https://blog.csdn.net/Nerver_77/article/details/84823657

3. Beetl

写在开头,Beetl是由《Spring Boot 2精髓》作者所开发并维护的后端模板引擎,主要用于渲染视图模板。

关于模板引擎,博主了解过的主要是JSP 和 FreeMarker,视图渲染技术的了解并不多。

这里谈一下自己对于Web开发的理解:基于现在的Web开发环境,前后端分离开发的思想,相对后端来讲,很多时候是面向接口编程,拿当下火热的前端渐进式组件框架Vue来讲,于后端的交互无异于请求数据并返回,前端框架进行数据解析和视图渲染,后端进行接口数据的获取以及返回。

借此阅读技术书籍以及结合案例Demo的机会,来比较系统的了解一下这个后端模板引擎:Beetl

关于模板介绍,可以移步:http://ibeetl.com/ ,这里就不赘述了,直接上手实操。

  • 依赖引入
    在Spring Boot中,beetl-framework-starter 将自动配置以 btl 结尾的所有视图,将自动使用 Beetl 渲染响应的 resources/templates 目录下的视图文件

      <dependency>
      	<groupId>com.ibeetl</groupId>
      	<artifactId>beetl-framework-starter</artifactId>
      	<version>1.1.57.RELEASE</version>
      </dependency>
    
  • 设置定界符和占位符
    记得当初使用JSP、ftl在页面上写脚本的时候,定界符和占位符的概念就了解过了。
    有图有真相:

    JavaWeb时期用过的JSP
    在这里插入图片描述

    SSM时期用过的FreeMarker
    在这里插入图片描述

    默认配置:
    <% %> 作为定界符,${ }作为占位符

    可以通过配置文件来设置定界符和占位符,需要在 resources 目录下创建 beetl.properties 文件
    案例中给出了一种配置方式:占位符使用:’${’ 和 ‘}’,定界符使用:’@’ 和 ‘回车换行’。

      DELIMITER_PLACEHOLDER_START=${
      DELIMITER_PLACEHOLDER_END=}
      DELIMITER_STATEMENT_START=@
      DELIMITER_STATEMENT_END=
    
  • 配置Beetl
    Beetl为了提高渲染性能,会在模板渲染之后对语法解析结果进行缓存,每次渲染前都会对模板文件进行更新监测,因此这个地方会存在一次I/O操作,线上系统可以取消这个更新监测。application.properties文件中添加:

      beetl-beetlsql.dev = false 
    

    关于Web项目中 target目录 没有同步更新最新目录文件以及资源的问题:IDEA不像Eclipse会自动将新保存的文件或目录及其他资源更新到target目录中,必须在pom.xml中设置

      <build>    
      <resources>
          <resource>
              <directory>src/main/java</directory>
              <includes>
                  <include>**/*.*</include>
              </includes>
          </resource>
          <resource>
              <directory>src/main/resources</directory>
              <includes>
                  <include>**/*.*</include>
              </includes>
          </resource>
      </resources>
      </build>
    

    接下来,maven clean、build就可以了,这个问题和mapper.xml文件无法加载的问题一致,原因都是在resource文件夹不被加入build行列。

  • GroupTemplate
    Beetl的核心是GroupTemplate,是一个重量级对象,实际使用的时候建议使用单例模式创建,创建GroupTemplate需要两个参数,一个是模板资源加载器,一个是配置类。

    模板资源加载器Beetl内置了6种,分别是:

    模板资源加载器 说明
    StringTemplateResourceLoader 字符串模板加载器,用于加载字符串模板,如本例所示
    FileResourceLoader 文件模板加载器,需要一个根目录作为参数构造,传入getTemplate方法的String是模板文件相对于Root目录的相对路径
    ClasspathResourceLoader 文件模板加载器,模板文件位于Classpath里
    WebAppResourceLoader 用于webapp集成,假定模板根目录就是WebRoot目录,参考web集成章
    MapResourceLoader 可以动态存入模板
    CompositeResourceLoader 混合使用多种加载方式

    GroupTemplate创建过程:

      // 模板资源加载器
      StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader();
      // 配置类
      Configuration cfg = Configuration.defaultConfiguration();
      // 单例模式创建
      GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
    

    配置类:通过自动注入的方式注入GroupTemplate,@PostConstruct作用于Config方法上,会在Spring启动阶段调用此方法,完成对GroupTemplate的拓展。

      @Configuration
      public class BeetlExtConfig {
      	@Autowired
      	GroupTemplate groupTemplate;
    
      	@Autowired
      	ApplicationContext applicationContext;
    
      	@PostConstruct
      	public void config() {
      			
      	}
      }
    

以下内容为Beetl的基础语法相关内容,该部分内容会进行提纲式的笔记整理,不会详细讲述语法相关内容。

  • 变量

    • 全局变量:在模板或者子模板中使用
      • request内置对象通过attribute在模板中均可直接通过name来引用。
      • Session提供了Session会话,这里指的是HTTPSession。
      • parameter,读取用户提交参数。
      • ctxPath,Web应用中的ContextPath。在Spring Boot中,应用默认是 “/”。
      • servlet,WebVariable的实例,包含 HTTPSession、HTTPServletRequest、HTTPServletResponse三个属性。模板中可以通过 request、response、session 来引用。
      • 所有groupTemplate的共享变量
    • 局部变量:只能在当前模板中使用
      • 变量类型同JavaScript类型一致,在Beetl中,任何与高精度数据进行算数运算后的结果会转换为BIgDecimal类型,对应Java中的BigDecimal类型。
    • 共享变量
      • 类似全局变量,可以在任何模板中使用,需要通过groupTemplate的API进行添加。

          定义:在注入GroupTemplate对象的配置类中,config方法中进行设置:
          groupTemplate.getSharedVars().put("key", value);
          使用:在任意末班中,通过占位符进行使用:
          ${key}
        
    • 模板变量
      • 定义:变量的内容是模板对应的输出

          @var a = 1 ; 
          @var template = { 
          <span>${a}</span〉
          @}
          输出:${template}
        

        template是个变量,内容位于${ }中,内容是1。
        模板变量可以用在后面的任何地方,Beetl使用模板变量来完成继承布局方式。

  • 表达式

    • 算数表达式
      • 支持 +、-、*、/、% 等表达式,变量类型与相应的Java类型一致。

      • 需要用到高精度数代替Double时,需要在数字后面添加 “h”,对应Java中BigDecimal类型。

          例如:@var a = 123.25785236h;
        
      • 为保证浮点计算准确,含有高精度数表达式的计算过程全部按照高精度进行计算

    • 逻辑表达式
      • 支持 >、<、==、!=、>=、<=、!、&&、||、?等条件表达式

      • 三元表达式只考虑true情况时,可以进行简化

          例如:
          $var a = 1;
          ${a == 1? "bingo" : ""}
          ${a == 1? "bingo"}
          上述两行代码效果一致,在简化的三元表达式中,false情况时,自动赋值为null。
          Beetl占位符对null值不做输出。
        
  • 控制语句

    • 循环语句
      • for…in [elsefor]、for(exp; exp; exp)、while(exp)
        • for…in 循环中可以得到循环的上下文信息,会自动创建一个变量名+LP后缀的变量,提供循环的上下文信息

            例如:
            @for(user in userList!){
              <span>${userLP.index}</span>
            @}
          

          上面的例子中在表达式:user in userList 后添加了 “!”,来进行安全输出。即若user不存在,或者为空,不要报错,不进入循环体。此外上下文对象userLP还有其他相关信息:

    属性/方法 说明
    userLP.index 当前索引值,从1开始
    userLP.size 集合长度
    userLP.first 是否是第一个
    userLP.last 是否是最后一个
    userLP.even 索引是否是偶数
    userLP.odd 索引是奇数
    • 条件语句
      • if…else [else if]
      • 加强版switch case:select-case
        • 允许case中使用逻辑表达式

        • 不需要每个case都break,默认遇到符合条件的case执行后退出

          <%
            var b = 1;
            select {
             case b < 1, b > 10:
               print("out of range");
             default:
               print("error") 
            }
          %>
          
    • try…catch
      • 捕获模板异常

          <%
          try{
            callOtherSystemView();
          } catch (error) {
            print(err.message);
          }
          %>
        
  • 函数调用

    常用函数 说明 举例
    print/pringln 输出对象,若对象为空,则不输出
    has 判断是否具有这个全局变量 if(has(userList)){…}
    isEmpty 判断变量或者表达式是否为空
    debug 在控制台打印变量或者表达式,附带所在文件模板路径信息
    date 日期函数,获得当前日期
    trim 截取一个日期或者数字类型并返回字符串 trim(126.18, 1) -> 126.18
    trim(date(),‘yyyy’) -> 2018
    parseInt 将字符串或者number转换为对应类型 parseLong、parseDouble
    global 返回全局变量值,参数是字符串 var user = global(“user_” + i)
    cookie 返回指定的cookie对象 var userCookie = cookie(“user”)
    strutil.* 字符串系列函数 详情参考Beetl使用手册
    array.* 集合相关函数
    shiro.* 安全框架shiro的相关方法封装 shiroExt类中有说明,并非内置函数
    spring.* Spring框架中可以使用的函数 spel表达式
    reg.* 正则表达式相关函数

    这里说一下用到过的Shiro.hasPermission()方法吧,首先Shiro安全框架是集成进项目中来的,并配置了ShiroConfig配置类。权限控制的方式上采用基于URL的形式进行控制,在视图层,使用Beetl提供的ShiroExt中的hasPermission方法,对模板中的URL字符串进行权限认证,ShiroExt在这一过程中只是做了封装操作,获取到权限URL参数、和当前Subject,并将参数交给Shiro框架进行处理。

      /**
      * 验证当前用户是否拥有指定权限,使用时与lacksPermission 搭配使用
      *
      * @param permission 权限名
      * @return 拥有权限:true,否则false
      */
      public boolean hasPermission(String permission) {
      	return getSubject() != null && permission != null
      	&& permission.length() > 0
      	&& getSubject().isPermitted(permission);
      }
    
      /**
      * 获取当前 Subject
      *
      * @return Subject
      */
      protected static Subject getSubject() {
      	return SecurityUtils.getSubject();
      }
    
      // isPermitted是接口Subject下的一个实现方法
      boolean isPermitted(String permission);
    
      // 视图层使用
      @if(shiro.hasPermission("/cta/add")){
      	<#button name="添加" icon="fa-plus" clickFun="Cta.openAddCta()"/>
      @}
    
  • 格式化函数
    允许在占位符输出的时候指定格式化函数来格式化输出
    格式化格式:${exp, formatName=“可选参数”}

  • 以Java方式进行调用
    可以在模板中以Java方式调用表达式,使用时必须在表达式前用"@"符号标识

    • 定界符中使用

      <%
      	var size = @a.size();
      %>
      
    • 占位符中使用

      ${ @user.getUserName() }
      
    • 需要注意的是:

      • 对于直接Java调用,GroupTemplate是可以配置进制此功能的。

      • 可以通过安全管理器配置Beetl不允许调用那些类。默认java.lang.Runtime 和 java.lang.Process不允许被调用。

      • 按照Java规范书写类名、方法名以及属性名

      • 内部类访问机制:outerClass$innerClass

      • 表达式是Java风格,参数依然是Beetl表达式。

          ${@user.sayHello(user.name)}
          user.sayHello 是Java调用
          user.name 依然是Beetl表达式
        
  • 标签函数

    • 功能等同于 jsp tag

    • layout:布局标签函数

        @layout("/inc/layout.html", {title:'主题'}){
          <p>Hello Beetl</p>
        @}
      

      layout标签会把标签体{ }部分内容渲染出来之后,传给layout指定的模板页面,默认接收变量名为layoutContent,同时携带title变量进行传递。

        layout.html
        <title>${title}</title>
        <div>
          ${layoutContent}
        </div>
      
    • include:包含标签函数

      @include("/inc/header.html", {title:"page header"}){...}
      <div>
      // main content
      </div>
      @include("/inc/footer.html"){}
      

      include标签第一个参数是公共模板的路径,其后可以接受一个map参数,map中的,每一项值都会传递给子模板作为子模板的全局变量。

  • 安全输出
    Beetl在变量表达式后面使用符号 “!” 来提醒Beetl此变量可能不存在,表达式将返回 “!” 后的表达式值,若没有表达式,则返回null。

      @ var user = null;
      ${user.name!"无此人姓名信息"}
    

    当user为null时,或者user.name为null时,返回 “无此人姓名信息”

猜你喜欢

转载自blog.csdn.net/Nerver_77/article/details/84823657