009_字符串内建函数

1. 内建函数就像FreeMarker在对象中添加的方法一样。要防止和实际方法和其它子变量的命名冲突, 则不能使用点(.), 这里使用问号(?)来和父对象分隔开。

2. 为了简洁, 如果方法没有参数, 那么就可以忽略(), 比如: 想要获取path的长度, 就可以写作: path?length, 而不是path?length()。

3. 内建函数关键性的另外一个原因是FreeMarker不会暴露对象的Java API。尽管Java的String类有length()方法, 但在模板中却是不可见的, 就不得不使用path?length来代替。这里的优点是模板不依赖下层Java对象的精确类型。

4. boolean

4.1. 字符串转为布尔值。字符串必须是true或false, 或者必须是由boolean_format设置的特定格式。

4.2. 如果字符串不是适当的格式, 那么当访问该内建函数时, 就会发成错误终止模板处理。

4.3. boolean_format的默认字符串是"true,false"。

4.4. FreeMarker还自带了一个boolean_format是c的值。

4.5. boolean_format用户还可以自定义, 使用逗号分割真和假的值。

5. cap_first

5.1. 字符串中的首单词的首字母大写。

6. uncap_first

6.1. 和cap_first相反。字符串中首单词的首字母小写。

7. capitalize

7.1. 字符串中所有单词的首字母大写。

8. upper_case

8.1. 字符串的大写形式。

9. lower_case

9.1. 字符串的小写形式。

10. contains

10.1. 如果函数中的参数指定的子串出现在源字符串中, 那么返回true。

11. starts_with

11.1. 字符串是否以指定的子字符串开头, 返回布尔值。

12. ends_with

12.1. 字符串是否以指定的子字符串结尾, 返回布尔值。

13. ensure_starts_with

13.1. 如果字符串没有以第一个参数指定的子串开头, 那么就会将它加到字符串开头, 否则返回原字符串。

13.2. 如果指定两个参数, 那么第一个参数就被解释成Java正则表达式, 如果它不匹配字符串的开头, 那么第二个参数指定的字符串就会添加到字符串开头。

13.3. 该方法也接受第三个标志位参数。"r"查找的子串是正则表达式。i比较是大小写不敏感的。值得注意的一点是当不需要第一参数被解释成正则表达式, 而只是普通文本, 但是又想让比较是大小写不敏感的, 那么此时就需要使用"i"作为第三个参数。

14. ensure_ends_with

14.1. 如果字符串没有以第一个参数指定的子串结尾, 那么就会将它加到字符串后面, 否则返回原字符串。

15. index_of

15.1. 返回第一次字符串中出现子串时的索引位置。不要忘了第一个字符的索引是0。

15.2. 你可以使用第二个参数指定开始搜索的索引位置。

15.3. 第二个参数的数值没有限制。如果它是负数, 那就和是0是相同效果了; 如果它比字符串的长度还大, 那么就和它是字符串长度那个数值是一个效果。小数会被切成整数。

16. last_index_of

16.1. 返回最后一次(最右边)字符串中出现子串时的索引位置。它返回子串第一个(最左边)字符所在位置的索引。

16.2. 可以使用第二个参数来指定开始搜索的索引。要注意第二个参数暗示了子串开始的最大索引。

16.3. 对第二个参数的数值没有限制: 如果它是负数, 会始终返回-1; 如果它比字符串的长度还大, 那么就和它是字符串长度那个数值是一个效果。小数会被切成整数。

16.4. 如果第一个参数作为子串没有在该字符串中出现时(如果你使用了第二个参数, 那么就从给定的序列开始), 那么就返回-1。

17. html/xhtml

17.1. 字符串按照html标记输出。也就是说, 下面字符串将会被替代:

  1. < 替换为 <
  2. > 替换为 >
  3. & 替换为 &
  4. " 替换为 "
  5. ' 替换为 '

18. keep_before

18.1. 移除字符串的一部分, 该部分是从给定子串开始的部分。

18.2. 如果参数字符串没有找到, 它会返回空串。如果参数是长度为0的字符串, 它会返回源字符串, 不会改变。

18.3. 该方法接受可选的标志位参数, 作为它的第二个参数。

19. keep_after

19.1. 移除字符串中的一部分内容, 该部分是给定子串第一次出现之前的部分。

