Freemarker这里先扯淡两句,在纯挚的页面利用上来说和JSP个人觉得没有太大的差异,都有比较多的类库支持,不过相对的如果FTL没有做静态化相对的还是JSP的速率要快一些。
但是为什么还是有很多项目用freemarker,网上也有很多文章,这里偷个

我这里比较传统用的IDE工具是Myeclipse2014,所有如果想要有ftl格式的东东高亮支持的话须要配置下插件,同样的网上一大把,这里也偷

在项目中,Spring是支持多个前段引擎的,只是须要在Spring的配置文件中去配置一下,就可以同时支持JSP和FLT了。
除了Spring须要的jar外还须要Freemarker的jar支持,这里我用的freemarker.jar完全的XML

<?xml version=&#34;1.0" encoding="UTF-8"?&gt;<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 开启springmvc的表明支持 --> <mvc:annotation-driven conversion-service="tc" /> <!-- 定义静态资源 --> <mvc:resources location="/static/" mapping="/static/" /> <!-- 制订扫描规则 --> <context:component-scan base-package="com"> <!-- 制订过滤器 --> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository" /> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan> <!-- 可以配置一个全局类型转换器 --> <!-- 配置spring定义的转换工厂类 --> <bean id="tc" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.lovo.converter.GlobalDateConverter"></bean> </set> </property> </bean> <!-- 配置http体数据与JSON转换 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="mappingJackson2HttpMessageConverter"></ref> </list> </property> </bean> <!-- 配置HTTP信息与JSON工具之间的一个转换器 --> <bean id="mappingJackson2HttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> </bean> <!-- 视图解析器 JSP --> <bean id="urlBasedViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> <property name="order" value="1"/> </bean> <!-- 视图解析器 FTL --> <bean id="viewResolverFtl" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/> <property name="contentType" value="text/html; charset=UTF-8"/> <!-- 将要乞降会话属性作为变量暴露给FreeMarker模板利用。
要做到这一点, 可以设置exposeRequestAttributes或者exposeSessionAttributes为true --> <property name="exposeRequestAttributes" value="true" /> <property name="exposeSessionAttributes" value="true" /> <!-- 利用这些宏,必须设置FreeMarkerViewResolver的exposeMacroHelpers属性为true --> <property name="exposeSpringMacroHelpers" value="true" /> <!-- 利用缓存 --> <property name="cache" value="true" /> <property name="suffix" value=".ftl" /> <property name="order" value="0"/> </bean> <!-- 配置freeMarker的模板路径 --> <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="/WEB-INF/ftl/"/> <property name="freemarkerVariables"> <map> <entry key="xml_escape" value-ref="fmXmlEscape" /> </map> </property> <property name="defaultEncoding" value="UTF-8"/> <!-- FreeMarker默认每隔5秒检讨模板是否被更新,如果已经更新了,就会重新加载并剖析模板。
但常常检讨模板是否更新可能比较耗时。
如果你的运用运行在生产模式下,而且你预期模板不会常常更新, 则可以将更新的延迟韶光延长至一个小时或者更久。
可以通过为freemarkerSettings属性设置template_update_delay达到这一目的 --> <property name="freemarkerSettings"> <props> <prop key="template_update_delay">3600</prop> <!-- 设置标签类型 两种:[] 和 <> 。
[] 这种标记解析要快些 --> <prop key="tag_syntax">auto_detect</prop> <prop key="default_encoding">UTF-8</prop> <prop key="output_encoding">UTF-8</prop> <prop key="locale">zh_CN</prop> <!-- 设置韶光格式 --> <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop> <prop key="date_format">yyyy-MM-dd</prop> <!-- 设置数字格式 --> <prop key="number_format">#.##</prop> <!-- 可以知足一样平常须要。
默认情形变量为null则更换为空字符串,如果须要自定义,写上${empty!"EmptyValue of fbysss"}的形式即可 --> <prop key="classic_compatible">true</prop> </props> </property> </bean> <bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape"/> <!-- 配置MultipartResolver 用于文件上传 利用spring的CommosMultipartResolver 解释: p:defaultEncoding="UTF-8":这里设置默认的文件编码为UTF-8,必须与用户JSP的默认编码同等; p:maxUploadSize="5000000":指定文件上传大小,单位为字节; p:uploadTempDir="fileUpload/temp":文件上传临时目录,上传完成后,就会将临时文件删除; --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8" p:maxUploadSize="5000000" p:uploadTempDir="fileUpload/temp"> </bean></beans>

