1. 程式人生 > >踩坑:springboot+freemarker 第二個引數丟失變為FreeMarker

踩坑:springboot+freemarker 第二個引數丟失變為FreeMarker

一個用springboot+freemarker做的頁面,發生了一件奇怪的事。

頁面出了問題後,自動第二次請求get,第一個引數保留,第二個引數被自動替換為FreeMarker

Controller的寫法:

@RequestMapping("content/{order}/{district}")
publicStringgetTravelPage(@PathVariable Stringorder, @PathVariable Stringdistrict, Map<String, Object> model) throwsIOException{
longorderId = 0;
try{
        
//... StringpicSrc = ""; model.put("PicSrc", picSrc); //... } catch(Exceptionex) { logger.warn("getContent Exception ", order, ex); } return"content"; }

第一遍請求url: localhost:8080/content/123/456

執行到return "content"這一句自動返回controller函式第一行,開始第二遍請求url: localhost:8080/content/123/FreeMarker

為什麼會請求第二遍?

為什麼第二個引數看起來是丟失賦了預設值?

看了頁面的sourcecode, 原因:

content頁面:

<img class="topicBox-img" src=${PicSrc}  />

這是第一個需要的引數,controller裡面會對freemarker的所有引數賦值,但是由於程式異常,這裡的賦值沒有賦,直接跳到catch Exception裡面執行。return 的頁面裡面PicSrc是空值。

頁面渲染到src=null報錯,提示資訊:

<div class="topicBox">

<img class="topicBox-img" src=FreeMarker template error (DEBUG mode; use RETHROW in production!):

The following has evaluated to null or missing:
==> PicSrc  [in template "content.ftl" at line 12, column 41]

由於src是資源,瀏覽器要載入和訪問資源,於是自動訪問路徑,但是由於報錯的提示資訊賦在了src後面,瀏覽器把第一個單詞(空格分隔)認為是src的值,瀏覽器是層級訪問,現在已經載入了第一層,也就是localhost:8080/content/123,img的src變為localhost:8080/content/123/FreeMarker

這時又命中的controller的規則,第二次進入controller, 且從int形的引數變成string,又出現錯誤,徹底載入不了了,頁面變為一段報錯資訊:

PicSrc [in template "content.ftl" at line 12, column 41] ---- Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>

如果頁面載入的第一個引數不是src的值,而是一段text則不會二次訪問controller, 直接顯示報錯頁面。

解決方法:

1. src等資源要做空的相容

src=${PicSrc?default('/image/initial.jpg')}

2. try...catch之後也要對model賦值,保證頁面需要的引數不是空的。

3. 即使頁面失敗,也需有失敗的補償。