013_序列内建函数

本文详细介绍了FreeMarker中用于序列操作的内置函数,如chunk用于分隔、first和last获取首尾元素、join连接字符串、sort排序等,通过实例展示了如何在实际开发中使用这些函数处理序列数据。
摘要由CSDN通过智能技术生成

1. chunk

1.1. 该内建函数将序列分隔为多个序列, 长度为第一个参数给定的值(比如: mySeq?chunk(3))。结果是包含这些序列的一个序列。最后一个序列可能比给定的长度要小, 除非第二个参数也给定了(比如: mySeq?chunk(3, '-')), 这就是用来填充最后一个序列, 以达到给定的长度。

1.2. 该内建函数通常在输出的序列中使用表格/柱状的格式。当被用于html表格时, 第二个参数通常是"\xA0"(也就是不换行的空格代码, 也就是我们所知的"nbsp"),  所以空td的边界就不会不丢失。

1.3. 第一个参数必须是一个数字, 而且至少是1。如果这个数字不是整数, 那么它会被静默地去掉小数部分(也就是说3.1和3.9都会被规整为3)。第二个参数可以是任意类型的值。

2. first

2.1. 序列的第一个子变量。如果序列为空, 那么模板处理将会中止。

3. join

3.1. 使用给定的分隔符来连接序列中的项为一个独立的字符串。

3.2. 序列中不是字符串的项会被转换为字符串, 使用${...}相同的转换规则(当然这里不会应用自动转义)。

3.3. join(...)最多可以有3个参数

3.3.1. 分隔符, 是必须的, 插入到每一项中间的字符串。

3.3.2. 空值, 默认是""(空字符串), 如果序列为空, 使用该值。

3.3.3. 列表结尾, 默认是"" (空字符串), 如果列表序列不为空, 该值在最后一个值后面输出。

4. last

4.1. 序列的最后一个子变量。如果序列为空,那么模板处理将会中止。

5. reverse

5.1. 序列的反序形式。

6. seq_contains

6.1. 辨别序列中是否包含指定值。它包含一个参数, 就是来查找的值。

6.2. 为了查找值, 该内建函数使用了FreeMarker的比较规则(就像使用==操作符)。你可以使用它来查找标量值(也就是字符串, 数字, 布尔值, 或日期/时间类型)。对于其他类型结果通常都是 false。

6.3. seq_前缀在该内建函数名字中是需要的, 用来和contains内建函数区分开。contains用来在字符串中查找子串(因为变量可以同时当作字符串和序列)。

7. seq_index_of

7.1. 返回序列中第一次出现该值时的索引位置, 如果序列不包含指定的值时返回-1。要查找的值作为第一个参数。

7.2. 为了查找值, 该内建函数使用了FreeMarker的比较规则(就像使用了==操作符)。你可以使用它来查找标量值(也就是字符串, 数字, 布尔值, 或日期/时间类型)。对于其他类型结果通常是-1。

7.3. 搜索开始的索引值可以由第二个可选参数来确定。如果在同一个序列中相同的项可以多次出现时, 这是很有用的。第二个参数的数值没有什么限制: 如果它是负数, 那么就和它是零的效果一样, 而如果它是比序列长度还大的数, 那么就和它是序列长度值的效果一样。小数值会被切成整数。

7.4. seq_前缀在该内建函数名字中是需要的, 用来和index_of内建函数区分开。index_of用来在字符串中查找子串(因为变量可以同时当作字符串和序列)。

8. seq_last_index_of

8.1. 返回序列中最后一次出现值的索引位置, 如果序列不包含指定的值时返回-1。也就是说, 和seq_index_of相同, 只是在序列中从最后一项开始向前搜索。

8.2. 它也支持可选的第二个参数来确定从哪里开始搜索的索引位置。

8.3. seq_前缀在该内建函数名字中是需要的, 用来和last_index_of内建函数区分开。last_index_of用来在字符串中查找子串(因为变量可以同时当作字符串和序列)。

9. size

9.1. 序列中子变量的数量(作为数字值)。假设序列中至少有一个子变量, 那么序列s中最大的索引是s?size - 1(因为第一个子变量的序列是0)。

10. sort

10.1. 以升序方式返回序列。(要使用降序排列时, 使用它之后使用reverse内建函数。)这仅在子变量都是字符串时有效, 或者子变量都是数字, 或者子变量都是日期值(日期, 时间, 或日期+时间)。如果子变量是字符串, 它使用本地化(语言)的具体单词排序(通常是大小写不敏感的)。

11. 例子

11.1. 新建一个名为FMBuiltInsForSequences的动态Web工程, 同时添加相关jar包。

11.2. 编写FMFactory.java

package com.fm.util;

import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import freemarker.template.Configuration;
import freemarker.template.TemplateExceptionHandler;

public class FMFactory {
	private final static FMFactory instance = new FMFactory();
	private FMFactory() {}
	public static FMFactory getInstance() {
		return instance;
	}
	