19.2. 如果参数字符串没有找到, 它会返回空串。如果参数是长度为0的字符串, 它会返回源字符串, 不会改变。

19.3. 该方法接受可选的标志位参数, 作为它的第二个参数。

20. keep_before_last

20.1. 和keep_before相同, 但是保留参数最后一次出现之前的部分, 而不是第一次出现之前。

21. keep_after_last

21.1. 和keep_after相同, 但是它会保留参数最后一次出现后的部分, 而不是第一次。

22. left_pad

22.1. 如果它仅仅用1个参数, 那么它将在字符串的开始插入空白, 直到整个串的长度达到参数指定的值。如果字符串的长度达到指定数值或者比指定的长度还长, 那么就什么都不做了。

22.2. 如果使用了两个参数, 那么第一个参数表示的含义和你使用一个参数时的相同, 第二个参数指定用什么东西来代替空白字符。

22.3. 第二个参数也可以是个长度比1大的字符串。那么这个字符串会周期性的插入。

22.4. 第二个参数必须是个字符串值, 而且至少有一个字符。

23. right_pad

23.1. 它和left_pad 相同, 但是它从末尾开始插入字符而不是从开头。

24. length

24.1. 字符串中字符的数量。

25. number

25.1. 字符串转化为数字格式。这个数字必须是"计算机语言"格式。也就是说, 它必须是本地化独立的形式, 小数的分隔符就是一个点, 没有分组。

25.2. 此外, 它也识别科学记数法(比如 "1.23E6", "1.5e-8") 。

26. replace

26.1. 在源字符串中, 用另外一个字符串来替换原字符串中出现它的部分。它不处理词的边界。

26.2. 替换是从左向右执行的。比如: ${"aaaaa"?replace("aaa", "X")}, 将会输出Xaa。

26.3. 如果第一个参数是空字符串, 那么所有的空字符串将会被替换, 比如: "foo"?replace("","|"), 就会得到 "|f|o|o|"。

26.4. replace 接受可选的 标志位参数, 作为它的第三参数。

27. remove_beginning

27.1. 从字符串的开头移除参数中的子串, 如果它不以参数中的子串开头, 那么就或者返回原字符串。

28. remove_ending

28.1. 从字符串的结尾移除参数中的子串, 如果它不以参数中的子串结尾, 那么就或者返回原字符串。

29. split

29.1. 它被用来根据另外一个字符串的出现将原字符串分割成字符串序列。

30. trim

30.1. 去掉字符串首尾的空格。

30. url

30.1. 在URL之后的字符串进行转义。这意味着, 所有非US-ASCII的字符和保留的URL字符将会被%XX形式转义。

30.2. 请注意, 它会转义所有保留的URL字符(/,  =,  &, 等...), 所以可以被用来编码查询参数值。

30.3. 为了进行URL转义, 必须要选择字符集, 它被用来计算被转义的部分(%XX)。

30.4. 如果内建函数url没有参数, 那么它会使用由url_escaping_charset设置的字符集。这个设置应该被软件设置, 包括FreeMarker(比如Web应用框架), 因为它默认不会被设置(null)。 如果它没有被设置, 那么FreeMarker退回使用output_encoding的设置, 这个也会被默认设置, 所以它也是又软件设置的。如果output_encoding也没有被设置, 那么没有参数的内建函数url 将不会被执行, 而且它会引起运行时错误。当然, 有参数的url函数将会执行。

30.5. 用setting指令在模板中设置url_escaping_charset是可能的。至少在真实的MVC应用中, 这是一个不好的实践行为。output_encoding不能由setting指令来设置, 所以它应该是软件的工作。

31. url_path

31.1. 它和url内建函数相同, 只是它不转义斜杠(/)字符。这就是意味着用来转义使用了斜杠(不是反斜杠!)的路径(比如操作系统或一些内容仓库的路径), 转义之后它们可以插入到URL中。需要该转义的常用原因是文件夹名称或文件名称可能含有非US-ASCII字母("国家"标准符号)。

32. word_list

32.1. 包含字符串中所有单词的序列, 顺序为出现在字符串中的顺序。单词是不间断的字符序列, 包含了任意字符, 但是没有空白。

33. 通用标志

