JSP 是个很好的概念,但是它却剥夺了 web 开发的乐趣。 对我而言,这些都是小事,比如无法在页面模板上使用单独的文件header.jsp 和 footer.jsp,不能调用表达式语言的方法,在运行时无法合并,重新排列页面的各个部分。所以我转而使用 FreeMarker 模板。FreeMarker 已经存在一段时间了,如果你最近没有关注过 FreeMarker 的话,那这有些建议给你,让你考虑下个web 应用使用 FreeMarker。
1、类加载没有 PermGen 问题
如果你已经开发Java Web应用程序一段时间,那么对于 JVM 的 PermGen 问题可能并不陌生。由于 FreeMarker 模板不编译成类,它们不占用 PermGen 空间,并不需要一个新的类加载器加载。
2、模板加载器
直接从数据源加载页面和模板岂不是很好?也许从 CMS 或数据库。也许你只想把它们放在一个地方,可以不重新部署整个应用程序就能更新它们。那么在 JSP 中你是很难做到这一点的,但 FreeMarker 提供的模板加载器就是为了 这个目的。你可以使用内建类或者创建你自己的实现。
ClassTemplateLoader:从classpath中加载模板。
FileTemplateLoader:在文件系统中从指定文件夹加载模板。
StringTemplateLoader:从一个字符串 Map 中加载模板。
URLTemplateLoader:从 URL 中加载模板。 你必须要实现 getURL 方法,但应该很容易做到。
WebappTemplateLoader:从 servlet 上下文中加载模板。
FreeMarker 也可以将多个加载器链在一起形成一个系列模板装载器。我通常使用 WebappTemplateLoader 指向 WEB—INF 下一个内容文件夹。
Configuration configuration = new Configuration();
configuration.setTemplateLoader(
new WebappTemplateLoader(servletContext, "WEB-INF/content"));
3、可以在运行时嵌入模板
${title}
并将其添加到另一个模板(site.ftl body区域)。
${body}
4、没有导入
JSP 要求你导入每个你需要使用的类,就像一个常规的 Java 类一样。FreeMarker 模板,嗯,仅仅是模板。可以被包括在另一个模板中,但目前还不需要导入类。
5、支持 JSP 标签
使用 Jsp 的一个理由是有可用性很好的标签库。好消息是 FreeMarker 支持 JSP 标签。坏消息是它们使用 FreeMarker 的语法,不是 JSP 语法。
6、表达式语言中的方法调用
除非你的目标是 Servlet 3.0/El 2.2 标准的容器,那么表达式语言中方法调用是不可用的。不是所有人都同意 EL 表达式中方法调用是一件好事,但是当你需要它们的时候,使用 JSP 真的太痛苦了。 但是 FreeMarker 同等对待其中每个引用。
${customer.address.country}
${customer.getAddress().country}
Invoice Date: ${(customer.invoice.date)!}
感叹号告诉 FreeMarker 对表达式自动检查 null 值和空字符串。如果 customer、invoice 或者 date 中有一个为空值或空字符串,你只会得到标签:
Invoice Date:
另一个选择是感叹号后包括你的默认值。
Invoice Date: ${(customer.invoice.date)!'No Invoice Available'}
如果所有值丢失,你会得到:
Invoice Date: No Invoice Available
Configuration configuration = new Configuration();
configuration.setSharedVariable("app", "StackHunter");
然后像任何其他变量一样访问它。
App: ${app}
在过去使用共享变量一般引用资源包 然后使用像 ${i18n.resourceBundle.key} 这样的表达式来获取值。
${i18n.countries.CA}
${i18n.countries['CA']}
${i18n.countries[countryCode]}
{ 'firstName': 'John', 'lastName': 'Smith', 'age': 25, 'address': { 'streetAddress': '21 2nd Street', 'city': 'New York', 'state': 'NY', 'postalCode': 10021 }}
<#assign user = user?eval>
User: ${user.firstName}, ${user.address.city}