须要把稳一下的是如果只须要FTL作为模板不作为前段引擎,可以不配置视图解析器,如果配置了多个视图解析器,其他视图解析器的优先级一定要高于JSP才行。

<property name="order" value="0"/>

配置完了后写个大略的controller,用法和传统的后台封装参数,前台写JSP写EL表达式一样

jspftlSpring整合JSPFreemarkerftl根本应用 Node.js

import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;@Controller@RequestMapping(value="/ftl")public class ftlController { @RequestMapping(value="/firstFtl.do",method=RequestMethod.GET) public String index(HttpServletRequest requset,HttpServletResponse response,Model mode) { mode.addAttribute("msg", "hi freemarker"); return "MyFtl"; }}

<!DOCTYPE html><html> <head> <title>MyHtml.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta name="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> </head> <body> <b>${msg}</b> </body></html>

首先科普下FreeMarker模板文件紧张有4个部分组成

1、文本,直接输出的部分2、注释,即<#--...-->格式不会输出3、插值(Interpolation):即${..}或者#{..}格式的部分,将利用数据模型中的部分替代输出4、FTL指令:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出。

Freemarker支持各种后台的常用类型,页面也支持条件判断,逻辑运算,首先,我们测试下最常用的后台封装list,前台循环出来,在通过条件去判断

