Spring整合JSP,F(xiàn)reemarker(ftl)基本使用

FTL自己用得比較少换团,這里做個(gè)備份記錄悉稠,以免忘記。

Freemarker這里先扯淡兩句艘包,在單純的頁面使用上來說和JSP個(gè)人感覺沒有太大的區(qū)別的猛,都有比較多的類庫支持耀盗,不過相對(duì)的如果FTL沒有做靜態(tài)化相對(duì)的還是JSP的速度要快一些。但是為什么還是有很多項(xiàng)目用freemarker卦尊,網(wǎng)上也有很多文章叛拷,這里偷個(gè)懶,傳送門:http://blog.csdn.net/qq897958555/article/details/53560655

我這里比較傳統(tǒng)用的IDE工具是Myeclipse2014猫牡,所有如果想要有ftl格式的東東高亮支持的話需要配置下插件胡诗,同樣的網(wǎng)上一大把,這里也偷懶了,傳送門:http://blog.csdn.net/ylyanglei/article/details/50464515

在項(xiàng)目中淌友,Spring是支持多個(gè)前段引擎的煌恢,只是需要在Spring的配置文件中去配置一下,就可以同時(shí)支持JSP和FLT了震庭。除了Spring需要的jar外還需要Freemarker的jar支持瑰抵,這里我用的freemarker.jar
完整的XML

<?xml version="1.0" encoding="UTF-8"?>
<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" />
    <!-- 定義靜態(tài)資源 -->
    <mvc:resources location="/static/" mapping="/static/**" />

    <!-- 制定掃描規(guī)則 -->
    <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>

    <!-- 可以配置一個(gè)全局類型轉(zhuǎn)換器 -->
    <!-- 配置spring定義的轉(zhuǎn)換工廠類 -->
    <bean id="tc"
        class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.lovo.converter.GlobalDateConverter"></bean>
            </set>
        </property>
    </bean>


    <!-- 配置http消息體數(shù)據(jù)與JSON轉(zhuǎn)換 -->
    <bean
        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="mappingJackson2HttpMessageConverter"></ref>
            </list>

        </property>
    </bean>
    <!-- 配置HTTP消息信息與JSON對(duì)象之間的一個(gè)轉(zhuǎn)換器 -->
    <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"/>
        <!-- 將請(qǐng)求和會(huì)話屬性作為變量暴露給FreeMarker模板使用。要做到這一點(diǎn)器联,
                       可以設(shè)置exposeRequestAttributes或者exposeSessionAttributes為true 
        -->
        <property name="exposeRequestAttributes" value="true" />
        <property name="exposeSessionAttributes" value="true" />
        <!-- 使用這些宏二汛,必須設(shè)置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默認(rèn)每隔5秒檢查模板是否被更新,如果已經(jīng)更新了拨拓,就會(huì)重新加載并分析模板肴颊。 
                       但經(jīng)常檢查模板是否更新可能比較耗時(shí)。如果你的應(yīng)用運(yùn)行在生產(chǎn)模式下渣磷,而且你預(yù)期模板不會(huì)經(jīng)常更新婿着,   
             則可以將更新的延遲時(shí)間延長至一個(gè)小時(shí)或者更久。 可以通過為freemarkerSettings屬性設(shè)置template_update_delay達(dá)到這一目的 
        -->  
        <property name="freemarkerSettings">
            <props>
                <prop key="template_update_delay">3600</prop>
                <!-- 設(shè)置標(biāo)簽類型 兩種:[] 和 <> 醋界。[] 這種標(biāo)記解析要快些 --> 
                <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>
                <!-- 設(shè)置時(shí)間格式 -->
                <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
                <prop key="date_format">yyyy-MM-dd</prop>
                <!-- 設(shè)置數(shù)字格式 -->  
                <prop key="number_format">#.##</prop>
                <!-- 可以滿足一般需要竟宋。默認(rèn)情況變量為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":這里設(shè)置默認(rèn)的文件編碼為UTF-8丘侠,必須與用戶JSP的默認(rèn)編碼一致; 
        p:maxUploadSize="5000000":指定文件上傳大小逐样,單位為字節(jié)蜗字; p:uploadTempDir="fileUpload/temp":文件上傳臨時(shí)目錄,上傳完成后脂新,就會(huì)將臨時(shí)文件刪除秽澳; -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
        p:defaultEncoding="UTF-8" p:maxUploadSize="5000000" p:uploadTempDir="fileUpload/temp">
    </bean>
</beans>

需要注意一下的是如果只需要FTL作為模板不作為前段引擎,可以不配置視圖解析器戏羽,如果配置了多個(gè)視圖解析器,其他視圖解析器的優(yōu)先級(jí)一定要高于JSP才行楼吃。

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

