Spring Freemarker 未获取模型属性的批处理管理自定义问题
Spring Batch Admin Customization Issues with Freemarker Not Picking Up Model Attributes
我目前正在尝试为一个企业项目扩展 Spring Batch Admin。我已经将基本的 SBA 设置集成到我的项目中,但我希望添加一些新功能。我要添加的功能是我在网上找到的 here。到目前为止我遇到的一件事是,当尝试添加新的控制器和 ftl 模板时,模型在将 Controller/Model 绑定到视图时出现问题。
我希望你能帮助我的是扩展 SBA 需要哪些额外的配置(相对逐步)。我不是 Spring 或 Spring Batch 的新手,但我是 Freemarker 的新手。 Freemarker 在传递给模型时如何从我的控制器中获取属性似乎有些混乱。
到目前为止,我已经有了要使用的 ftl 模板(从 SBA 的标准模板中提取)。这基本上是在 spring-batch-admin-manager.jar:
中找到的默认 ftl 文件之一的修改版本
<#import "/spring.ftl" as spring />
<@spring.bind "model"/>
<div id="job-triggers">
<h2>${MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE}</h2>
<p/>
<#if fireTimes??>
<table title="Future Job Executions"
class="bordered-table">
<tr>
<th>Job Name</th>
<th>Date</th>
</tr>
<#list fireTimes as execution>
<#if execution_index % 2 == 0>
<#assign rowClass="name-sublevel1-even" />
<#else>
<#assign rowClass="name-sublevel1-odd" />
</#if>
<tr class="${rowClass}">
<#assign execution_url><@spring.url relativeUrl="${servletPath}/jobs/${execution.jobName?c}"/></#assign>
<td>${execution.jobName}</td>
<td>${execution.date}</td>
</tr>
</#list>
</table>
<#if startJobExecution??>
<ul class="controlLinks">
<#assign executions_url><@spring.url relativeUrl="${servletPath}/jobs/executions"/></#assign>
<li>Rows: ${startJobExecution}-${endJobExecution} of ${totalJobExecutions}</li>
<#if nextJobExecution??><li><a href="${executions_url}?startJobExecution=${nextJobExecution?c}&pageSize=${pageSize!30}">Next</a></li></#if>
<#if previousJobExecution??><li><a href="${executions_url}?startJobExecution=${previousJobExecution?c}&pageSize=${pageSize!30}">Previous</a></li></#if>
<!-- TODO: enable pageSize editing -->
<li>Page Size: ${pageSize!30}</li>
</ul>
</#if>
</#if>
然后我有一个控制器,它有一个 GET 请求的 ModelMap 参数,我用 model.addAttribute("someName", someObject):
将不同的属性放入其中
@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(@ModelAttribute("model") ModelMap model) throws SchedulerException, ParseException {
Scheduler scheduler = appCtx.getBean(SchedulerFactoryBean.class).getObject();
Calendar cal = Calendar.getInstance();
Date from = cal.getTime();
cal.add(Calendar.DATE, 1);
Date to = cal.getTime();
List<FireTime> fireTimes = getFiretimesForTriggers(scheduler, from, to);
Collections.sort(fireTimes);
model.addAttribute("fireTimes", fireTimes);
if(fireTimes.isEmpty()) {
model.addAttribute(MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE,"No firetimes found between " + DATE_FORMAT.format(from) + " and " + DATE_FORMAT.format(to));
} else {
model.addAttribute(MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE, fireTimes.size() + " firetimes found between" + DATE_FORMAT.format(from) + " and " + DATE_FORMAT.format(to));
}
return INDEX_VIEW;
}
除了这几个文件之外,除了在我的 servlet 中定义新视图之外,我真的没有任何其他配置-config.xml:
<import resource="classpath:/applicationContext.xml"/>
<import resource="classpath*:/META-INF/spring/batch/servlet/resources/*.xml" />
<import resource="classpath*:/META-INF/spring/batch/servlet/manager/*.xml" />
<context:component-scan base-package="com.basepackage.where.my.controller.components.are" />
<bean name="firetimesView" parent="standard">
<property name="attributes">
<props merge="true">
<prop key="body">/firetimesView.ftl</prop>
<prop key="titleCode">fire.times.title</prop>
<prop key="titleText">Fire Times</prop>
</props>
</property>
</bean>
我遇到的问题是 Freemarker 给出错误,指出引用的模型组件是无效引用:
freemarker.core.InvalidReferenceException: Expression MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE is undefined on line 5, column 11 in firetimesView.ftl.
freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:124)
freemarker.core.Expression.getStringValue(Expression.java:118)
freemarker.core.Expression.getStringValue(Expression.java:93)
freemarker.core.DollarVariable.accept(DollarVariable.java:76)
freemarker.core.Environment.visit(Environment.java:209)
freemarker.core.MixedContent.accept(MixedContent.java:92)
freemarker.core.Environment.visit(Environment.java:209)
freemarker.core.Environment.include(Environment.java:1482)
freemarker.core.Include.accept(Include.java:169)
freemarker.core.Environment.visit(Environment.java:209)
freemarker.core.MixedContent.accept(MixedContent.java:92)
freemarker.core.Environment.visit(Environment.java:209)
freemarker.core.Environment.process(Environment.java:189)
freemarker.template.Template.process(Template.java:237)
org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:366)
org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:283)
org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:233)
org.springframework.batch.admin.web.freemarker.AjaxFreeMarkerView.renderMergedTemplateModel(AjaxFreeMarkerView.java:107)
org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:263)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)
org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.web.filter.ShallowEtagHeaderFilter.doFilterInternal(ShallowEtagHeaderFilter.java:73)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
我还有 getters/setters 注入和从视图访问变量所需的 getters/setters。关于为什么 Freemarker 无法获取我添加到地图的属性的任何想法?任何帮助将不胜感激!
由于您使用的是 ModelMap
,因此您可以使用 put
而不是 addAttribute
。最后,您的代码应如下所示:
if(fireTimes.isEmpty()) {
model.put(MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE,"No firetimes found between " + DATE_FORMAT.format(from) + " and " + DATE_FORMAT.format(to));
} else {
model.put(MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE, fireTimes.size() + " firetimes found between" + DATE_FORMAT.format(from) + " and " + DATE_FORMAT.format(to));
}
如果这不起作用,请尝试将其设为 Model
而不是 ModelMap
。
我目前正在尝试为一个企业项目扩展 Spring Batch Admin。我已经将基本的 SBA 设置集成到我的项目中,但我希望添加一些新功能。我要添加的功能是我在网上找到的 here。到目前为止我遇到的一件事是,当尝试添加新的控制器和 ftl 模板时,模型在将 Controller/Model 绑定到视图时出现问题。
我希望你能帮助我的是扩展 SBA 需要哪些额外的配置(相对逐步)。我不是 Spring 或 Spring Batch 的新手,但我是 Freemarker 的新手。 Freemarker 在传递给模型时如何从我的控制器中获取属性似乎有些混乱。
到目前为止,我已经有了要使用的 ftl 模板(从 SBA 的标准模板中提取)。这基本上是在 spring-batch-admin-manager.jar:
中找到的默认 ftl 文件之一的修改版本<#import "/spring.ftl" as spring />
<@spring.bind "model"/>
<div id="job-triggers">
<h2>${MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE}</h2>
<p/>
<#if fireTimes??>
<table title="Future Job Executions"
class="bordered-table">
<tr>
<th>Job Name</th>
<th>Date</th>
</tr>
<#list fireTimes as execution>
<#if execution_index % 2 == 0>
<#assign rowClass="name-sublevel1-even" />
<#else>
<#assign rowClass="name-sublevel1-odd" />
</#if>
<tr class="${rowClass}">
<#assign execution_url><@spring.url relativeUrl="${servletPath}/jobs/${execution.jobName?c}"/></#assign>
<td>${execution.jobName}</td>
<td>${execution.date}</td>
</tr>
</#list>
</table>
<#if startJobExecution??>
<ul class="controlLinks">
<#assign executions_url><@spring.url relativeUrl="${servletPath}/jobs/executions"/></#assign>
<li>Rows: ${startJobExecution}-${endJobExecution} of ${totalJobExecutions}</li>
<#if nextJobExecution??><li><a href="${executions_url}?startJobExecution=${nextJobExecution?c}&pageSize=${pageSize!30}">Next</a></li></#if>
<#if previousJobExecution??><li><a href="${executions_url}?startJobExecution=${previousJobExecution?c}&pageSize=${pageSize!30}">Previous</a></li></#if>
<!-- TODO: enable pageSize editing -->
<li>Page Size: ${pageSize!30}</li>
</ul>
</#if>
</#if>
然后我有一个控制器,它有一个 GET 请求的 ModelMap 参数,我用 model.addAttribute("someName", someObject):
将不同的属性放入其中@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(@ModelAttribute("model") ModelMap model) throws SchedulerException, ParseException {
Scheduler scheduler = appCtx.getBean(SchedulerFactoryBean.class).getObject();
Calendar cal = Calendar.getInstance();
Date from = cal.getTime();
cal.add(Calendar.DATE, 1);
Date to = cal.getTime();
List<FireTime> fireTimes = getFiretimesForTriggers(scheduler, from, to);
Collections.sort(fireTimes);
model.addAttribute("fireTimes", fireTimes);
if(fireTimes.isEmpty()) {
model.addAttribute(MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE,"No firetimes found between " + DATE_FORMAT.format(from) + " and " + DATE_FORMAT.format(to));
} else {
model.addAttribute(MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE, fireTimes.size() + " firetimes found between" + DATE_FORMAT.format(from) + " and " + DATE_FORMAT.format(to));
}
return INDEX_VIEW;
}
除了这几个文件之外,除了在我的 servlet 中定义新视图之外,我真的没有任何其他配置-config.xml:
<import resource="classpath:/applicationContext.xml"/>
<import resource="classpath*:/META-INF/spring/batch/servlet/resources/*.xml" />
<import resource="classpath*:/META-INF/spring/batch/servlet/manager/*.xml" />
<context:component-scan base-package="com.basepackage.where.my.controller.components.are" />
<bean name="firetimesView" parent="standard">
<property name="attributes">
<props merge="true">
<prop key="body">/firetimesView.ftl</prop>
<prop key="titleCode">fire.times.title</prop>
<prop key="titleText">Fire Times</prop>
</props>
</property>
</bean>
我遇到的问题是 Freemarker 给出错误,指出引用的模型组件是无效引用:
freemarker.core.InvalidReferenceException: Expression MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE is undefined on line 5, column 11 in firetimesView.ftl.
freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:124)
freemarker.core.Expression.getStringValue(Expression.java:118)
freemarker.core.Expression.getStringValue(Expression.java:93)
freemarker.core.DollarVariable.accept(DollarVariable.java:76)
freemarker.core.Environment.visit(Environment.java:209)
freemarker.core.MixedContent.accept(MixedContent.java:92)
freemarker.core.Environment.visit(Environment.java:209)
freemarker.core.Environment.include(Environment.java:1482)
freemarker.core.Include.accept(Include.java:169)
freemarker.core.Environment.visit(Environment.java:209)
freemarker.core.MixedContent.accept(MixedContent.java:92)
freemarker.core.Environment.visit(Environment.java:209)
freemarker.core.Environment.process(Environment.java:189)
freemarker.template.Template.process(Template.java:237)
org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:366)
org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:283)
org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:233)
org.springframework.batch.admin.web.freemarker.AjaxFreeMarkerView.renderMergedTemplateModel(AjaxFreeMarkerView.java:107)
org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:263)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)
org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.web.filter.ShallowEtagHeaderFilter.doFilterInternal(ShallowEtagHeaderFilter.java:73)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
我还有 getters/setters 注入和从视图访问变量所需的 getters/setters。关于为什么 Freemarker 无法获取我添加到地图的属性的任何想法?任何帮助将不胜感激!
由于您使用的是 ModelMap
,因此您可以使用 put
而不是 addAttribute
。最后,您的代码应如下所示:
if(fireTimes.isEmpty()) {
model.put(MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE,"No firetimes found between " + DATE_FORMAT.format(from) + " and " + DATE_FORMAT.format(to));
} else {
model.put(MODEL_ATTRIBUTE_SEARCH_RESULT_MESSAGE, fireTimes.size() + " firetimes found between" + DATE_FORMAT.format(from) + " and " + DATE_FORMAT.format(to));
}
如果这不起作用,请尝试将其设为 Model
而不是 ModelMap
。