1.引入核心依赖
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency>
2.编辑 web.xml 文件(使用 3.0 的版本)
<servlet> <servlet-name>freemarkerServlet</servlet-name> <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class> <init-param> <param-name>TemplatePath</param-name> <param-value>/</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>freemarkerServlet</servlet-name> <url-pattern>*.ftl</url-pattern> </servlet-mapping>
3.编写一个 servlet(至此,整合 Servlet 已经结束)
@WebServlet("/test01") public class TestServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Template template = FreemarkerUtils.getTemplate("2.ftl"); Map<String, Object> rootMap = new HashMap<>(); rootMap.put("username", "tomtom"); rootMap.put("addr", "nanjing"); req.getRequestDispatcher("template/f01.ftl").forward(req, resp); } }
4.开始自定义一个标签
1.1 首先编写一个工具类
public class FreemarkerUtils { private static Configuration configuration; private static Configuration buildCofiguration() { if(null == configuration) { configuration = new Configuration(Configuration.VERSION_2_3_23); configuration.setSharedVariable("origin", new MySimpleDirective()); File dirFile = new File("D:/ij-workspace/xxx/my-web/src/main/resources/"); try { configuration.setDirectoryForTemplateLoading(dirFile); } catch (Exception e) { e.printStackTrace(); } return configuration; } return configuration; } public static Template getTemplate(String filename) { try { Template template = buildCofiguration().getTemplate(filename); return template; } catch (Exception e) { e.printStackTrace(); } return null; } }
1.2 实现自定义指令
public class MySimpleDirective implements TemplateDirectiveModel { @Override public void execute(Environment env, Map map, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { System.out.println("MySimpleDirective..." + " , map is : " + map); Writer out = env.getOut(); int count = Integer.parseInt(map.get("count") + ""); for(int i = 0; i < 1; i++) { //可以在内容强加上前置(也可以直接拼接在 下面的 content 中) out.write(" predix "); //将 body 中内容交给 writer 处理,但并不由输出流写出。而是将内容取出,此时可以针对内容做任何处理 MyWriter myWriter = new MyWriter(); body.render(myWriter); String content = myWriter.getContent(); out.write(content); //可以在内容后加上后置 out.write(" suffix"); } } static class MyWriter extends Writer { private StringBuilder builder = new StringBuilder(); public String getContent() { return builder.toString(); } @Override public void write(char[] cbuf, int off, int len) throws IOException { //这里是分段显示的,每个插值表达式作为一个段,比如模板中的内容 "---${username}---${addr}" 将分成 5 段 // writer.write(new String(cbuf)); builder.append(new String(cbuf)); } @Override public void flush() throws IOException { System.out.println("flush"); } @Override public void close() throws IOException { System.out.println("close"); } } }
1.3 编写 2.ftl,内容如下:
<@origin count=3 warn=5>--- ${username} --- ${addr}</@origin>
1.4 编写测试类
public static void main(String[] args) throws Exception { Template template = FreemarkerUtils.getTemplate("2.ftl"); Map<String, Object> rootMap = new HashMap<>(); rootMap.put("username", "tomtom"); rootMap.put("addr", "nanjing"); Writer out = new OutputStreamWriter(System.out); template.process(rootMap, out); System.out.println(" over"); }
1.5 相关参考链接
https://freemarker.apache.org/docs/pgui_datamodel_directive.html