OSGi中的速度:如何从类路径加载模板

时间:2011-12-22 11:57:29

标签: java osgi velocity

我正在使用速度模板引擎开发OSGi应用程序。 它适用于通过文件加载器加载我的模板,但现在我必须在我的jar中实现这些模板并将其作为资源加载。

我怎样才能使它发挥作用?

我的代码:

ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", 
    ClasspathResourceLoader.class.getName());
ve.setProperty("classpath.resource.loader.path", "/velocitytemplates");
ve.init();

ve.getTemplate("foo.vm");

这将抛出类似

的异常
  

无法找到资源'index.vm'

     

引起:

     

org.apache.velocity.exception.ResourceNotFoundException:无法找到资源'index.vm'

4 个答案:

答案 0 :(得分:8)

可悲的是,Velocity并不是OSGi友好的。因此,您无法使用内置的ClasspathResourceLoader,也很难添加自定义开发的ResourceLoader。

我建议您应该以任何常规方式将模板作为Reader,并选择以下选项之一:

  • 如果需要合并,请使用VelocityEngine evaulate功能 模板很少(性能无关紧要)
  • 使用Velocity内部类手动创建模板

如果您不必经常合并模板,则可以使用第一个选项,因此性能不是关键要求。

以下是第二个选项的示例,其中创建的模板对象可以通过调用其上的合并函数来重用(期望您已经有一个读取器到您的vm文件或资源):

RuntimeInstance runtimeInstance = new RuntimeInstance();
runtimeInstance.init();
SimpleNode simpleNode = runtimeInstance.parse(reader, "nameOfYourTemplateResource");

Template template = new Template();
simpleNode.init(new InternalContextAdapterImpl(new VelocityContext()), runtimeInstance);
template.setData(simpleNode);

template.merge(...);
...

要获取OSGi中vm文件的读者,您应该选择一个与vm资源位于同一个包中的类,并调用SameBundleClass.class.getResourceAsStream ...您可以使用InputStreamReader将流转换为writer。

请注意,该示例错过了一些try-catch-finally块。

答案 1 :(得分:1)

要验证的两件事

1。类路径问题

确保通过MANIFEST.MF设置OSGi包的类路径以包含一个点:

Bundle-ClassPath: .

点表示在类加载层次结构中包含bundle的根,您的文件夹“velocitytemplates”可能位于该文件夹中。

你需要将Velocity jar文件放在模板文件所在的同一个包中,否则你会遇到类加载问题,因为Velocity会驻留在另一个包中,因此不会看到“velocitytemplates”所有在其类路径中。

2。 ClasspathResourceLoader

没有“路径”

ClasspathResourceLoader不支持设置“路径”,因为它根据定义使用Classpath,因此要么将“velocitytemplates”添加到OSGi包中的Classpath(MANIFESt.MF),要么使用完整路径引用速度模板,即“ velocitytemplates / index.vm“

答案 2 :(得分:0)

我遇到了类加载器模板的类似问题,我想指定一个不同的根。我通过继承ClasspathResourceLoader来解决它。

package my.package;

import java.io.InputStream;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

public class PrefixedClasspathResourceLoader 
    extends ClasspathResourceLoader
{
    /** Prefix to be added to any names */
    private String prefix = "";

    @Override
    public void init(ExtendedProperties configuration) {
        prefix = configuration.getString("prefix","");
    }

    @Override
    public InputStream getResourceStream(String name)
            throws ResourceNotFoundException 
    {
        return super.getResourceStream(prefix+name);
    }
}

设置以下属性

resource.loader=myloader
myloader.resource.loader.class=my.package.PrefixedClasspathResourceLoader
myloader.resource.loader.prefix=/velocitytemplates/

这样,如果你有一个名为“index.vm”的模板,velocity将使用类加载器来查找名为“/velocitytemplates/index.vm”的资源

答案 3 :(得分:0)

两天后,我和一位同事找到了默认的Velocity Engine解决方案:file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader

像这样创建自己的类资源加载器

public static final class PdfResourceLoader extends ResourceLoader

@Override
public void init(ExtendedProperties configuration)
{
}

@Override
public InputStream getResourceStream(String source) throws ResourceNotFoundException
{
  return getClass().getResourceAsStream(source);
}

@Override
public boolean isSourceModified(Resource resource)
{
  return false;
}

@Override
public long getLastModified(Resource resource)
{
  return 0;
}
}

设置新的上下文类加载器

Thread.currentThread().setContextClassLoader(PdfResourceLoader.class.getClassLoader());  
    VelocityEngine ve = new VelocityEngine();

在速度引擎

中更改了默认属性
ve.setProperty("resource.loader", "pdf"); 
ve.setProperty("pdf.resource.loader.class",
PdfResourceLoader.class.getName());
ve.init(); 

示例名称路径模板

String pathTemplate = "/templates/yourTemplateName.html";      
Template t = ve.getTemplate(pathTemplate, "UTF-8"); 

它是