Freemarker無法使用Session和Taglib

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生成靜態文件,再由用戶進行調用。

 

通常前兩種方式對一些數據對象封裝使得使用模板時能進行調用,可以滿足用戶需求。而開始列出的兩個錯誤通常出現在手工進行封裝的時候。舉代碼爲例:

Java代碼 複製代碼
  1. public static void crateHTML(ServletContext context,Map<String,Object> data,String templatePath,String targetHtmlPath){   
  2.     Configuration freemarkerCfg = new Configuration();   
  3.     //加載模版   
  4.     freemarkerCfg.setServletContextForTemplateLoading(context, "/");   
  5.     freemarkerCfg.setEncoding(Locale.getDefault(), "UTF-8");   
  6.     try {   
  7.         //指定模版路徑   
  8.         Template template = freemarkerCfg.getTemplate(templatePath,"UTF-8");   
  9.         template.setEncoding("UTF-8");   
  10.         //靜態頁面路徑   
  11.         String htmlPath = context.getRealPath("/html")+"/"+targetHtmlPath;   
  12.         File htmlFile = new File(htmlPath);   
  13.         Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8"));   
  14.         //處理模版     
  15.         template.process(data, out);   
  16.         out.flush();   
  17.         out.close();   
  18.     } catch (Exception e) {   
  19.         e.printStackTrace();   
  20.     }   
  21. }  
    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標籤了。

可以改爲:

Java代碼 複製代碼
  1. public static void crateHTML(HttpServletRequest request, Map data,   
  2.         String templatePath, String targetHtmlPath) {   
  3.     Configuration freemarkerCfg = new Configuration();   
  4.     // 加載模版   
  5.     freemarkerCfg.setServletContextForTemplateLoading(request.getSession()   
  6.             .getServletContext(), "/");   
  7.     freemarkerCfg.setEncoding(Locale.getDefault(), "UTF-8");   
  8.     try {   
  9.         // 指定模版路徑   
  10.         Template template = freemarkerCfg   
  11.                 .getTemplate(templatePath, "UTF-8");   
  12.         template.setEncoding("UTF-8");   
  13.         // 靜態頁面路徑   
  14.         String htmlPath = request.getSession().getServletContext()   
  15.                 .getRealPath("/html")   
  16.                 + "/" + targetHtmlPath;   
  17.         File htmlFile = new File(htmlPath);   
  18.         Writer out = new BufferedWriter(new OutputStreamWriter(   
  19.                 new FileOutputStream(htmlFile), "UTF-8"));   
  20.         // 處理模版   
  21.   
  22.         data.put("Request", request);   
  23.         data.put("Session", request.getSession());   
  24.         data.put("JspTaglibs"new TaglibFactory(request.getSession()   
  25.                 .getServletContext()));   
  26.            
  27.         template.process(data, out);   
  28.         out.flush();   
  29.         out.close();   
  30.     } catch (Exception e) {   
  31.         e.printStackTrace();   
  32.     }   
  33. }  
	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文件中配置:

Xml代碼 複製代碼
  1. <servlet>  
  2.     <servlet-name>JSPSupportServlet</servlet-name>  
  3.     <servlet-class>  
  4.         org.apache.struts2.views.JspSupportServlet   
  5.     </servlet-class>  
  6.     <load-on-startup>1</load-on-startup>  
  7. </servlet>  

 這時,在ftl模板中可以使用Jsp標籤了。

http://huajiang.javaeye.com/blog/574220

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章