配置完了后寫個(gè)簡單的controller,用法和傳統(tǒng)的后臺(tái)封裝參數(shù)始花,前臺(tái)寫JSP寫EL表達(dá)式一樣

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>
image.png

首先科普下
FreeMarker模板文件主要有4個(gè)部分組成
1妄讯、文本,直接輸出的部分
2酷宵、注釋亥贸,即<#--...-->格式不會(huì)輸出
3、插值(Interpolation):即${..}或者#{..}格式的部分,將使用數(shù)據(jù)模型中的部分替代輸出
4浇垦、FTL指令:FreeMarker指令炕置,和HTML標(biāo)記類似,名字前加#予以區(qū)分男韧,不會(huì)輸出朴摊。

Freemarker支持各種后臺(tái)的常用類型,頁面也支持條件判斷此虑,邏輯運(yùn)算甚纲,首先,我們測試下最常用的后臺(tái)封裝list朦前,前臺(tái)循環(huán)出來介杆,在通過條件去判斷

 @RequestMapping(value="/expression.do")
    public String expressionTest(HttpServletRequest requset,HttpServletResponse response,Model mode)
    {
        //頁面測試用集合,簡單數(shù)據(jù)類型
        
        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中${}表達(dá)式會(huì)直接忽略不顯示,而freemarker會(huì)報(bào)異常韭寸,還是一大堆春哨,freemarker就需要您手動(dòng)去處理-->
        <#--  ?? 用于判斷是否為空   ?number將字符串轉(zhuǎn)換為數(shù)字-->
        <#if list??>
        <span>集合長度:${list?size} </span><br>
        <#list list as a >
            集合的下標(biāo):${a_index}
            當(dāng)前集合值:${a}&nbsp;
            <#if a?number%2==0>偶數(shù)
            <#else>奇數(shù)
            </#if>
            <br>
        </#list>
        <#else>
        集合為空
        </#if>
        
    
    </div>
  </body>
</html>

image.png

這里可以發(fā)現(xiàn)在用JSP的過程中我們一般不會(huì)對(duì)null值進(jìn)行特殊的處理判斷,JSP默認(rèn)會(huì)處理恩伺,當(dāng)為null時(shí)顯示為空赴背。但是在FLT模板中并不會(huì)這樣,如果未進(jìn)行非空判斷莫其,而直接進(jìn)行取值癞尚,會(huì)拋出異常。通常有兩種方式進(jìn)行處理乱陡。

例如現(xiàn)在有個(gè)user對(duì)象浇揩,里面有角色屬性
方式1:配置classic_compatible=true,此種方式只能判斷一層憨颠,如user.role為null胳徽,顯示為空,若user為空爽彤,則仍會(huì)發(fā)生異常养盗。
方式2:使用!或者适篙?往核?

${list!'集合為空'}

如果集合為空會(huì)顯示空

?? 用于判斷是否為空

<#if user.role??>
 當(dāng)前用戶沒有權(quán)限角色
 <#else>
 當(dāng)前用戶有權(quán)限角色
</#if>

${user.role???string}<#--這里將結(jié)果以字符串的形式輸出:true 或者false-->
${user.role???string("YES","NO")} <#--這判定用戶權(quán)限角色為空 -->
${user.role!"當(dāng)前用戶沒有角色"}
<#--獲取當(dāng)前用戶的角色:${user.role.rolename!}  而role任然沒值的時(shí)候依然會(huì)報(bào)錯(cuò),而正確的方式<br/>獲取當(dāng)前用戶的角色:${(user.role.rolename)!}-->

來完整的處理個(gè)null嚷节,首先建立一個(gè)簡單的user對(duì)象

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);
        //不對(duì)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>
        班級(jí):<input type = "text" value="${user.classBean.className}"/>
    </div>
  </body>
</html>

會(huì)發(fā)現(xiàn)報(bào)錯(cuò)

image.png
image.png

這個(gè)時(shí)候用!和聂儒?虎锚?處理下!是直接做null判斷衩婚,后面可以跟值窜护,如果不寫,顯示為空字符串非春,柱徙??是做是否為空判斷奇昙,多用作if else中护侮,也可以輸出默認(rèn)值???需用???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>
        班級(jí):<input type = "text" value="${(user.classBean.className)!}"/>
        班級(jí):<input type = "text" value="<#if (user.classBean.className)??></#if>"/>
        班級(jí):<input type = "text" value="${(user.classBean.className)???string("班級(jí)不為空","班級(jí)為空")}"/>
    </div>
  </body>
