表达式springMacroRequestContext未定义

表达式springMacroRequestContext未定义,spring,spring-mvc,junit,freemarker,htmlunit,Spring,Spring Mvc,Junit,Freemarker,Htmlunit,我正在尝试使用htmlunit、junit和freemarker模板进行freemarker单元测试。但当我使用它时,它给了我这个例外 freemarker.core.InvalidReferenceException: Expression springMacroRequestContext is undefined on line 89, column 134 in spring.ftl. at freemarker.core.TemplateObject.assertNonNull(Tem

我正在尝试使用htmlunit、junit和freemarker模板进行freemarker单元测试。但当我使用它时,它给了我这个例外

freemarker.core.InvalidReferenceException: Expression springMacroRequestContext is undefined on line 89, column 134 in spring.ftl.
at freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:125)
at freemarker.core.TemplateObject.invalidTypeException(TemplateObject.java:135)
at freemarker.core.Dot._getAsTemplateModel(Dot.java:78)
at freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
at freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:86)
at freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
at freemarker.core.Expression.getStringValue(Expression.java:93)
at freemarker.core.DollarVariable.accept(DollarVariable.java:76)
at freemarker.core.Environment.visit(Environment.java:221)
at freemarker.core.IfBlock.accept(IfBlock.java:82)
at freemarker.core.Environment.visit(Environment.java:221)
at freemarker.core.Macro$Context.runMacro(Macro.java:172)
at freemarker.core.Environment.visit(Environment.java:614)
at freemarker.core.UnifiedCall.accept(UnifiedCall.java:106)
at freemarker.core.Environment.visit(Environment.java:221)
at freemarker.core.MixedContent.accept(MixedContent.java:92)
at freemarker.core.Environment.visit(Environment.java:221)
at freemarker.core.Macro$Context.runMacro(Macro.java:172)
at freemarker.core.Environment.visit(Environment.java:614)
at freemarker.core.UnifiedCall.accept(UnifiedCall.java:106)
at freemarker.core.Environment.visit(Environment.java:221)
at freemarker.core.MixedContent.accept(MixedContent.java:92)
at freemarker.core.Environment.visit(Environment.java:221)
at freemarker.core.Environment.process(Environment.java:199)
at freemarker.template.Template.process(Template.java:237)

你知道这个例外情况吗?我如何解决这个问题?提前感谢您的帮助。

我不确定该怎么处理,因为我自己花了大约一个小时试图解决这个问题。但对我有效的是使用以下方法手动将“springMacroRequestContext”添加到数据模型中:

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
model.put("springMacroRequestContext", new RequestContext(request, null, null, null));

请注意,这仍然必须发生在有效请求的内部。因此,这在cron作业或计划任务中可能不起作用,因为当前没有请求。

您需要在Spring controllerContext.xml中配置Freemarker视图解析器。具体而言,增加:

<property name="exposeSpringMacroHelpers" value="true"/>

所以它看起来像:

<bean id="freemarkerViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
    <property name="cache" value="true"/>
    <property name="prefix" value=""/>
    <property name="suffix" value=".ftl"/>
    <property name="exposeSpringMacroHelpers" value="true"/>
    <property name="exposeSessionAttributes" value="true"/>
    <property name="contentType" value="text/html;charset=UTF-8"/>
</bean>

扩展Brad Parks关于手动添加
springMacroRequestContext的答案

有一个对
WebApplicationContext
的引用就足够了(如果对象是WebApplicationContext中的bean,则可以使用
@Autowired
轻松访问该引用),因为您可以模拟请求:

// Declare WebApplicationContext as an instance variable
@Autowired
WebApplicationContext ctx;

// Then in the method...:
    // (The mock object is from the org.springframework.mock.web package)
    MockHttpServletRequest req = new MockHttpServletRequest();
    // secret sauce:
    req.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx);
    // Create a MacroRequestContext for Freemarker to use
    model.put("springMacroRequestContext", new RequestContext(req));

至少对我来说,只有在java内部使用
freemarker.template.template.process
方法生成html时才会发生这种情况。似乎springMacroRequestContext被添加到模型的后期freemarker的正常使用-通过从控制器返回带有模板名称的字符串-不会出现此问题。如果您有权访问
WebApplicationContext
,则可以模拟请求。查看我的答案。如果试图使用
FreeMarkerTemplateUtils.ProcessTemplateIntosString(Template t,Model m)
仅从FreeMarker模板获取字符串输出,则此操作无效。Spring最近反对Velocity,并建议其用户使用FreeMarker来写电子邮件,所以我想这是很多人都在尝试的。