java - 在 Spring 应用程序中的另一个中包含 Velocity 模板

标签 java spring templates velocity

我可能正在尝试做一些不寻常的事情。我有一个 Spring Web 应用程序,我正在手动渲染速度模板,这意味着调用

template.merge(context, stringWriter)

以下是我从应用程序获取模板的方法:

InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/vml/" + templateName);
String templateString = StreamUtils.inputStreamToString(inputStream);
RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices();
StringReader reader = new StringReader(templateString);
SimpleNode node = runtimeServices.parse(reader, templateName);
Template template = new Template();
template.setRuntimeServices(runtimeServices);
template.setData(node);
template.initDocument();

我相信我必须以这种方式加载模板,因为我没有使用 Spring 的 VelocityViewResolver将模板呈现为请求的一部分(这是 Jboss 中后台任务的一部分)。但现在我当然无法在这个模板中包含模板,因为Velocity不知道从哪里获取它们,而且我还没有设置TEMPLATE_ROOT我也没有使用 Velocity ClasspathResourceLoader。

所以我的问题是,我有什么选择?基本目标是能够手动渲染这些模板,并能够将一个模板包含在另一个模板中,所有这些都在 Spring Web 应用程序中进行。

我尝试通过使用 ClasspathResourceLoader

static {
    velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
    velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
    velocityEngine.init();
}

我在 WEB-INF/vml/hello.vml 下放置了一个小的 hello world 模板。当我尝试调用velocityEngine.getTemplate("/vml/hello.vml");时无论 vml 之前有或没有前导正斜杠,我都会得到 org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource '/vml/hello.vml' 。我被困在这里,因为这用尽了我所知道的获取模板的两种方法。

最佳答案

速度配置并不是 Spring 中记录最好的部分。而且它已经相当过时了:即使在 4.0.5 中,引用文档也声明了对velocity 1.x(fine)和velocity-tools(1.x)的依赖,这在最新版本的velocity 中已被弃用。尽管如此,一旦配置了速度 1.7 和速度工具 2.0,一切都可以正常工作

允许velocity在WEB-INF下找到模板的部分是velocity-tools的WebappResourceLoader。一旦您的 VelocityEngine 被声明为使用它来加载模板,一切都会正常工作,包括模板包含在其他模板中。

因此您可以继续以速度方式进行配置。您准备的速度属性包括:

resource.loader=webapp
webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader
webapp.resource.loader.path=/WEB-INF/vml

并初始化并正常使用VelocityEngine

但是您也可以使用 Spring VelocityConfigurer,如果您以后想在应用程序中使用速度 View (*),它可能会很有用。以下是工作应用程序上下文的摘录:

<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
    <property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
    <property name="velocityProperties">
        <props>
            <prop key="input.encoding">UTF-8</prop>
            <prop key="output.encoding">UTF-8</prop>
            <prop key="velocimacro.library">VM_global_library.vm</prop>
            <prop key="resource.loader">webapp</prop>
            <prop key="webapp.resource.loader.class">org.apache.velocity.tools.view.WebappResourceLoader</prop>
            <prop key="webapp.resource.loader.path">/WEB-INF/vlm</prop>
            <prop key="evaluate.provide.scope.control">true</prop>
        </props>
    </property>
</bean>
<bean id="velocityEngine" factory-bean="velocityConfig" factory-method="getVelocityEngine"/>

你会得到一个完全配置的VelocityEngine,Spring可以在你需要的任何bean中注入(inject)它(我认为property name="resourceLoaderPath"是一个scory在旧版本上,但由于它有效,我不敢删除它,并且 VM_global_library.vm 是我自己的速度宏库,位于 webapp.resource.loader.path 下,可从我的所有模板访问)。我目前使用此配置来生成邮件正文。

不,您有速度引擎(直接配置或通过 VelocityConfigurer 配置),您可以使用它来加载和合并模板:

Template template = velocityEngine.getTemplate("/hello.vml");
Context context = new VelocityContext();
context.put(..., ...);
...
template.merge(context, writer);

(*) VelocityLayoutViewResolver 在该环境中可以正常工作,但为了能够使用 2.0 速度工具箱,我必须修改默认的 Spring VelocityLayoutView 并声明我的子类在解析器中:

在调度程序 servlet 中:

<bean class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver"
      id="vmViewResolver" p:order="10" p:suffix=".vm" p:prefix=""
      p:cache="true" p:contentType="text/html;charset=UTF-8"
      p:exposeRequestAttributes="false" p:exposeSessionAttributes="false"
      p:exposePathVariables="true" p:exposeSpringMacroHelpers="true"
      p:dateToolAttribute="date" p:toolboxConfigLocation="/WEB-INF/toolbox.xml"
      p:viewClass="i2.application.commun.web.views.Velocity2LayoutView">
...

和我的Velocity2LayoutView

public class Velocity2LayoutView extends VelocityLayoutView {
    ViewToolManager toolManager;

    @Override
    protected Context createVelocityContext(Map<String, Object> model,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        ViewToolContext context = toolManager.createContext(request, response);
        context.putAll(model);
        return context;
    }

    @Override
    protected void initTool(Object tool, Context velocityContext) throws Exception {
        //super.initTool(tool, velocityContext);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        toolManager = new ViewToolManager(getServletContext(), false, false);
        if (getToolboxConfigLocation() != null) {
            String path = getToolboxConfigLocation();
            logger.debug("Init ViewToolManager with " + path);
            XmlFactoryConfiguration config = new XmlFactoryConfiguration();
            config.read(getServletContext().getResourceAsStream(getToolboxConfigLocation()));
            toolManager.configure(config);
        }
        toolManager.setVelocityEngine(getVelocityEngine());
    }
}

关于java - 在 Spring 应用程序中的另一个中包含 Velocity 模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24441100/

相关文章:

java - 如何在不更改代码的情况下更改tomcat中eclipselink的日志级别?

Spring Redirect 命令重定向到 Load Balancer 下的 Localhost

c++ - 非类型模板参数

java - GWT Guice/Gin 在服务器端的问题

Java 流 : flatMap returns Stream of Objects

java - 嵌入Tomcat 9执行@PostConstruct

java - Spring 3.2资源文件加载问题

spring - 如何使用 Spring Boot 运行 FlyWay clean?

c++ - (不完全)constexpr 模板参数的要求

c++ - 使用自定义构造函数作为模板函数