搜索
首页Javajava教程使用Java进行FreeMarker的web模板开发的基础教程

一、概述

FreeMarker 是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯 Java 编写,FreeMarker 被设计用来生成 HTML Web 页面,特别是基于 MVC 模式的应用程序,虽然 FreeMarker 具有一些编程的能力,但通常由 Java 程序准备要显示的数据,由FreeMarker 生成页面,通过模板显示准备的数据(如下图)

使用Java进行FreeMarker的web模板开发的基础教程

FreeMarker 不是一个 Web 应用框架,而适合作为 Web 应用框架一个组件。FreeMarker 与容器无关,因为它并不知道 HTTP 或 Servlet;FreeMarker 同样可以应用于非Web应用程序环境,FreeMarker 更适合作为 Model2 框架(如 Struts)的视图组件,你也可以在模板中使用 JSP标记库。另外,FreeMarker是免费的。

二、Freemarker的准备条件

    freemarker.2.3.16.jar,下载地址这里就不贴了..(这个jar包其实在struts2里面)


三、Freemarker生成静态页面的原理

    Freemarker 生成静态页面,首先需要使用自己定义的模板页面,这个模板页面可以是最最普通的html,也可以是嵌套freemarker中的 取值表达式, 标签或者自定义标签等等,然后后台读取这个模板页面,解析其中的标签完成相对应的操作, 然后采用键值对的方式传递参数替换模板中的的取值表达式,做完之后 根据配置的路径生成一个新的html页面, 以达到静态化访问的目的。


四、Freemarker提供的标签

Freemarker提供了很多有用 常用的标签,Freemarker标签都是885fdb74da354267290f864b346f7f4c这样子命名的,${value} 表示输出变量名的内容 ,具体如下:

1、list:该标签主要是进行迭代服务器端传递过来的List集合,比如:

<#list nameList as names> 
 ${names} 
</#list>

   

name是list循环的时候取的一个循环变量,freemarker在解析list标签的时候,等价于:

for (String names : nameList) {
  System.out.println(names);
}

   

2、if:该标签主要是做if判断用的,比如:

<#if (names=="陈靖仇")>
 他的武器是: 十五~~
</#if>

   

这个是条件判断标签,要注意的是条件等式必须用括号括起来, 等价于:

if(names.equals("陈靖仇")){
  System.out.println("他的武器是: 十五~~");
}

   


3、include:该标签用于导入文件用的。

<#include "include.html"/>

   

这个导入标签非常好用,特别是页面的重用。

另外在静态文件中可以使用${} 获取值,取值方式和el表达式一样,非常方便。

下面举个例子(static.html):





Insert title here


  
描述:${description}

集合大小:${nameList?size}
迭代list集合:
<#list nameList as names> 这是第${names_index+1}个人,叫做: if判断:
<#if (names=="陈靖仇")> 他的武器是: 十五~~ <#elseif (names=="宇文拓")> <#--注意这里没有返回而是在最后面--> 他的武器是: 轩辕剑~· <#else> 她的绝招是:蛊毒~~
迭代map集合:
<#list weaponMap?keys as key> key--->${key}
value----->${weaponMap[key]!("null")} <#-- fremarker 不支持null, 可以用! 来代替为空的值。 其实也可以给一个默认值 value-----${weaponMap[key]?default("null")} 还可以 在输出前判断是否为null <#if weaponMap[key]??>都可以 -->
include导入文件:
<#include "include.html"/>

   

实际代码:

package com.chenghui.test;
  
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
  
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
  
public class CreateHtml {
  public static void main(String[] args) {
    try {
      //创建一个合适的Configration对象
      Configuration configuration = new Configuration();
      configuration.setDirectoryForTemplateLoading(new File("D:\\project\\webProject\\WebContent\\WEB-INF\\template"));
      configuration.setObjectWrapper(new DefaultObjectWrapper());
      configuration.setDefaultEncoding("UTF-8");  //这个一定要设置,不然在生成的页面中 会乱码
      //获取或创建一个模版。
      Template template = configuration.getTemplate("static.html");
      Map<String, Object> paramMap = new HashMap<String, Object>();
      paramMap.put("description", "我正在学习使用Freemarker生成静态文件!");
        
      List<String> nameList = new ArrayList<String>();
      nameList.add("陈靖仇");
      nameList.add("玉儿");
      nameList.add("宇文拓");
      paramMap.put("nameList", nameList);
        
      Map<String, Object> weaponMap = new HashMap<String, Object>();
      weaponMap.put("first", "轩辕剑");
      weaponMap.put("second", "崆峒印");
      weaponMap.put("third", "女娲石");
      weaponMap.put("fourth", "神农鼎");
      weaponMap.put("fifth", "伏羲琴");
      weaponMap.put("sixth", "昆仑镜");
      weaponMap.put("seventh", null);
      paramMap.put("weaponMap", weaponMap);
        
      Writer writer = new OutputStreamWriter(new FileOutputStream("success.html"),"UTF-8");
      template.process(paramMap, writer);
        
      System.out.println("恭喜,生成成功~~");
    } catch (IOException e) {
      e.printStackTrace();
    } catch (TemplateException e) {
      e.printStackTrace();
    }
      
  }
}

   


    这样子基本上可以算的上可以简单的去做一点简单的生成了,但是要在实际中去运用,还是差的很远的,因为freemarker给的标签完全满足不了我们的需要,这时候就需要自定义标签来完成我们的需求了。。 
