处理 FreeMarker 模板中的错误都有哪些不同的方法?

Posted

技术标签:

【中文标题】处理 FreeMarker 模板中的错误都有哪些不同的方法?【英文标题】:What are different ways to handle error in FreeMarker template?处理 FreeMarker 模板中的错误有哪些不同的方法? 【发布时间】:2013-02-13 22:44:57 【问题描述】:

如何抑制 FreeMarker 模板错误? 我在看这里:http://freemarker.sourceforge.net/docs/pgui_config_errorhandling.html 但我不明白如何“TemplateExceptionHandler.IGNORE_HANDLER”。我正在使用 Struts2 以及如何显示另一个 ftl 页面而不是显示堆栈跟踪?

class MyTemplateExceptionHandler implements TemplateExceptionHandler 
    public void handleTemplateException(TemplateException te, Environment env, java.io.Writer out)
            throws TemplateException 
        try 
            out.write("[ERROR: " + te.getMessage() + "]");
         catch (IOException e) 
            throw new TemplateException("Failed to print error message. Cause: " + e, env);
        
    


...

cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());

在http://freemarker.sourceforge.net/docs/pgui_config_errorhandling.html找到了上面的文章 我该如何使用它?最后一行,cfg 是从哪里来的?

“FreeMarker API 的主要入口点”...http://massapi.com/source/freemarker-2.3.18/src/freemarker/template/Configuration.java.html

所以,这是主要的入口点,我猜 cfg 来自这个类。我仍然没有看到控制器将如何进入我的 MyTemplateExceptionHandler 类。

以下行需要去哪里?

cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());

只是将这条线放在正确的位置吗?

这就是我现在的班级的样子:

    import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.Properties;

import freemarker.cache.FileTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.cache.WebappTemplateLoader;
import freemarker.core.Environment;
import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.jsp.TaglibFactory;
import freemarker.ext.servlet.HttpRequestHashModel;
import freemarker.ext.servlet.HttpRequestParametersHashModel;
import freemarker.ext.servlet.HttpSessionHashModel;
import freemarker.ext.servlet.ServletContextHashModel;
import freemarker.template.ObjectWrapper;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.TemplateModel;

import javax.servlet.GenericServlet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.views.JspSupportServlet;
import org.apache.struts2.views.freemarker.FreemarkerManager;
import org.apache.struts2.views.freemarker.ScopesHashModel;
import org.apache.struts2.views.freemarker.StrutsBeanWrapper;
import org.apache.struts2.views.freemarker.StrutsClassTemplateLoader;
import org.omg.CORBA.PUBLIC_MEMBER;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.util.ValueStack;

public class MyTemplateExceptionHandler extends org.apache.struts2.views.freemarker.FreemarkerManager 

    freemarker.template.Configuration configuration = new freemarker.template.Configuration();

    public MyTemplateExceptionHandler() 
        System.out.println("MyTemplateExceptionHandler constructor()");
        configuration.setTemplateExceptionHandler(new Test1());
    

    class Test1 implements TemplateExceptionHandler 

        @Override
        public void handleTemplateException(TemplateException te, Environment env, java.io.Writer out) throws TemplateException 
            System.out.println("MyTemplateExceptionHandler1 handleTemplateException()");
            try 
                out.write("[ERROR TEST TEST: " + te.getMessage() + "]");
             catch (IOException e) 
                throw new TemplateException("Failed to print error message. Cause: " + e, env);
            
        
    

我的代码将进入 MyTemplateExceptionHandler 构造函数()。但不能进入 MyTemplateExceptionHandler1 handleTemplateException()。我需要做什么?

我仍然看到黄色的 FTL 堆栈跟踪。

这个博客上也指出了同样的事情:http://blog.cherouvim.com/freemarker-exception-handling/ 我在哪里配置我的 freemarker 以及如何配置?我仍然不知道那条线需要去哪里。

我的另一个问题是,博客上发布的类似乎是一个内部类,我是把那个内部类放到任何类中还是那是一个外部类?

【问题讨论】:

【参考方案1】:

如果你想在 freemarker 中处理它,使用它的attempt-recover 机制:

<#attempt>
  attempt block
<#recover>
  recover block
</#attempt>

类似于 Java 的 try-catch。