	private Map<String, Configuration> map = new ConcurrentHashMap<String, Configuration>();
	
	// 创建单个Configuration实例
	public synchronized Configuration getCfg(Object servletContext, String path) {
		if(null != map.get(path)) {
			return map.get(path);
		}
		Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
		cfg.setServletContextForTemplateLoading(servletContext, path);
		cfg.setDefaultEncoding("utf-8");
		// 本地化设置
		cfg.setLocale(Locale.CHINA);
		cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
		map.put(path, cfg);
		
		return cfg;
	}
	
}

11.3. 编写BuiltInsForSequences.java

package com.fm.action;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fm.util.FMFactory;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class BuiltInsForSequences extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Configuration cfg = FMFactory.getInstance().getCfg(req.getServletContext(), "/WEB-INF/templates");
		Template template = cfg.getTemplate("builtinsforsequences.html");
		
		Map<String, Object> root = new HashMap<String, Object>();
		Writer out = new OutputStreamWriter(resp.getOutputStream());
		try {
			template.process(root, out);
		} catch (TemplateException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}

11.4. 修改web.xml

11.5. 在/WEB-INF/templates下编写builtinsforsequences.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>序列内建函数</title>
	</head>
	<body>
		<h2>分隔序列为多个序列</h2>
		<#assign seq = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']>
		<#list seq?chunk(4) as row>
			<#list row as cell>${cell} </#list><br />
		</#list><br />
		<#list seq?chunk(4, '-') as row>
			<#list row as cell>${cell} </#list><br />
		</#list>
		<h2>序列的第一个子变量</h2>
		${['你好', '我好', '他也好']?first}
		<h2>使用给定的分隔符来连接序列中的项为一个独立的字符串</h2>
		[${["red", "green", "blue"]?join(", ")}]<br />
		[${["red", "green", "blue"]?join(", ", "-")}]<br />
		[${[]?join(", ", "-")}]<br />
		[${["red", "green", "blue"]?join(", ", "-", ".")}]<br />
		[${[]?join(", ", "-", ".")}]
		<h2>序列的最后一个子变量</h2>
		${['你好', '我好', '他也好']?last}
		<h2>序列的反序形式</h2>
		${['你好', '我好', '他也好']?reverse?join(", ")}
		<h2>辨别序列中是否包含指定值</h2>
		"blue": ${["red", 16, "blue", "cyan"]?seq_contains("blue")?string("yes", "no")}<br />
		"yellow": ${["red", 16, "blue", "cyan"]?seq_contains("yellow")?string("yes", "no")}
		<h2>返回序列中第一次出现该值时的索引位置</h2>
		"Joe"在["Joe", "Fred", "Joe", "Susan"]中第一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_index_of("Joe")}<br />
		"lili"在["Joe", "Fred", "Joe", "Susan"]中第一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_index_of("lili")}<br />
		从-2的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中第一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_index_of("Joe", -2)}<br />
		从-1的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中第一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_index_of("Joe", -1)}<br />
 		从0的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中第一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_index_of("Joe", 0)}<br />
 		从1的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中第一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_index_of("Joe", 1)}<br />
 		从2的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中第一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_index_of("Joe", 2)}<br />
 		从3的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中第一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_index_of("Joe", 3)}<br />
 		从4的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中第一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_index_of("Joe", 4)}
		<h2>返回序列中最后一次出现值的索引位置</h2>
		"Joe"在["Joe", "Fred", "Joe", "Susan"]中最后一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_last_index_of("Joe")}<br />
		"lili"在["Joe", "Fred", "Joe", "Susan"]中最后一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_last_index_of("lili")}<br />
		从-2的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中最后一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_last_index_of("Joe", -2)}<br />
		从-1的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中最后一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_last_index_of("Joe", -1)}<br />
 		从0的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中最后一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_last_index_of("Joe", 0)}<br />
 		从1的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中最后一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_last_index_of("Joe", 1)}<br />
 		从2的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中最后一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_last_index_of("Joe", 2)}<br />
 		从3的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中最后一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_last_index_of("Joe", 3)}<br />
 		从4的位置起, "Joe"在["Joe", "Fred", "Joe", "Susan"]中最后一次出现的位置: ${["Joe", "Fred", "Joe", "Susan"]?seq_last_index_of("Joe", 4)}
		<h2>序列中子变量的数量</h2>
		${['你好', '我好', '他也好']?size}
		<h2>以升序方式返回序列</h2>
		${['hello', 'world', 'thanks', 'word']?sort?join(", ")}<br />
		${[1, 22, 3, 1]?sort?join(", ")}<br />
		${['1900-05-12', '2021-05-12', '1999-01-01', '1900-12-21']?sort?join(", ")}<br />
		${['00:00:01', '12:00:01', '02:00:01', '12:59:01']?sort?join(", ")}<br />
		${['1900-05-12 00:00:01', '1999-05-12 12:00:01', '1900-05-12 10:00:01']?sort?join(", ")}
	</body>
</html>

11.6. 运行项目

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值