@RequestMapping(value="/expression.do") public String expressionTest(HttpServletRequest requset,HttpServletResponse response,Model mode) { //页面测试用凑集,大略数据类型 List<Object> testList = new ArrayList<Object>(); testList.add("1"); testList.add("2"); testList.add("3"); mode.addAttribute("list",testList); return "expressionTest"; }

<!DOCTYPE html><html> <head> <title>MyHtml.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta name="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> </head> <body> <div > <#--在jsp中${}表达式会直接忽略不显示,而freemarker会报非常,还是一大堆,freemarker就须要您手动去处理--> <#-- ?? 用于判断是否为空 ?number将字符串转换为数字--> <#if list??> <span>凑集长度:${list?size} </span><br> <#list list as a > 凑集的下标:${a_index} 当前凑集值:${a} <#if a?number%2==0>偶数 <#else>奇数 </#if> <br> </#list> <#else> 凑集为空 </#if> </div> </body></html>

这里可以创造在用JSP的过程中我们一样平常不会对null值进行分外的处理判断,JSP默认会处理,当为null时显示为空。
但是在FLT模板中并不会这样,如果未进行非空判断,而直接进行取值,会抛出非常。
常日有两种办法进行处理。

例如现在有个user工具,里面有角色属性办法

1:配置classic_compatible=true,此种办法只能判断一层,如user.role为null,显示为空,若user为空,则仍会发生非常。

办法2:利用!
或者??

${list!'凑集为空'}

如果凑集为空会显示空

?? 用于判断是否为空

<#if user.role??> 当前用户没有权限角色 <#else> 当前用户有权限角色</#if>

${user.role???string}<#--这里将结果以字符串的形式输出:true 或者false-->${user.role???string("YES","NO")} <#--这剖断用户权限角色为空 -->

${user.role!"当前用户没有角色"}<#--获取当前用户的角色:${user.role.rolename!} 而role任然没值的时候依然会报错,而精确的办法<br/>获取当前用户的角色:${(user.role.rolename)!}-->

来完全的处理个null,首先建立一个大略的user工具

package com.lovo.beans;import java.io.Serializable;public class UserBean implements Serializable{ / 省略get set方法 / private static final long serialVersionUID = -2959897964759682757L; private Long id; private String name; private String sex; private Long age; }

掌握器

@RequestMapping(value="/expressionUser.do") public String expressionUset(HttpServletRequest requset,HttpServletResponse response,Model mode) { UserBean bean = new UserBean(); bean.setName("小明"); bean.setAge(20L); bean.setSex(null); //不对classBean做null处理 bean.setClassBean(null); mode.addAttribute("user", bean); return "expressionUser"; }

FTL模板

<!DOCTYPE html><html> <head> <title>MyHtml.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta name="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> </head> <body> <div > 姓名:<input type = "text" value="${user.name}"/><br> 性别:<input type = "text" value="${user.age}"/><br> 年事:<input type = "text" value="${user.sex}"/><br> 班级:<input type = "text" value="${user.classBean.className}"/> </div> </body></html>

会创造报错

这个时候用!和??处理下!
是直接做null判断,后面可以跟值,如果不写,显示为空字符串,??是做是否为空判断,多用作if else中,也可以输出默认值???需用???string("yes","no")

<!DOCTYPE html><html> <head> <title>MyHtml.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta name="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> </head> <body> <div > 姓名:<input type = "text" value="${user.name}"/><br> 性别:<input type = "text" value="${user.age}"/><br> 年事:<input type = "text" value="${user.sex!}"/><br> 班级:<input type = "text" value="${(user.classBean.className)!}"/> 班级:<input type = "text" value="<#if (user.classBean.className)??></#if>"/> 班级:<input type = "text" value="${(user.classBean.className)???string("班级不为空","班级为空")}"/> </div> </body></html>

在页面利用FTL时,不可避免的会操作变量,在Freemarker中变大大致可以分为4种。

数据模型变量,后台封装的变量参数通报到模板中模板中的变量利用,用<#assign>定义局部变量,在指令中的变量循环变量,在循环中的变量

数据模型变量,可以在后台封装成工具,list,map等,这里举例字符串

@RequestMapping(value="/expressionAssagin.do") public String expressionAssagin(HttpServletRequest requset,HttpServletResponse response,Model mode) { mode.addAttribute("root", "后台封装的变量"); return "expressionAssagin"; }

<b>${root}</b>

页面显示

<#assign>定义的变量

<body> 后台封装的变量:<b>${root}</b></br> 页面定义的变量: <#assign username="李四"> ${username} </body>

当页面定义的assign变量名与数据模型变量名相同时,优先展示页面定义的assign变量,不是覆盖数据模型变量,可以利用.globals进行展示

<body> <#assign root="页面变量优先于数据模型变量展示"> 优先展示:<b>${root}</b></br> 指定展示:<b>${.globals.root}</b></br> 页面定义的变量: <#assign username="李四"> ${username}</body>

局部变量

<body> <#assign root="页面变量优先于数据模型变量展示"> 优先展示:<b>${root}</b></br> 指定展示:<b>${.globals.root}</b></br> 页面定义的变量: <#assign username="李四"> ${username}<br> <#--利用local可以声明局部变量,以是在marco宏中局部变量--> <#macro test> <#--此时当调用该指令之后,会将模板中的变量覆盖,不能利用globals,一样平常不该用这种办法在指令中定义变量--> <#local username="我的名字变了"/> <#local sex="性别是保密的"/> 姓名:${username!} 性别${sex!}</br> </#macro> <#--调用宏--> <@test/> ${sex!"局部变量外部是调用不到的"} </body>

循环变量,便是在循环体中利用的变量

<#--循环变量--> <#list 1..3 as num> <#--只能在循环体中利用--> ${num} </#list> ${num!"循环变量出了循环体就消逝了"}