踩坑: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!):
==> 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. 即使頁面失敗,也需有失敗的補償。