FTL 使用自定义模板的方法

前言:

1)在实际的工程中,可能存在FTL要引入相同的js或css的代码,每个页面手动copy引入js或css的代码很是麻烦。现在为大家介绍在FTl中定义模板的方法。所谓模板是指:可以指定所有的FTL页面自动加载某些代码工具。

2)在引入模板前,先要引入模板用到jar。jar的名称分别是:sitemesh-2.2.1.jar 和 struts2-sitemesh-plugin-2.0.11.2.jar。在实际的项目中,可以根据struts2的版本,现在对应jar的版本。

3)修改web.xml文件,加入以下内容:

<filter>
	<filter-name>sitemesh</filter-name>
	<filter-class>org.apache.struts2.sitemesh.FreeMarkerPageFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>sitemesh</filter-name>
	<url-pattern>*.action</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>FORWARD</dispatcher>
</filter-mapping>  

 注:filter-mapping的配置应和struts2对应的filter-mapping的配置相同;

 

4)在 WEB-INF目录下面创建文件:sitemesh.xml。内容如下:

<sitemesh>
	<property name="decorators-file" value="/WEB-INF/decorators.xml" />
	<excludes file="${decorators-file}" />

	<page-parsers>
		<parser content-type="text/html"
			class="com.opensymphony.module.sitemesh.parser.FastPageParser" />
	</page-parsers>

	<decorator-mappers>

		<mapper
			class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper">
			<param name="property.1" value="meta.decorator" />
			<param name="property.2" value="decorator" />
		</mapper>

		<mapper
			class="com.opensymphony.module.sitemesh.mapper.FrameSetDecoratorMapper">
		</mapper>

		<mapper
			class="com.opensymphony.module.sitemesh.mapper.AgentDecoratorMapper">
			<param name="match.MSIE" value="ie" />
			<param name="match.Mozilla [" value="ns" />
			<param name="match.Opera" value="opera" />
			<param name="match.Lynx" value="lynx" />
		</mapper>

		<mapper
			class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper">
			<param name="decorator" value="printable" />
			<param name="parameter.name" value="printable" />
			<param name="parameter.value" value="true" />
		</mapper>

		<mapper
			class="com.opensymphony.module.sitemesh.mapper.RobotDecoratorMapper">
			<param name="decorator" value="robot" />
		</mapper>

		<mapper
			class="com.opensymphony.module.sitemesh.mapper.ParameterDecoratorMapper">
			<param name="decorator.parameter" value="decorator" />
			<param name="parameter.name" value="confirm" />
			<param name="parameter.value" value="true" />
		</mapper>

		<mapper
			class="com.opensymphony.module.sitemesh.mapper.FileDecoratorMapper">
		</mapper>

		<mapper
			class="org.apache.struts2.sitemesh.NoneDecoratorMapper">
		</mapper>

		<mapper
			class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
			<param name="config" value="${decorators-file}" />
		</mapper>

	</decorator-mappers>

</sitemesh>

 

 

5)在 WEB-INF目录下面创建文件:decorators.xml。内容如下:

 

<?xml version="1.0" encoding="utf-8"?>

