Freemarker无法使用Session和Taglib

    技术2025-06-10  32

    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代码 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标签了。

    可以改为:

    Java代码 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文件中配置:

    Xml代码 <servlet>      <servlet-name>JSPSupportServlet</servlet-name>      <servlet-class>          org.apache.struts2.views.JspSupportServlet       </servlet-class>      <load-on-startup>1</load-on-startup>  </servlet>   <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

     

    最新回复(0)