Freemarker中取Session中對象出現Expression Session is undefined異常,
還有在模板中無法使用jsp標籤,出現Expression JspTaglibs is undefined異常。
其實兩個原因是相同的,都是在ftl模板中沒有找到對應的對象Session或 JspTaglibs ,通常我們使用freemarker有三種手段。
其一,是通過使用freemarker.ext.servlet.FreemarkerServlet。在web.xml中配置freemarkerServlet就可以通過*.ftl直接訪問指定路徑的freemarker模板,並生成對應的文件/流進行輸出。我認爲這種方式最簡便的一種,然而其中生成的文件被限定爲html或xml文件,編碼之類都被統一處理,對於不同輸出要進行多次配置。
第二種方式是使用頁面框架,這些頁面框架都是調用freemarker配置使用模板進行輸出,最大好處是與現有框架集成,可以使用頁面框架的一些特性,並且可以進行一定程序定製,如指定文件類型和編碼等。
第三種方式是手動進行封裝,直接調用配置使用模板生成指定的內容。其有個好處,是可以進行定製,如文件類型和編碼都可以進行指定的配置,並且更多人是使用模板生成指定文件進行頁面靜態化,程序員通過將後臺信息使用freemarker生成靜態文件,再由用戶進行調用。
通常前兩種方式對一些數據對象封裝使得使用模板時能進行調用,可以滿足用戶需求。而開始列出的兩個錯誤通常出現在手工進行封裝的時候。舉代碼爲例:
- public static void crateHTML(ServletContext context,Map<String,Object> data,String templatePath,String targetHtmlPath){
- Configuration freemarkerCfg = new Configuration();
- //加載模版
- freemarkerCfg.setServletContextForTemplateLoading(context, "/");
- freemarkerCfg.setEncoding(Locale.getDefault(), "UTF-8");
- try {
- //指定模版路徑
- Template template = freemarkerCfg.getTemplate(templatePath,"UTF-8");
- template.setEncoding("UTF-8");
- //靜態頁面路徑
- String htmlPath = context.getRealPath("/html")+"/"+targetHtmlPath;
- File htmlFile = new File(htmlPath);
- Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8"));
- //處理模版
- template.process(data, out);
- out.flush();
- out.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
public static void crateHTML(ServletContext context,Map<String,Object> data,String templatePath,String targetHtmlPath){
Configuration freemarkerCfg = new Configuration();
//加載模版
freemarkerCfg.setServletContextForTemplateLoading(context, "/");
freemarkerCfg.setEncoding(Locale.getDefault(), "UTF-8");
try {
//指定模版路徑
Template template = freemarkerCfg.getTemplate(templatePath,"UTF-8");
template.setEncoding("UTF-8");
//靜態頁面路徑
String htmlPath = context.getRealPath("/html")+"/"+targetHtmlPath;
File htmlFile = new File(htmlPath);
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8"));
//處理模版
template.process(data, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
在以上代碼中,就會出現問題,直接調用template進行輸出時,並沒有封裝Session,JspTaglibs等對象,所以會報找不到對應對象的錯誤,也就不能使用Jsp標籤了。
可以改爲:
- public static void crateHTML(HttpServletRequest request, Map data,
- String templatePath, String targetHtmlPath) {
- Configuration freemarkerCfg = new Configuration();
- // 加載模版
- freemarkerCfg.setServletContextForTemplateLoading(request.getSession()
- .getServletContext(), "/");
- freemarkerCfg.setEncoding(Locale.getDefault(), "UTF-8");
- try {
- // 指定模版路徑
- Template template = freemarkerCfg
- .getTemplate(templatePath, "UTF-8");
- template.setEncoding("UTF-8");
- // 靜態頁面路徑
- String htmlPath = request.getSession().getServletContext()
- .getRealPath("/html")
- + "/" + targetHtmlPath;
- File htmlFile = new File(htmlPath);
- Writer out = new BufferedWriter(new OutputStreamWriter(
- new FileOutputStream(htmlFile), "UTF-8"));
- // 處理模版
- data.put("Request", request);
- data.put("Session", request.getSession());
- data.put("JspTaglibs", new TaglibFactory(request.getSession()
- .getServletContext()));
- template.process(data, out);
- out.flush();
- out.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
public static void crateHTML(HttpServletRequest request, Map data,
String templatePath, String targetHtmlPath) {
Configuration freemarkerCfg = new Configuration();
// 加載模版
freemarkerCfg.setServletContextForTemplateLoading(request.getSession()
.getServletContext(), "/");
freemarkerCfg.setEncoding(Locale.getDefault(), "UTF-8");
try {
// 指定模版路徑
Template template = freemarkerCfg
.getTemplate(templatePath, "UTF-8");
template.setEncoding("UTF-8");
// 靜態頁面路徑
String htmlPath = request.getSession().getServletContext()
.getRealPath("/html")
+ "/" + targetHtmlPath;
File htmlFile = new File(htmlPath);
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(htmlFile), "UTF-8"));
// 處理模版
data.put("Request", request);
data.put("Session", request.getSession());
data.put("JspTaglibs", new TaglibFactory(request.getSession()
.getServletContext()));
template.process(data, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
這時,在ftl模板中就可以調用Request,Session,JspTaglibs等對象了。
注:在Struts2中封裝的Freemarker視圖也不能在ftl模板中使用JspTaglibs對象,可能通過在web.xml文件中配置:
- <servlet>
- <servlet-name>JSPSupportServlet</servlet-name>
- <servlet-class>
- org.apache.struts2.views.JspSupportServlet
- </servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
這時,在ftl模板中可以使用Jsp標籤了。
http://huajiang.javaeye.com/blog/574220