33.1. 很多字符串内建函数接受可选的字符串参数, 它们被称为"标志"。在这个字符串中, 每个字母影响内建函数一个特定方面的行为。比如, 字母i说明内建函数不应该区别相同字母的小写和大写变化。标志字符串中的字母顺序是不重要的。

33.2. 下面是字母(标志)的完整列表

33.2.1. i: 不区别相同字母的小写和大写变化。

33.2.2. f: 只是第一个。

33.2.3. r: 查找的子串是正则表达式。

33.2.4. m: 正则表达式的多行模式。在多行正则表达式^和$, 各自匹配行终止符或字符串结尾。

33.2.5. s: 开启正则表达式的dot-all模式。在dot-all模式下, 表达式.匹配任意字符串, 包含行终止符。默认情况下, 该表达式不匹配行终止符。

33.2.6. c: 允许正则表达式中的空白和注释。

33.3. 下表是支持使用这些通用标志的内建函数

34. 例子

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

34.2. 编写FMFactory.java

package com.fm.util;

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");
		// url转义编码
		cfg.setURLEscapingCharset("utf-8");
		// 输出编码
		cfg.setOutputEncoding("utf-8");
		// 设置可以进行布尔值格式化的值
		cfg.setBooleanFormat("开,关");
		cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
		map.put(path, cfg);
		
		return cfg;
	}
	
}

34.3. 编写BuiltInsForStrings.java

package com.fm.action;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
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 BuiltInsForStrings 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("builtinsforstrings.html");
		
		Map<String, Object> root = new HashMap<String, Object>();
		root.put("date", new Date(0));
		root.put("time", new Time(0));
		root.put("datetime", new Timestamp(0));
		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);
	}
}

34.4. 修改web.xml

