2014-09-24 29 views
0

我有一個問題,我需要一些幫助。在運行時加載jar和使用它的類

問題聲明: 我正在使用一個jar以excel工作表格式生成報告。只有當用戶想要以excel格式生成報告時,才需要該jar。其他格式的報告是htmltxt,不需要這個罐子。

當前用戶以html格式生成報告,所以他說,爲什麼我應該下載這個jar並將其導出到classpath,因爲我不需要以excel格式報告。

現在的問題是,如果這個jar被刪除,這個構建將失敗/因爲所有正在使用的類的導入都會給出錯誤。 Class.forName可以在運行時加載類,並不會給我錯誤,但是由於我無法使用該類的引用,因此我將無法使用該類的方法。

有什麼出路或這是不可能的?

+0

如果拿走'.jar',你的程序就不能引用裏面的變量或方法。 「你有什麼出路或這是不可能的」是什麼意思? – theGreenCabbage 2014-09-24 10:22:32

+0

@CloseVoters,我認爲很清楚beeing在這裏問了什麼。 – A4L 2014-09-24 10:27:35

回答

0

問題是你很難連接你的依賴關係。所以你的代碼需要爲第三方庫做一些import。你需要的是鬆散地耦合第三方庫,這樣你的應用程序的核心就不需要導入與第三方庫相關的任何東西。使用一個界面,該界面定義了以任何格式生成報告所需的方法或一組方法。使此接口成爲核心應用程序的一部分。格式具體的實現然後在獨立的模塊,這是依賴於你的核心應用程序和第三方庫。使用核心應用程序中的工廠使用refelction在運行時加載特定的實現。如果請求的格式是相關模塊罐不在類路徑中,則會拋出一個ClassNotFoundException,並捕獲它並進行相應的處理。

這裏爲您的應用

核心應用

class ReportData { 

} 

interface ReportGenerator { 
    byte[] generate(ReportData data); 
} 


class ReportGeneratorFactory { 
    public ReportGenerator getInstance(String format) 
      throws InstantiationException, IllegalAccessException, ClassNotFoundException { 
     ReportGenerator reportGenerator = null; 
     if("txt".equals(format)) { 
      reportGenerator = (ReportGenerator) 
        Class.forName("com.foo.TxtReportGenerator").newInstance(); 
     } else if("html".equals(format)) { 
      reportGenerator = (ReportGenerator) 
        Class.forName("com.foo.HtmlReportGenerator").newInstance(); 
     } else if("xl".equals(format)) { 
      reportGenerator = (ReportGenerator) 
        Class.forName("com.foo.XlReportGenerator").newInstance(); 
     } else { 
      throw new UnsupportedOperationException(
       String.format("Unsupport format %s", format)); 
     } 
     return reportGenerator; 
    } 
} 

TXT/HTML導出一個樣本結構(可能是核心應用程序的一部分,如果不需要第三方LIB)

class TxtReportGenerator implements ReportGenerator { 
    public byte[] generate(ReportData data) { 
     // TODO Auto-generated method stub 
     return null; 
    } 
} 

class HtmlReportGenerator implements ReportGenerator { 
    public byte[] generate(ReportData data) { 
     // TODO Auto-generated method stub 
     return null; 
    } 
} 

用於XL報告的模塊(自帶罐子)(取決於您的核心應用程序和第三方庫)

class XlReportGenerator implements ReportGenerator { 
    public byte[] generate(ReportData data) { 
     // TODO Auto-generated method stub 
     return null; 
    } 
} 

用法:

public static void main(String[] args) 
     throws InstantiationException, IllegalAccessException, ClassNotFoundException { 
    byte[] report = new ReportGeneratorFactory() 
     .getInstance("xl") 
     .generate(new ReportData()); 
} 
0

你有沒有嘗試用罐子作爲編譯依賴編譯它。

然後在運行時,你將有一個地方檢查jar是否需要,如果是的話你可以動態獲取jar並加載它(代碼不會像這樣工作):

import java.lang.reflect.Method; 
import java.net.URLClassLoader; 

Method addURL = null; 
try { 
    addURL = URLClassLoader.class.getDeclaredMethod("addURL", 
      new Class[]{URL.class}); 
} catch (Exception e1) { 
    //Log error 
} 
addURL.setAccessible(true); 
//Maybe download the file or check if file exist else give out error and end processing 
File yourJar = new File(filePath+"/"+fileName+".jar"); 
//Replace Your.Main.Class with your main class 
addURL.invoke(Your.Main.Class.class 
         .getClassLoader(), yourJar.toURI().toURL()); 
// Your class should now be loaded and no more ClassNotFound exception should occur when it is accessed, but not if it is accessed before! 
相關問題