2010-07-20 24 views
24

Tôi có một ứng dụng java đơn giản tải một tệp thuộc tính từ gói hiện tại.Tải tài nguyên từ bất kỳ đâu trong đường dẫn lớp

this.getClass().getResourceAsStream("props.properties"); 

Điều này làm việc tốt khi tệp thuộc tính tôi muốn nằm trong gói hiện tại. Tuy nhiên, tôi muốn đóng gói ứng dụng này như một JAR và định nghĩa và ghi đè bằng một tệp thuộc tính mới mà tôi sử dụng nó. Có cách nào để tải tài nguyên đầu tiên có tên "props.properties" có trên classpath không?

Tôi muốn nó được dễ dàng để ghi đè lên tập tin thuộc tính thông qua dòng lệnh:

java.exe -classpath props.properties;myJar.jar com.test.MyApp 

Tôi không muốn phải giải nén JAR và sửa đổi tập tin thuộc tính để thay đổi một cái gì đó. Tôi cảm thấy như tôi là thiếu một cái gì đó rõ ràng ...

Trả lời

4

Nếu thất bại, bạn có thể sử dụng hai tên tệp khác nhau, giả sử props-default.properties bên trong myJar.jarprops.properties để ghi đè trên dòng lệnh. Trong mã của bạn, bạn sẽ thử tải tệp props.properties trước và dự phòng thành props-default.properties nếu không tìm thấy.

0

Tôi không chắc chắn, nhưng có lẽ: ClassLoader.getResourceAsStream()

EDIT:

Tôi không nghĩ rằng đây là khác nhau đáng kể vào this.getClass () .getResourceAsStream() từ câu hỏi, vì như đã đề cập bạn vẫn phải lấy ClassLoader bạn muốn sử dụng để tải tài nguyên.

Vì bạn cung cấp tài nguyên trong đường dẫn-classpath trong ví dụ của bạn, nên có sẵn từ trình nạp lớp giống như lớp "chính" của bạn (trong SUN JVM, đó là sun.misc.Launcher $ AppClassLoader, không chắc chắn nếu điều này có thể/không thay đổi đối với các triển khai JVM khác).

+0

Âm thanh về quyền: Bạn muốn hỏi một ClassLoader là "ông chủ" của người đã tải lớp học của bạn, vì vậy nó có thể có quyền truy cập vào nhiều gói hơn. Một khả năng khác là thử 'ClassLoader.getSystemClassLoader()' - như tên của nó, đó là "ông chủ" của những người khác. –

+0

không có phương thức tĩnh 'getResourceAsStream()' trong lớp 'ClassLoader'. –

+0

và trình nạp lớp hệ thống sẽ có khả năng tải tài nguyên từ bên ngoài đường dẫn lớp của ứng dụng của bạn, tức là tìm trong thư mục bootstrap trong đường dẫn cài đặt JRE –

26

Các javadoc for Class.getResourceAsStream() tài liệu logic tra cứu:

Nếu tên bắt đầu bằng một '/' ('\u002f'), sau đó tên tuyệt đối của tài nguyên là một phần của tên theo sau '/'.

Nếu không, tên tuyệt đối có dạng sau:
modified_package_name/name

Trường hợp modified_package_name là tên gói của đối tượng này với '/' thay cho '.' ('\u002e').

Vì vậy, nói cách khác, tên tài nguyên truyền cho phương pháp này sẽ giống như /com/package/p2/props.properties nếu props.properties được lưu trữ trong gói com.package.p2 thay vì lớp của hiện tại.

13

Tôi chắc chắn đã quá muộn để trả lời nhưng có thể thú vị với những người giúp việc trình trợ giúp đoạn mã nhỏ này để tải tệp thuộc tính từ bất kỳ vị trí nào trong Classpath.

ClassLoader cl = ClassLoader.getSystemClassLoader(); 
    if (cl != null) { 
     URL url = cl.getResource(CONF_PROPERTIES); 
     if (url == null) { 
      url = cl.getResource("/" + CONF_PROPERTIES); 
     } 
     if (url != null) { 
      try { 
       InputStream in = url.openStream(); 
       props = new Properties(); 
       props.load(in); 
      } catch (IOException e) { 
       // Log the exception 
      } finally { 
       // close opened resources 
      } 

     } 
    } 
+2

Có lý do cụ thể nào mà bạn không sử dụng getResourceAsStream không? –

+0

Tôi sử dụng loại khởi tạo này khi tôi đang phát triển một ứng dụng EE. Trong quá trình phát triển, ứng dụng của tôi nhận thức được rằng tệp đó ném Eclipse Classpath. Nhưng khi tạo ra EAR, ứng dụng nhận thức được tệp đó ném cấu hình ClassPath ném WebSphere. Tôi cũng sẽ đánh giá cao một giải pháp thanh lịch khác. –

+0

Tôi hiểu. Tôi sẽ không có dự kiến ​​này để ném ngoại lệ khác nhau (hoặc ít nhất sẽ mong đợi rằng cả hai đều có một phụ huynh phổ biến, như IOException). Cách tiếp cận thú vị mặc dù. –

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