五、Freemarker自定义标签

Freemarker自定义标签就是自己写标签,然后自己解析,完全由自己来控制标签的输入输出,极大的为程序员提供了很大的发挥空间。

基于步骤:

       以前写标签需要在<后加# ,但是freemarker要识别自定义标签需要在后面加上@,然后后面可以定义一些参数,当程序执行template.process(paramMap, out);,就会去解析整个页面的所有的freemarker标签。

     自定义标签 需要自定义一个类,然后实现TemplateDirectiveModel,重写execute方法,完成获取参数,根据参数do something等等。。

    将自定义标签与解析类绑定在一起需要在paramMap中放入该解析类的实例,存放的key与自定义标签一致即可。。

    注意:在自定义标签中,如果标签内什么也没有,开始标签和结束标签绝对不能再同一行,不然会报错 

freemarker.log.JDK14LoggerFactory$JDK14Logger error

   

  我曾经上当过,这是freemarker 存在的bug。

下面是static.html的例子:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#--自定义变量-->
<#assign num=&#39;hehe&#39;/>
${num}
<br/>
自定义标签
 <@content name="chenghui" age="120">
  ${output}
  ${append}
 </@content>
   
</body>
</html>

   


下面是上面的static.html模板的解析类:

package com.chenghui.test;
  
import static freemarker.template.ObjectWrapper.DEFAULT_WRAPPER;
  
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
  
  
import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
  
/**
 * 自定义标签解析类
 * @author Administrator
 *
 */
public class ContentDirective implements TemplateDirectiveModel{
  
  private static final String PARAM_NAME = "name";
  private static final String PARAM_AGE = "age";
    
  @Override
  public void execute(Environment env, Map params,TemplateModel[] loopVars,
      TemplateDirectiveBody body) throws TemplateException, IOException {
    if(body==null){
      throw new TemplateModelException("null body");
    }else{
      String name = getString(PARAM_NAME, params);
      Integer age = getInt(PARAM_AGE, params);
      //接收到参数之后可以根据做具体的操作,然后将数据再在页面中显示出来。
      if(name!=null){
        env.setVariable("output", DEFAULT_WRAPPER.wrap("从ContentDirective解析类中获得的参数是:"+name+", "));
      }
      if(age!=null){
        env.setVariable("append", DEFAULT_WRAPPER.wrap("年龄:"+age));
      }
      Writer out = env.getOut();
      out.write("从这里输出可以再页面看到具体的内容,就像document.writer写入操作一样。<br/>");
      body.render(out);
        
      /*
      如果细心的话,会发现页面上是显示out.write()输出的语句,然后再输出output的内容,
      可见 在body在解析的时候会先把参数放入env中,在页面遇到对应的而来表单时的才会去取值
      但是,如果该表单时不存在,就会报错, 我觉得这里freemarker没有做好,解析的时候更加会把错误暴露在页面上。
      可以这样子弥补${output!"null"},始终感觉没有el表达式那样好。
      */
    }
  }
    
  /**
   * 获取String类型的参数的值
   * @param paramName
   * @param paramMap
   * @return
   * @throws TemplateModelException
   */
  public static String getString(String paramName, Map<String, TemplateModel> paramMap) throws TemplateModelException{
    TemplateModel model = paramMap.get(paramName);
    if(model == null){
      return null;
    }
    if(model instanceof TemplateScalarModel){
      return ((TemplateScalarModel)model).getAsString();
    }else if (model instanceof TemplateNumberModel) {
      return ((TemplateNumberModel)model).getAsNumber().toString();
    }else{
      throw new TemplateModelException(paramName);
    }
  }
    
