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

Java 在另一个In-Spring应用程序中包含Velocity模板,java,spring,templates,velocity,Java,Spring,Templates,Velocity,我可能想做一些不寻常的事。我有一个SpringWeb应用程序,我正在手动呈现一个velocity模板,这意味着调用 template.merge(context, stringWriter) 以下是我如何从应用程序中获取模板: InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/vml/" + templateName); String templateString = StreamUtils.input

我可能想做一些不寻常的事。我有一个SpringWeb应用程序,我正在手动呈现一个velocity模板,这意味着调用

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\u ROOT
,我也没有使用Velocity类路径资源加载程序

所以我的问题是,我的选择是什么?基本目标是能够手动呈现这些模板,并且能够在另一个模板中包含一个模板,所有这些都在SpringWeb应用程序中

我已尝试通过使用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:找不到资源'/vml/hello.vml'
。我被困在这里,因为这耗尽了我所知道的获取模板的两种方法

以下是
尝试将模板放入WEB-INF/lib目录。出于测试目的,尽量不要创建任何类似vml的子目录,这样当某些东西仍然无法工作时,您就不会感到困惑。

Velocity配置不是Spring中最好的文档部分。而且它已经过时了:即使在4.0.5中,参考文档也声明了对velocity 1.x(fine)和velocity工具(1.x)的依赖关系,这在velocity的最新版本中已被弃用。尽管如此,只要配置了velocity 1.7和velocity tools 2.0,所有工具都可以正常工作

允许velocity在WEB-INF下查找模板的部分是velocity工具的
WebappResourceLoader
。一旦您的
VelocityEngine
被声明使用它来加载模板,所有这些都可以正常工作,包括在其他模板中包含模板

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

resource.loader=webapp
webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader
webapp.resource.loader.path=/WEB-INF/vml
并初始化并正常使用
VelocityEngine

但您也可以使用Spring
VelocityConfigure
,如果您以后想在应用程序(*)中使用velocity视图,这将非常有用。以下是工作应用程序上下文的摘录:

<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"/>
(*)
VelocityLayoutViewResolver
在该环境中正常工作,但为了能够使用2.0 velocity工具箱,我必须修改默认的Spring
VelocityLayoutView
并在resolver中声明我的子类:

在dispatcher 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">
...

我认为其中一个棘手的问题是WEB-INF被分解并部署到一个自定义位置
/usr/share/jboss-5.1.0.GA/server/myServlet/deploy/dev.ear/dev.war/WEB-INF/lib/hello.vml
当我打印文件时,我仍然会得到
org.apache.velocity.exception.resourcennotfoundexception:找不到资源'/hello.vml'
通过
URL[]URL=((URLClassLoader)cl.geturl()指向记录器的类路径;对于(URL-URL:URL){LOGGER.info(“类路径项:+URL.getFile());}
,我看到了
类路径项:/usr/share/jboss-5.1.0.GA/bin/run.jar
,因为模板不在类路径中,而是直接在WEB-INF下(这对于WEB应用程序来说很正常),您不能使用
ClasspathResourceLoader
。那么我的选项是什么?换句话说,如果没有任何velocity初始化的加载程序,我如何将一个模板包含在另一个模板中?或者我必须使用类加载器还是url加载器?我认为通过velocity初始化是可能的。如何初始化
速度引擎
?它是春豆吗?或者您使用的velocity单例模型只使用
velocity
类?它目前不是Springbean,尽管我并不反对尝试这种方法。目前,它的初始化方式如上所述,使用“private static VelocityEngine VelocityEngine=new VelocityEngine();静态{velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER,“classpath”);velocityEngine.setProperty(“classpath.RESOURCE.LOADER.class”,ClasspathResourceLoader.class.getName());velocityEngine.init();}`是的,靠Greyskull的力量!那就行了!谢谢,先生。接下来,我注意到$contextVariable并没有在包含的模板中被解释,而是作为文本字符串“$contextVariable”出现。这些包含的模板中是否没有上下文?我如何做到这一点?我的foreach循环等也被逐字呈现,例如
#foreach($foo in$傻瓜)#end
就是这样出现的。我该怎么办?velocityEngine似乎没有将这些Include识别为velocity模板。也许我需要这样配置它。@davidwillams:在velocity中,
#include
只包含修复文本。您必须使用
#parse
来包含另一个模板。
<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">
...
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());
    }
}