</html>


image.png

在頁面使用FTL時(shí),不可避免的會(huì)操作變量敬矩,在Freemarker中變大大致可以分為4種概行。

  1. 數(shù)據(jù)模型變量,后臺(tái)封裝的變量參數(shù)傳遞到模板中
  2. 模板中的變量使用弧岳,用<#assign>定義
  3. 局部變量凳忙,在指令中的變量
  4. 循環(huán)變量,在循環(huán)中的變量

數(shù)據(jù)模型變量禽炬,可以在后臺(tái)封裝成對(duì)象涧卵,list,map等腹尖,這里舉例字符串

@RequestMapping(value="/expressionAssagin.do")
    public String expressionAssagin(HttpServletRequest requset,HttpServletResponse response,Model mode)
    {
        mode.addAttribute("root", "后臺(tái)封裝的變量");
        return "expressionAssagin";
    }
<b>${root}</b>

頁面顯示


image.png

<#assign>定義的變量

<body>
        后臺(tái)封裝的變量:<b>${root}</b></br>
        頁面定義的變量:
     <#assign username="李四">
     ${username}
    
  </body>
image.png

當(dāng)頁面定義的assign變量名與數(shù)據(jù)模型變量名相同時(shí)柳恐,優(yōu)先展示頁面定義的assign變量,不是覆蓋數(shù)據(jù)模型變量热幔,可以使用.globals進(jìn)行展示

<body>
    <#assign root="頁面變量優(yōu)先于數(shù)據(jù)模型變量展示">
        優(yōu)先展示:<b>${root}</b></br>
        指定展示:<b>${.globals.root}</b></br>
        
     頁面定義的變量:
     <#assign username="李四">
     ${username}
</body>
image.png

局部變量

<body>
    <#assign root="頁面變量優(yōu)先于數(shù)據(jù)模型變量展示">
        優(yōu)先展示:<b>${root}</b></br>
        指定展示:<b>${.globals.root}</b></br>
        
        頁面定義的變量:
     <#assign username="李四">
     ${username}<br>
     
     <#--使用local可以聲明局部變量乐设,所以在marco宏中局部變量-->
     <#macro test>
        <#--此時(shí)當(dāng)調(diào)用該指令之后,會(huì)將模板中的變量覆蓋绎巨,不能使用globals捧韵,一般不使用這種方式在指令中定義變量-->
        <#local  username="我的名字變了"/>
        <#local  sex="性別是保密的"/>
        姓名:${username!}&nbsp;性別${sex!}</br>
     </#macro>
     <#--調(diào)用宏-->
     <@test/>
     ${sex!"局部變量外部是調(diào)用不到的"}
  </body>
image.png

循環(huán)變量移稳,就是在循環(huán)體重使用的變量

<#--循環(huán)變量-->
     <#list 1..3 as num>
     <#--只能在循環(huán)體中使用-->
        ${num}
     </#list>
     ${num!"循環(huán)變量出了循環(huán)體就消失了"}
image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子挠他,更是在濱河造成了極大的恐慌呕童,老刑警劉巖巴刻,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狠鸳,死亡現(xiàn)場離奇詭異,居然都是意外死亡留瞳,警方通過查閱死者的電腦和手機(jī)拒迅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坪它,你說我怎么就攤上這事骤竹。” “怎么了往毡?”我有些...
    開封第一講書人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長靶溜。 經(jīng)常有香客問我开瞭,道長,這世上最難降的妖魔是什么罩息? 我笑而不...
    開封第一講書人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任嗤详,我火速辦了婚禮,結(jié)果婚禮上瓷炮,老公的妹妹穿的比我還像新娘葱色。我一直安慰自己,他們只是感情好娘香,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開白布苍狰。 她就那樣靜靜地躺著,像睡著了一般烘绽。 火紅的嫁衣襯著肌膚如雪淋昭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評(píng)論 1 299
  • 那天安接,我揣著相機(jī)與錄音翔忽,去河邊找鬼。 笑死盏檐,一個(gè)胖子當(dāng)著我的面吹牛歇式,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胡野,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼材失,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了给涕?” 一聲冷哼從身側(cè)響起豺憔,我...
    開封第一講書人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎够庙,沒想到半個(gè)月后恭应,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耘眨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年昼榛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胆屿,死狀恐怖奥喻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情非迹,我是刑警寧澤环鲤,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站憎兽,受9級(jí)特大地震影響冷离,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纯命,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一西剥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧亿汞,春花似錦瞭空、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至碍粥,卻和暖如春鳖眼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嚼摩。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來泰國打工钦讳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枕面。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓愿卒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親潮秘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子琼开,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容