2010-05-28 41 views
41

Tôi có một dự án mà tôi muốn tải một mẫu vận tốc để hoàn thành nó với các tham số. Toàn bộ ứng dụng được đóng gói dưới dạng tệp jar. Điều tôi nghĩ ban đầu khi làm là:Tải mẫu vận tốc bên trong tệp 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(); 

Và điều này hoạt động tốt khi tôi chạy nó trong nhật thực. Tuy nhiên, một khi tôi gói chương trình và cố gắng chạy nó bằng cách sử dụng dòng lệnh tôi nhận được một lỗi bởi vì các tập tin không thể được tìm thấy.

Tôi tưởng tượng vấn đề là ở dòng này:

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

Bởi vì trong một cái lọ các tập tin tuyệt đối không tồn tại, vì nó bên trong một zip, nhưng tôi vẫn chưa thể tìm ra cách tốt hơn để làm điều đó .

Có ai có ý tưởng nào không?

+2

cho tình yêu của thần, làm nổi bật mã trong bài đăng của bạn và nhấp vào nút mã để định dạng của nó đúng cách! :) – vicatcu

+0

Bạn có chắc chắn rằng thư mục/templates/đang được xuất vào bình của bạn không? Bạn phải đánh dấu nó là một phần của cài đặt và công cụ xây dựng của bạn. – vicatcu

+0

không biết về nút mã, cảm ơn. Có, các mẫu dir đang nhận được vào tập tin jar. – Rafael

Trả lời

67

Nếu bạn muốn sử dụng các nguồn lực từ classpath, bạn nên sử dụng bộ nạp nguồn cho classpath:

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

Tôi sẽ kiểm tra nó! Bạn có biết nơi tôi có thể tìm thấy tài liệu cho mỗi RuntimeContants và giá trị có thể của nó? – Rafael

+0

Không thể làm cho nó hoạt động, nó không tìm thấy tập tin trong nhật thực cũng như trong bình. – Rafael

+0

@Rafael: Đã sửa lỗi. 'ClasspathResourceLoader' không được đăng ký theo mặc định. – axtavt

7

Trừ JAR được bùng nổ, bạn không thể đọc các tài nguyên trong JAR như tập tin. Sử dụng luồng đầu vào.

Xem sau đoạn mã,

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

mã cuối cùng, phát triển dựa trên ý tưởng trình bày trong cả hai câu trả lời trên:

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

Cảm ơn bạn, điều này đã giúp tôi rất nhiều! Có thể là sự thích ứng của tôi hoạt động hơi khác một chút, nhưng bằng cách sử dụng VelocityEngine # assessment (...), tôi có thể bỏ qua phần instantiation của Template và lời gọi tới Template # merge (...) – Argelbargel

+0

hoạt động như một sự quyến rũ. RuntimeInstance đã giải quyết được sự cố của tôi cho phép tôi tải mẫu trong gói của mình.Giải pháp tốt nhất cho OSGI – iberbeu

1

Để làm Velocity nhìn cho các mẫu trong classpath:

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

Trông giống như câu trả lời được chấp nhận. – JKirchartz

+7

Tôi nghĩ bạn hơi muộn với bữa tiệc. –

Các vấn đề liên quan