Beetl
1, Introduction
Beetl is similar to JS syntax and can also support html tags. The engine performance is 5-6 times that of freemaker and 2 times that of JSP, which makes the development of static pages in CMS system cost-effective
2, Grammar
1. Delimiters and placeholders
Delimiter:<% %>: Write some for loop if Judge variable assignment and other operations Placeholder: ${ }: Placeholders are used to embed placeholders in static text for output
The following is a correct example
<% var a = 2; var b = 3; var result = a+b; %> hello 2+3=${result}
Note: never use placeholders in delimiters, because placeholders are only embedded in static text. The following example is an error example
<% var a = "hi"; var c = ${a}+"beetl"; //Should be var c = a+"beetl" %>
2. Notes
Single line notes adopt// Note Content Multi line fixation/*Note Content */
3. Temporary variable definition
The variables defined in the template become temporary variables, which is similar to the variables defined by var in js, as shown in the following example
<% 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. Global variable definition
The global variable is through template The variables passed in by binding can be accessed anywhere in the template, including sub templates
//Here is the java code. Assign a value to the template template.binding("list",service.getUserList()); //In the template <% for(user in list){ %> User name:,${user.name}; <% } %>
Because we use version 3.0, since version 2.8.0, a special variable has become the root variable. When the template cannot find the variable, it will look for the attribute of the root variable as the value of the variable. This root variable must be bound to "_root"
//Here is the java code. Assign a value to the template template.binding("_root",new User()); //In the template ${name} ${wife.name}
Here, both name and wife are attributes of the User object
5. Shared variable
Shared variables refer to variables that can be referenced in all templates, which can be accessed through GroupTemplate Setsharedvars (map < string, Object > sharedvars) passes in variables, which can be used anywhere in all templates
@Test void mapVariableFile() throws IOException, ParseException { //templates directory String root = "D:\\wyx\\beetl\\template"; //File template loader FileResourceLoader resourceLoader = new FileResourceLoader(root); Configuration cfg = Configuration.defaultConfiguration(); GroupTemplate gt = new GroupTemplate(resourceLoader, cfg); // Shared variable settings Map<String,Object> shared = new HashMap<String,Object>(); shared.put("share", "I am beetl Shared variable"); gt.setSharedVars(shared); Template t = gt.getTemplate("/shareOneTemplate.html"); t.binding("shareTitleOne","I am a shared variable template"); String str = t.render(); logger.info("Share one output:\n" + str); t = gt.getTemplate("/shareTwoTemplate.html"); t.binding("shareTitleTwo","I'm shared variable template 2"); str = t.render(); logger.info("Share two output results:\n" + str);
//t1.txt hi,${name} //t2.txt hello,${name}
6. Reference properties
① Beetl supports through "." Number to access the properties of the object, if it is the same as javascript. If the User object has a getName() method, it can be accessed through ${xxx.name} in the template
② If the template variable is an array or List class, this can be accessed through [], such as ${userList[0]}
③ If the template variable is a map class, this can be accessed through [], such as ${map ["name"]}. If the key value is a string type, you can also use ${map.name} However, this is not recommended because it will mislead template readers into thinking it is a Pojo object
④ Beetl also supports the generic get method, that is, if the object has a public Object get(String key) method, you can use "." For example, ${activityRecord.name} or ${activityRecord ["name"]} will call the get(String key) method of activityRecord. If the object has both specific attributes and generic get (this model design method is not encouraged), the specific attributes have higher priority
⑤ Beetl can also reference attributes through []. For example, ${user ["name"]} is equivalent to ${user.name} This is consistent with javascript. However, it is not recommended to do so, because it is easy for people reading the template to mistakenly think that this is a Map type
⑥ Beetl can also define additional object attributes without changing java objects. This is called virtual attributes. For example, for all sets and arrays, there is a common virtual attribute size The virtual attribute is ". ~" + virtual attribute name
template.binding("list",service.getUserList()); template.binding("pageMap",service.getPage()); //In the template in total ${list.~size} <% for(user in list){ %> hello,${user.name}; <% } %> Current page ${pageMap['page']},in total ${pageMap["total"]}
7. Arithmetic expression
Beetl supports javascript like arithmetic expressions and conditional expressions, such as + - * /% and (), as well as self increasing + +, self decreasing –
<% var a = 1; var b = "hi"; var c = a++; var d = a+100.232; var e = (d+12)*a; var f = 122228833330322.1112h //h indicates that this is a long precision BigDecimal %>
8. Logical expression
Beetl supports conditional expressions like JavaScript and Java, such as >, <, = =,! =, > =<= And!, There are also & & and 𞓜, and ternary expressions, as shown in the following examples
<% var a = 1; var b="good"; var c = null; <% var a = 1 ; %> ${a==1?"ok":''} ${a==1?"ok"} %>
9. Circular statement
Beetl supports rich loop modes, such as for in, for (Exp; exp; exp), while loop and loop control statement break;continue; In addition, if you do not enter the for loop body, you can also execute the statement specified by else for.
for-in
<% for(user in userList){ print(userLP.index);//userLP.index * current index, starting from 1 print(user.name); } %>
*userLP.index * current index, starting from 1
userLP.dataIndex index, starting from 0
*userLP.size * length of set
userLP. Is first the first
userLP. Is last the last one
userLP. Whether the even index is even
userLP. Is the odd index odd
for(exp;exp;exp)
For rendering logic, the classic for loop statement is more common, as shown in the following example
<% var a = [1,2,3]; for(var i=0;i<a.~size;i++){ print(a[i]); } %>
10. Conditional statement
if else
Like js, if else is supported, as shown in the following example
<% var a =true; var b = 1; if(a&&b==1){ }else if(a){ }else{ } %>
11,try-catch
Generally, try catch is rarely used in template rendering logic, but considering the complexity of rendering logic and uncontrollable places of template, try catch is provided to ensure normal output in case of rendering failure
<% try{ callOtherSystemView() }catch(error){ print("No data temporarily"); } %>
Error represents an exception. You can use error Message to get possible error messages
You can also omit the catch part, so that an exception occurs and no operation is done
<% var date = date(); var len = strutil.length("cbd"); println("len="+len); %>
12. Function call
Beetl has a few built-in practical functions, which can be called anywhere in Beetl. The following example is to call the date function and return the current date without passing parameters
Please refer to the appendix for Beetl built-in functions. The commonly used functions are listed below
① Date returns a java util. A variable of type date, for example, date() returns a current time (corresponding to java.util.Date of java)$ {date ("2011-1-1", "yyyy MM DD")} returns the specified date, date (MS), specifying a number of milliseconds. Equivalent to calling java util. date(ms)
② Print prints an object print(user.name);
③ Println prints an object and the carriage return line feed symbol. The carriage return symbol uses the template itself, not the local system If you only print a line break, you can call println() directly
④ nvl function nvl. If the object is null, it returns the second parameter. Otherwise, it returns its own nvl(user, "does not exist")
⑤ isEmpty determines whether the variable or expression is empty, the variable does not exist, the variable is null, the variable is an empty string, the variable is an empty collection, and the variable is an empty array. This function will return true
⑥ isNotEmpty is the same as above to judge whether the object is not empty
⑦ The has variable is named as a parameter to judge whether this "global variable" exists, such as has(userList), similar to 1 X version of exist("userList"), but there is no need to enter quotation marks Note that has and isEmpety judge the global variables passed from java to the template, not the temporary variables
⑧ hasAttrbiute tests whether the target object has this attribute. hasAttribute(user, "name")
⑨ assert throws an exception if the expression is false
Trim intercepts numbers or dates and returns characters. For example, trim(12.456,2) returns "12.45", and trim (date, 'yyyy') returns "2017"
⑩ trunc intercepts the number and retains the specified decimal places. For example, the output of trunc(12.456,2) is 12.45 It is not recommended because there is a problem with handling float, which is reserved for compatibility reasons
① ② decode is a simplified if else structure, such as decode(a,1, "a=1", 2, "a=2", "don't know"), if a is 1, decode outputs "a=1", if a is 2, it outputs "a==2", and if it is other values, it outputs "don't know"
① ③ debug output the object specified by debug and the number of lines in the template file and template on the console. For example, debug(1), output 1 [in line 3 @ / org/beetl/core/lab/hello.txt], or multiple, for example, debug("hi", a), output hi,a=123, [in line 3 @ / org/beetl/core/lab/hello.txt]
① ④ parseInt parses a number or character into an integer, such as parseInt("123");
① ⑤ parseLong parses numbers or characters into long shaping, parseInt(123.12);
① ⑥ parseDouble parses numbers or characters into floating-point types, such as ① ⑦ parseDouble("1.23")
① ⑧ range receives three parameters, the initial value, the end value, and the step-by-step increment (if it is unnecessary, the default is 1), and returns an Iterator, which is commonly used in the loop, such as for(var i in range(1,5)) {print(i)}, which will print 1234 in turn
① ⑨ flush forced io output.
② 0 JSON, convert the object into JSON string. For example, var data = json(userList) can be followed by a serialization rule. For example, var data = json(userList,"[*].id:i"), please refer to https://git.oschina.net/xiandafu/beetl-json
(1) pageCtx, only in web development, set up a variable, and then in the page rendering process, call this api to get, such as pageCtx("title", "user add page"), then anywhere, pageCtx("title") get the variable.
②②type.new creates an object instance, such as var user = type new(“com.xx.User”); If import is configured_ Package, you can omit the package name, type new(“User”)
②③type.name returns the name of an instance, VAR userclassname = type Name (User), return "User"
② ④ global returns a global variable value, and the parameter is a string, such as var user = global("user_"+ i);
② ⑤ cookie returns the specified cookie object, such as var usercookie = ② ⑥ cookie("user"), allCookies = cookie();
13. Safe output
Safe output is a problem that any template engine must pay attention to, otherwise, it will greatly perplex template developers. In Beetl, if the template variable to be output is null, Beetl will not output. This is different from JSP. JSP outputs null and Freemarker. If it is useless!, It will report an error
There are two other situations in the template that will lead to abnormal template output
Sometimes template variables do not exist (for example, in sub templates)
The template variable is null, but the output is a property of this variable, such as ${user. WiFi. Name}
For the first two cases, you can add after the variable reference! To remind beetl that this is a safe output variable.
Such as ${user. WiFi. Name!}, Even if user does not exist, or user is null, or user WiFi is null or user wife. If name is null, Beetl will not output
14. Format
<% var date = date(); %> Today is ${date,dateFormat="yyyy-MM-dd"}. Today is ${date,dateFormat} salary is ${salary,numberFormat="##.##"} //Abbreviation ${date,"yyyy-MM-dd"}
15. Label function
The so-called tag function allows you to process a piece of content in the template file. The function is the same as jsp tag. Such as Beetl's built-in layout label
index.html
<% //The variable title comes from the parameters of the layout label function layout("/inc/layout.html",{title:'theme'}){ %> Hello,this is main part <% } %>
layout.html
title is ${title} body content ${layoutContent} footer
3, Use
Integrate springboot
pom file
<dependency> <groupId>com.ibeetl</groupId> <artifactId>beetl-framework-starter</artifactId> <version>1.2.28.RELEASE</version> </dependency>
yml file
Change the btl suffix of Beetl to html suffix file
beetl: suffix: html
Template basic configuration
Start with GroupTemplate
The core of Beetl is GroupTemplate. Creating GroupTemplate requires two parameters: template resource loader and configuration class
① String template loader
//String template loader StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader(); //Template basic configuration Configuration cfg = Configuration.defaultConfiguration(); //The core of Beetl is GroupTemplate. Creating GroupTemplate requires two parameters: template resource loader and configuration class GroupTemplate gt = new GroupTemplate(resourceLoader, cfg); //Get template Template t = gt.getTemplate("hello,${name},${title}"); //Data rendering t.binding("name", "I'm the name"); t.binding("title", "I'm the title"); //Render results String str = t.render(); logger.info("Output result:\n" + str);
② File resource template loader (multivariable assignment)
//Template file directory String root = "D:\\wyx\\beetl\\template"; //File template loader FileResourceLoader resourceLoader = new FileResourceLoader(root); //Configuration class Configuration cfg = Configuration.defaultConfiguration(); GroupTemplate gt = new GroupTemplate(resourceLoader, cfg); //Get template Template t = gt.getTemplate("/muchVariableTemplate.html"); //Data rendering t.binding("title", "beetl Multivariable page"); t.binding("name", "beetl"); t.binding("age", 18); t.binding("time", new Date()); String str = t.render(); logger.info("Output result:\n" + str);
③ File resource template loader (map type variable assignment)
//Template file directory String root = "D:\\wyx\\beetl\\template"; //File template loader FileResourceLoader resourceLoader = new FileResourceLoader(root); //Configuration class Configuration cfg = Configuration.defaultConfiguration(); GroupTemplate gt = new GroupTemplate(resourceLoader, cfg); //Get template file Template t = gt.getTemplate("/muchVariableTemplate.html"); //Assembly template data Map<String, Object> map = new HashMap<>(); map.put("title", "beetl map Variable page"); map.put("name", "I am map"); t.binding("age", 20); t.binding("time", new SimpleDateFormat("yyyy-MM-dd").parse("2021-01-01")); //Template assignment t.binding(map); String str = t.render(); logger.info("Output result:\n" + str);
④ Share variables and generate html pages
//templates directory String root = "D:\\wyx\\beetl\\template"; //File template loader FileResourceLoader resourceLoader = new FileResourceLoader(root); Configuration cfg = Configuration.defaultConfiguration(); GroupTemplate gt = new GroupTemplate(resourceLoader, cfg); // Shared variable settings Map<String,Object> shared = new HashMap<String,Object>(); shared.put("share", "I am beetl Shared variable"); gt.setSharedVars(shared); //Get template 1 Template t = gt.getTemplate("/shareOneTemplate.html"); //Render template one's own data t.binding("shareTitleOne","I am a shared variable template"); //Create generated html page path File fileOne = new File("D:\\wyx\\beetl\\page\\shareOnePage.html"); if(!fileOne.exists()) { fileOne.createNewFile(); } Writer writer = new FileWriter(fileOne); //Write rendering results to html t.renderTo(writer); //Get template 2 t = gt.getTemplate("/shareTwoTemplate.html"); t.binding("shareTitleTwo","I'm shared variable template 2"); 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("Page generated successfully-----");
FTP file transfer
Function: send the generated html code to the server
pom file
<!-- ftp File upload--> <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 : File address */ public static void ftpUploadFile(String htmlUrl){ //Create client object FTPClient ftp = new FTPClient(); InputStream local=null; try { //Connect to ftp server ftp.connect("47.110.152.159", 21); //Sign in ftp.login("wyxftp", "wei123.."); //Set upload path String path="/home/wyxftp/a"; //Check whether the upload path exists. If it does not exist, return false boolean flag = ftp.changeWorkingDirectory(path); if(!flag){ //Create the upload path. This method can only create a primary directory. Here, if / home/ftpuser exists, you can create an image ftp.makeDirectory(path); } //Specify upload path ftp.changeWorkingDirectory(path); //Specifies the binary file type of the uploaded file ftp.setFileType(FTP.BINARY_FILE_TYPE); //Read local file File file = new File(htmlUrl); local = new FileInputStream(file); //The first parameter is the file name ftp.storeFile(file.getName(), local); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { //Close file stream local.close(); //sign out ftp.logout(); //Disconnect ftp.disconnect(); logger.info("Upload successful"); } catch (IOException e) { e.printStackTrace(); } } }
FastDFS file store
Function: store the file, return the address, and obtain the file according to the address
pom file dependency
<!-- fastdfs --> <dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>1.26.7</version> </dependency>
yml file
fdfs: so-timeout: 2500 # Read time connect-timeout: 600 # Connection timeout tracker-list: # tracker service configuration address list - 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); //Upload to FastDFS // 1. Get extension String extension = StringUtils.substringAfterLast(file.getName(), "."); // 2. Upload StorePath storePath = storageClient.uploadFile(inputStream, file.length(), extension, null); // Return path String fullPath = storePath.getFullPath(); logger.info("url:" + prop.getBaseUrl() + fullPath);