<decorators defaultdir="/WEB-INF/decorators">
	<!-- Any urls that are excluded will never be decorated by Sitemesh -->
	<excludes>
		<pattern>/js/*</pattern>
		<pattern>/css/*</pattern>
		<pattern>/images/*</pattern>
	</excludes>

	<decorator name="main" page="/module/common/decorator/main.dec">
		<pattern>/*</pattern>
	</decorator>
</decorators>

 

注:page="/module/common/decorator/main.dec" 这个的值。其意是:在WEB-INF目录有 "/module/common/decorator 目录,并在其目录下有main.dec的文件。

6)main.dec 文件的内容是:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
	<head>
	    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>FTL模板示例 - ${title}</title>
		<style type="text/css">
		<!--
		body {
			margin-left: 5px;
			margin-right: 5px;
		}
		-->
		</style>
		<script type="text/javascript" src="${base}/js/lib/jquery/jquery-1.4.2.js"></script>
		<script type="text/javascript" src="${base}/js/lib/jquery/jquery.validate.js"></script>
		<script type="text/javascript" src="${base}/js/lib/jquery/jquery.form.js"></script>
	    
	    ${head}
	</head>

	<body>
	<link rel="shortcut icon" href="http://localhost/qq.ico"/>
			${body}
	</body>
</html>

 

注:main.dec 是模板定义文件,模板中定义要自动加载的js和css代码。在这里,我定义人的每个ftl页面自动加载jquery的js文件。文件中还有三个自定义参数。这是将目标页面的对应内容加载到模板中显示。

7)自定义一个view.ftl页面,内容如下:

 

<html>
	<head>
		<title>自动跳转到ftl页面</title>
	</head>
	<body>
	这是ftl页面呀~~
	</body>
</html>

 

 

8)能通action跳转到view.ftl页面,解析后的html如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
	<head>
	    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>FTL模板示例 - 自动跳转到ftl页面</title>
		<style type="text/css">
		<!--
		body {
			margin-left: 5px;
			margin-right: 5px;
		}
		-->
		</style>
		<script type="text/javascript" src="/js/lib/jquery/jquery-1.4.2.js"></script>
		<script type="text/javascript" src="/js/lib/jquery/jquery.validate.js"></script>
		<script type="text/javascript" src="/js/lib/jquery/jquery.form.js"></script>
	    
	    
	</head>
 
	<body>
	<link rel="shortcut icon" href="http://localhost/qq.ico"/>
			这是ftl页面呀~~
	</body>
</html>

 

 

9)目标页面在加载解析时,自动加载了模板中定义的js文件。止此配置成功。

### Java 模板方法设计模式与 FreeMarker FTL 的结合 模板方法设计模式是一种行为型设计模式,定义了一个算法的骨架,而将一些步骤延迟到子类中实现。通过这种方式,可以使得某些特定部分可变,而其他部分保持不变。 在 Java 开发中,FreeMarker 是一种流行的模板引擎,用于生成动态内容(HTML 页面、电子邮件、Word 文档等)。可以通过 FreeMarker 的 `TemplateDirectiveModel` 实现自定义指令,从而模拟模板方法的设计模式[^2]。 以下是基于 FreeMarker 和模板方法设计模式的一个示例: #### 自定义 Directive 类 创建一个抽象基类作为模板方法的核心逻辑,并让具体的子类继承该基类以提供具体实现。 ```java public abstract class AbstractDirective implements TemplateDirectiveModel { @Override public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { // 验证参数 validateParams(params); // 获取上下文写入器 Writer out = env.getOut(); // 执行核心逻辑前的操作 beforeExecute(out); // 调用子类的具体实现 doExecute(env, params, loopVars, body, out); // 执行核心逻辑后的操作 afterExecute(out); } protected abstract void doExecute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body, Writer out) throws TemplateException, IOException; private void validateParams(Map params) throws TemplateException { if (params == null || params.isEmpty()) { throw new TemplateException("缺少必要的参数!", null); } } private void beforeExecute(Writer out) throws IOException { out.write("<div>"); } private void afterExecute(Writer out) throws IOException { out.write("</div>"); } } ``` #### 子类实现 下面是一个具体的子类,实现了父类中的抽象方法 `doExecute`。 ```java public class HighlightDirective extends AbstractDirective { @Override protected void doExecute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body, Writer out) throws TemplateException, IOException { String text = getStringParam("text", params, env); out.write(String.format("<strong>%s</strong>", text)); } private String getStringParam(String key, Map<String, TemplateModel> params, Environment env) throws TemplateException { TemplateScalarModel paramValue = (TemplateScalarModel) params.get(key); if (paramValue != null) { return paramValue.getAsString(); } else { throw new TemplateException("未找到必需的参数:" + key, env); } } } ``` #### 注册自定义 Directive 到 FreeMarker 配置 为了让 FreeMarker 使用上述自定义指令,需要将其注册到配置对象中。 ```java Configuration cfg = new Configuration(Configuration.VERSION_2_3_31); cfg.setClassForTemplateLoading(this.getClass(), "/templates"); // 注册自定义指令 cfg.setSharedVariable("highlight", new HighlightDirective()); ``` #### FreeMarker 模板文件 (`example.ftl`) 在模板文件中调用自定义指令。 ```ftl <@highlight text="这是一个高亮显示的文字"/> ``` 当执行此模板时,最终输出的内容将是: ```html <div><strong>这是一个高亮显示的文字</strong></div> ``` --- ### 总结 上述示例展示了如何使用 FreeMarker 结合模板方法设计模式来构建灵活的模板处理机制。通过定义抽象基类和扩展子类的方式,可以在不改变整体结构的情况下轻松添加新的功能或修改现有功能。 此外,FreeMarker 提供了许多内置的功能和支持,使其成为 IT 行业中广泛使用的工具之一[^4]。例如,在 Web 应用程序开发中,它可以用来生成 HTML 页面;而在企业级应用中,则常被用来生成 Word 或 PDF 报告。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值