34.5. 在/WEB-INF/templates下编写builtinsforstrings.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>字符串内建函数</title>
	</head>
	<body>
		<h2>字符串转为布尔值</h2>
		<#assign bln = "true" />
		<#if bln?boolean>
			字符串"true"转布尔值成功。
		</#if>
		<#assign bln = "开" />
		<#if bln?boolean>
			字符串"开"转布尔值成功。
		</#if>
		<h2>字符串中的首单词的首字母大写</h2>
		${"chinese china"?cap_first}
		<h2>字符串中首单词的首字母小写</h2>
		${"China And Chinese"?uncap_first}
		<h2>字符串中所有单词的首字母大写</h2>
		${"china chinese"?capitalize}
		<h2>字符串的大写形式</h2>
		${"China And Chinese"?upper_case}
		<h2>字符串的小写形式</h2>
		${"China And Chinese"?lower_case}
		<h2>包含字符串</h2>
		<#if "我们是中国人"?contains("中国人")>
			我们是中国人包含<b>中国人</b>。
		</#if>
		<h2>字符串转换成日期值, 时间或日期-时间值</h2>
		${"1970-1-1"?date}
		${"8:00:00"?time}
		${"1970-1-1 8:00:00"?datetime}
		<h2>字符串是否以指定的子字符串开头</h2>
		<#if "我们是中国人"?starts_with("我们")>
			我们是中国人以<b>我们</b>开头。
		</#if>
		<h2>字符串是否以指定的子字符串结尾</h2>
		<#if "我们是中国人"?ends_with("中国人")>
			我们是中国人以<b>中国人</b>结尾。
		</#if>
		<h2>以指定字符串开头</h2>
		${"WEB-INF/templates"?ensure_starts_with("/")}<br />
		${"localhost:8080/"?ensure_starts_with("https?://", "http://")}<br />
		<#--  r查找的子串是 正则表达式。i比较是大小写不敏感的。-->
		${"HTTPS://localhost:8080/"?ensure_starts_with("https?://", "http://", "ri")}
		<h2>以指定字符串结尾</h2>
		${"WEB-INF/templates"?ensure_ends_with("/")}
		<h2>返回第一次字符串中出现子串时的索引位置</h2>
		"我们是中国人我们是中国人", 第一个"们"的位置: ${"我们是中国人我们是中国人"?index_of("们")}<br />
		"我们是中国人我们是中国人", 从第-3的位置起, 第一个"们"的位置: ${"我们是中国人我们是中国人"?index_of("们", -3)}<br />
		"我们是中国人我们是中国人", 从第20的位置起, 第一个"们"的位置: ${"我们是中国人我们是中国人"?index_of("们", 20)}<br />
		"我们是中国人我们是中国人", 从第7的位置起, 第一个"们"的位置: ${"我们是中国人我们是中国人"?index_of("们", 7)}
		<h2>返回最后一次(最右边)字符串中出现子串时的索引位置</h2>
		"abcabc", 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab")}<br />
		"abcabc", 从-2的位置算, 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab", -2)}<br />
		"abcabc", 从-1的位置算, 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab", -1)}<br />
		"abcabc", 从0的位置算, 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab", 0)}<br />
		"abcabc", 从1的位置算, 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab", 1)}<br />
		"abcabc", 从2的位置算, 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab", 2)}<br />
		"abcabc", 从3的位置算, 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab", 3)}<br />
		"abcabc", 从4的位置算, 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab", 4)}<br />
		"abcabc", 从5的位置算, 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab", 5)}<br />
		"abcabc", 从6的位置算, 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab", 6)}<br />
		"abcabc", 从7的位置算, 最后一次"ab"出现的位置: ${"abcabc"?last_index_of("ab", 7)}
		<h2>字符串按照html标记输出</h2>
		${"<b>\"true\" & 'false'</b>"?html}
		<h2>移除字符串中的一部分内容</h2>
		<#--  \s匹配空格 -->
		${"abcdef"?keep_before("de")}<br />
		${"foo : bar"?keep_before(r"\s*:\s*", "r")}<br />
		${"abcdefgh"?keep_after("de")}<br />
		${"foo : bar"?keep_after(r"\s*:\s*", "r")}<br />
		${"foo.bar.txt"?keep_before_last(".")}<br />
		${"foo.bar.txt"?keep_after_last(".")}
		<h2>开始位置插入足量空白</h2>
		<pre>[${"abc"?left_pad(6)}]</pre>
		<pre>[${"abc"?left_pad(3)}]</pre>
		[${"abc"?left_pad(6, "-")}]<br />
		[${"abc"?left_pad(6, "-*&")}]
		<h2>结束位置插入足量空白</h2>
		<pre>[${"abc"?right_pad(6)}]</pre>
		<pre>[${"abc"?right_pad(3)}]</pre>
		[${"abc"?right_pad(6, "-")}]<br />
		[${"abc"?right_pad(6, "-*&")}]
		<h2>字符串中字符的数量</h2>
		"我们都是中国人。"字符数量: ${"我们都是中国人。"?length}
		<h2>字符串转化为数字格式</h2>
		"123"转化为数字格式: ${"123"?number}<br />
		"1.23E6"转化为数字格式: ${"1.23E6"?number}<br />
		"1.5e-8"转化为数字格式: ${"1.5e-8"?number}
		<h2>替换字符串</h2>
		${"我们都是中国人。我们都是中国人。"?replace("们都", "")}<br />
		${"我们都是中国人。"?replace("", "|")}<br />
		${"aaaaa"?replace("aaa", "X")}<br />
		${"aaaaaAAAAA"?replace("aaa", "X", "i")}<br />
		<h2>从字符串的开头移除参数中的子串</h2>
		${"abcdef"?remove_beginning("abc")}<br />
		${"defabc"?remove_beginning("abc")}
		<h2>从字符串的结尾移除参数中的子串</h2>
		${"defabc"?remove_ending("def")}<br />
		${"abcdef"?remove_ending("def")}
		<h2>分割字符串</h2>
		<#list "some,,test,text,"?split(",") as x>
			"${x}"<br />
		</#list>
		<h2>去掉字符串首尾的空格</h2>
		[${" 你好哇     "?trim}]
		<h2>在URL之后的字符串进行转义</h2>
		${"a/b c"?url("ISO-8859-1")}<br />
		${"<>'"?url("UTF-8")}<br />
		<#-- 设置url转义编码, 最好不要在这里设置, 在程序里设置。 -->
		<#setting url_escaping_charset="UTF-8">
		${"a/b c"?url}<br />
		${"<>'"?url}
		<h2>url_path不转义斜杠</h2>
		${"/<>/'/"?url_path("UTF-8")}
		<h2>包含字符串中所有单词的序列</h2>
		<#assign words = "   a bcd, .   1-2-3"?word_list />
		<#list words as word>${word}<#sep><br /></#sep></#list>
	</body>
</html>

34.6. 运行项目

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值