  /**
   *
   * 获得int类型的参数
   * @param paramName
   * @param paramMap
   * @return
   * @throws TemplateModelException
   */
  public static Integer getInt(String paramName, Map<String, TemplateModel> paramMap) throws TemplateModelException{
    TemplateModel model = paramMap.get(paramName);
    if(model==null){
      return null;
    }
    if(model instanceof TemplateScalarModel){
      String str = ((TemplateScalarModel)model).getAsString();
      try {
        return Integer.valueOf(str);
      } catch (NumberFormatException e) {
        throw new TemplateModelException(paramName);
      }
    }else if(model instanceof TemplateNumberModel){
      return ((TemplateNumberModel)model).getAsNumber().intValue();
    }else{
      throw new TemplateModelException(paramName);
    }
  }
}

   

然后再前面的实际代码中加上:

//自定义标签解析
paramMap.put("content", new ContentDirective());

   

这样子基本上可以使用,freemarker完成自定义标签了,解决一写简单的业务逻辑, 但是在实际的项目中不可能这样子去做,因为还没有和spring进行集成使用,每次都需要在解析的时候把解析类的实例放进去。。

更多使用Java进行FreeMarker的web模板开发的基础教程相关文章请关注PHP中文网!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Java平台是否独立,如果如何?Java平台是否独立,如果如何?May 09, 2025 am 12:11 AM

Java是平台独立的,因为其"一次编写,到处运行"的设计理念,依赖于Java虚拟机(JVM)和字节码。1)Java代码编译成字节码,由JVM解释或即时编译在本地运行。2)需要注意库依赖、性能差异和环境配置。3)使用标准库、跨平台测试和版本管理是确保平台独立性的最佳实践。

关于Java平台独立性的真相:真的那么简单吗?关于Java平台独立性的真相:真的那么简单吗?May 09, 2025 am 12:10 AM

Java'splatFormIndenceIsnotsimple; itinvolvesComplexities.1)jvmCompatiblemustbeiblemustbeensurecensuredAcrospPlatForms.2)nativelibrariesandsycallsneedcarefulhandling.3)

Java平台独立性:Web应用程序的优势Java平台独立性:Web应用程序的优势May 09, 2025 am 12:08 AM

Java'splatformindependencebenefitswebapplicationsbyallowingcodetorunonanysystemwithaJVM,simplifyingdeploymentandscaling.Itenables:1)easydeploymentacrossdifferentservers,2)seamlessscalingacrosscloudplatforms,and3)consistentdevelopmenttodeploymentproce

JVM解释:Java虚拟机的综合指南JVM解释:Java虚拟机的综合指南May 09, 2025 am 12:04 AM

thejvmistheruntimeenvorment forexecutingjavabytecode,Cocucialforjava的“ WriteOnce,RunanyWhere”能力

Java的主要功能:为什么它仍然是顶级编程语言Java的主要功能:为什么它仍然是顶级编程语言May 09, 2025 am 12:04 AM

JavaremainsatopchoicefordevelopersduetoitsplatFormentence,对象与方向设计,强度,自动化的MememoryManagement和ComprechensivestAndArdArdArdLibrary

Java平台独立性:这对开发人员意味着什么?Java平台独立性:这对开发人员意味着什么?May 08, 2025 am 12:27 AM

Java'splatFormIndependecemeansDeveloperScanWriteCeandeCeandOnanyDeviceWithouTrecompOlding.thisAcachivedThroughThroughTheroughThejavavirtualmachine(JVM),WhaterslatesbyTecodeDecodeOdeIntComenthendions,允许univerniverSaliversalComplatibilityAcrossplatss.allospplats.s.howevss.howev

如何为第一次使用设置JVM?如何为第一次使用设置JVM?May 08, 2025 am 12:21 AM

要设置JVM,需按以下步骤进行:1)下载并安装JDK,2)设置环境变量,3)验证安装,4)设置IDE,5)测试运行程序。设置JVM不仅仅是让其工作,还包括优化内存分配、垃圾收集、性能调优和错误处理,以确保最佳运行效果。

如何查看产品的Java平台独立性?如何查看产品的Java平台独立性?May 08, 2025 am 12:12 AM

toensurejavaplatFormIntence,lofterTheSeSteps:1)compileAndRunyOpplicationOnmultPlatFormSusiseDifferenToSandjvmversions.2)upureizeci/cdppipipelinelikeinkinslikejenkinsorgithikejenkinsorgithikejenkinsorgithikejenkinsorgithike forautomatecross-plateftestesteftestesting.3)

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。