【讨论】:

不,我正在为产品发布做准备。我需要从一个地方处理所有事情。我喜欢上面的答案,但我仍然找不到一些例子。 这是个好方法【参考方案2】:

如果您想在 Struts2 中将 TemplateExceptionHandler 设置为 TemplateExceptionHandler.IGNORE_HANDLER,您需要扩展 org.apache.struts2.views.freemarker.FreemarkerManager 类,覆盖 initcreateConfiguration 方法并在 struts.properties 文件中配置您的自定义管理器。

struts.freemarker.manager.classname = your.package.YourFreeMarkerManager  

更新

您的自定义 FreemarkerManager 应如下所示:

public class MyFreemarkerManager extends
    org.apache.struts2.views.freemarker.FreemarkerManager 

private static final Logger LOG = LoggerFactory
        .getLogger(MyFreemarkerManager.class);

@Override
public void init(ServletContext servletContext) throws TemplateException 
    config = createConfiguration(servletContext);

    // Set defaults:
    config.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
    contentType = DEFAULT_CONTENT_TYPE;

    // Process object_wrapper init-param out of order:
    wrapper = createObjectWrapper(servletContext);
    if(LOG.isDebugEnabled()) 
        LOG.debug("Using object wrapper of class " + wrapper.getClass().getName());
    
    config.setObjectWrapper(wrapper);

    // Process TemplatePath init-param out of order:
    templatePath = servletContext.getInitParameter(INITPARAM_TEMPLATE_PATH);
    if(templatePath == null) 
        templatePath = servletContext.getInitParameter("templatePath");
    

    config
            .setTemplateLoader(createTemplateLoader(servletContext, templatePath));

    loadSettings(servletContext);


@Override
protected Configuration createConfiguration(ServletContext servletContext)
        throws TemplateException 
    Configuration configuration = new Configuration();

    configuration
            .setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);

    if(mruMaxStrongSize > 0) 
        configuration.setSetting(Configuration.CACHE_STORAGE_KEY, "strong:"
                + mruMaxStrongSize);
    
    if(templateUpdateDelay != null) 
        configuration.setSetting(Configuration.TEMPLATE_UPDATE_DELAY_KEY,
                templateUpdateDelay);
    
    if(encoding != null) 
        configuration.setDefaultEncoding(encoding);
    

    configuration.setWhitespaceStripping(true);

    return configuration;


将该常量放入您的 struts.xml 文件中:

<constant name="struts.freemarker.manager.classname" value="your_package.MyFreemarkerManager" /> 

【讨论】:

有什么例子吗?我在哪里可以找到一些代码示例?有什么参考吗?我在哪里可以更深入地了解这一点?谢谢。 @NomanArain:看看org.apache.struts2.views.freemarker.FreemarkerManager 类。 嘿,如果你能回答我最新的问题,那真的很有帮助。这条线需要去哪里:cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());?只是将这条线放在正确的位置吗? 在 Struts2 中,您需要创建自己的自定义类来扩展 org.apache.struts2.views.freemarker.FreemarkerManager。看一下这个类的源代码,你会看到TemplateExceptionHandler 的设置位置。 我在这里看到:docjar.com/html/api/org/apache/struts2/views/freemarker/… 但是该类与freemarker.sourceforge.net/docs/pgui_config_errorhandling.html 提供的内部类有什么关系?我不明白看 FreemarkerManager 课程对我有什么帮助?【参考方案3】:

您还可以将freemarker.properties 与以下key=value 一起使用:

template_exception_handler = rethrow

只需将您的 freemarker.properties 放在类路径中即可。

我认为这是一种更清洁的方法。

【讨论】:

这将无法创建您自己的异常处理程序

以上是关于处理 FreeMarker 模板中的错误都有哪些不同的方法?的主要内容,如果未能解决你的问题,请参考以下文章

java 用freemark的好处

在 Freemarker 模板中显示 Spring MVC 验证错误

在 Freemarker 中使用 NetSuite 日期

处理 Mozilla Firefox 中的“可见性:折叠”错误都有哪些好的解决方法?

Netsuite / Freemarker - 访问电子邮件模板中的交易行级别数据

FreeMarker 模板错误:以下已评估为 null 或缺失 |但不是真的