簡體   English   中英

OSGi中的速度:如何從類路徑加載模板

[英]Velocity in OSGi: how to load templates from classpath

我正在開發一個帶速度模板引擎的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'

可悲的是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.類路徑問題

確保通過MANIFEST.MF設置OSGi包的類路徑以包含一個點:

Bundle-ClassPath: .

點表示在類加載層次結構中包含bundle的根,您的文件夾“velocitytemplates”可能駐留在該層次結構中。

並且你需要將Velocity jar文件放在模板文件所在的同一個包中,否則你會得到類加載問題,因為Velocity將駐留在另一個包中,因此根本不會看到“velocitytemplates”類路徑。

2. ClasspathResourceLoader沒有“路徑”

ClasspathResourceLoader不支持設置“路徑”,因為它根據定義使用Classpath,因此要么將“velocitytemplates”添加到OSGi包中的Classpath(MANIFESt.MF),要么使用完整路徑引用速度模板,即“velocitytemplates / index” .vm”

2天后,我和一位同事發現了Velocity Engine默認的解決方案:file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader

像這樣創建自己的類Resource loader

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"); 

就是這樣

我遇到了類加載器模板的類似問題,我想指定一個不同的根。 我通過繼承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”的資源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM