2010-05-28 12 views
41

Mam projekt, w którym chcę załadować szablon prędkości, aby uzupełnić go o parametry. Cała aplikacja jest spakowana jako plik JAR. To, co początkowo myślałem o zrobieniu, to:Ładowanie szablonu prędkości wewnątrz pliku JAR

VelocityEngine ve = new VelocityEngine(); 

    URL url = this.getClass().getResource("/templates/"); 

    File file = new File(url.getFile()); 

    ve = new VelocityEngine(); 
    ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "file"); 
    ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, file.getAbsolutePath()); 
    ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, "true"); 

    ve.init(); 

    VelocityContext context = new VelocityContext(); 

    if (properties != null) { 
    stringfyNulls(properties); 
    for (Map.Entry<String, Object> property : properties.entrySet()) { 
    context.put(property.getKey(), property.getValue()); 
    } 
    } 

    final String templatePath = templateName + ".vm"; 
    Template template = ve.getTemplate(templatePath, "UTF-8"); 
    String outFileName = File.createTempFile("report", ".html").getAbsolutePath(); 
    BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outFileName))); 

    template.merge(context, writer); 

    writer.flush(); 
    writer.close(); 

To działa dobrze, gdy uruchamiam go w czasie zaćmienia. Jednak po spakowaniu programu i próbie uruchomienia go przy użyciu wiersza poleceń pojawia się błąd, ponieważ nie można znaleźć pliku.

Wyobrażam sobie, że problem jest w tym wierszu:

ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, file.getAbsolutePath()); 

Ponieważ w słoiku nie istnieje plik absolutna, ponieważ jest w środku na zamek, ale nie mogę jeszcze znaleźć lepszy sposób to zrobić .

Ktoś ma jakieś pomysły?

+2

z miłości do Boga, podświetl kod w poście i kliknij przycisk kodu, aby poprawnie sformatować go! :) – vicatcu

+0

Czy jesteś pewien, że katalog/templates/zostanie wyeksportowany do twojego słoika? Musisz oznaczyć go jako część ustawień kompilacji i innych rzeczy. – vicatcu

+0

nie wiedział o przycisku kodu, dziękuję. Tak, katalog szablonów dostaje się do pliku JAR. – Rafael

Odpowiedz

67

Jeśli chcesz korzystać z zasobów od ścieżki klasy, należy użyć ładowarkę zasobów na ścieżce klasy:

ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); 
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); 
+0

Przetestuję to! czy wiesz, gdzie mogę znaleźć dokumentację do każdego RuntimeContants i jego możliwych wartości? – Rafael

+0

Nie można go uruchomić, nie znajduje pliku ani w zaćmieniu, ani w słoiku. – Rafael

+0

@Rafael: Naprawiono. 'ClasspathResourceLoader' nie jest domyślnie zarejestrowany. – axtavt

7

ile JAR jest eksplodował, nie można odczytać zasobu w JAR jako plik. Użyj strumienia wejściowego.

Zobacz następujące fragmenty kodu,

InputStream input = classLoader.getResourceAsStream(fileName); 
    if (input == null) { 
     throw new ConfigurationException("Template file " + 
       fileName + " doesn't exist");   
    } 

    InputStreamReader reader = new InputStreamReader(input);    
     Writer writer = null; 

     try { 
      writer = new OutputStreamWriter(output);   

      // Merge template 
      if (!engine.evaluate(context, writer, fileName, reader)) 
       ...... 
17

kod końcowy, opracowany z wykorzystaniem pomysłów przedstawionych w obu odpowiedziach powyżej:

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

      ve.init(); 

      final String templatePath = "templates/" + templateName + ".vm"; 
      InputStream input = this.getClass().getClassLoader().getResourceAsStream(templatePath); 
      if (input == null) { 
       throw new IOException("Template file doesn't exist"); 
      } 

      InputStreamReader reader = new InputStreamReader(input); 

      VelocityContext context = new VelocityContext(); 

      if (properties != null) { 
       stringfyNulls(properties); 
       for (Map.Entry<String, Object> property : properties.entrySet()) { 
        context.put(property.getKey(), property.getValue()); 
       } 
      } 

      Template template = ve.getTemplate(templatePath, "UTF-8"); 
      String outFileName = File.createTempFile("report", ".html").getAbsolutePath(); 
      BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outFileName))); 

      if (!ve.evaluate(context, writer, templatePath, reader)) { 
       throw new Exception("Failed to convert the template into html."); 
      } 

      template.merge(context, writer); 

      writer.flush(); 
      writer.close(); 
+0

Dziękuję, to mi bardzo pomogło! Możliwe, że moja adaptacja działa trochę inaczej, ale używając oceny VelocityEngine # (...), mógłbym pominąć tworzenie szablonu, a połączenie z szablonem # scalić (...) – Argelbargel

+0

działa jak urok. RuntimeInstance rozwiązał mój problem, pozwalając mi załadować szablon w moim pakiecie.Najlepsze rozwiązanie dla OSGI – iberbeu

1

Aby Velocity wygląd szablonów w ścieżce klas:

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

To wygląda dokładnie tak, jak przyjęta odpowiedź. – JKirchartz

+7

Myślę, że trochę się spóźniłeś na imprezę. –

Powiązane problemy