Nơi để đặt và làm thế nào để đọc các tệp tài nguyên cấu hình trong ứng dụng dựa trên servlet?


222

Trong ứng dụng web của tôi, tôi phải gửi email đến tập hợp những người dùng được xác định trước như thế finance@xyz.com, vì vậy tôi muốn thêm nó vào một .propertiestệp và truy cập nó khi được yêu cầu. Đây có phải là một quy trình đúng không, nếu vậy thì tôi nên đặt tập tin này ở đâu? Tôi đang sử dụng Netbeans IDE đang có hai thư mục riêng cho các tệp nguồn và tệp JSP.


JNDI có lẽ là một giải pháp?
Basil Bourque

Câu trả lời:


464

Đó là sự lựa chọn của bạn. Về cơ bản có ba cách trong kho lưu trữ ứng dụng web Java (WAR):


1. Đặt nó trong classpath

Vì vậy, bạn có thể tải nó bằng ClassLoader#getResourceAsStream()một đường dẫn tương đối classpath:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);

Ở đây foo.propertiesđược cho là được đặt trong một trong những gốc được bao phủ bởi đường dẫn lớp mặc định của ứng dụng web, ví dụ như ứng dụng web /WEB-INF/lib/WEB-INF/classes, máy chủ /libhoặc JDK / JRE /lib. Nếu thuộc tính là dành riêng cho webapp, tốt nhất là đặt nó vào /WEB-INF/classes. Nếu bạn đang phát triển một dự án WAR tiêu chuẩn trong IDE, hãy thả nó vào srcthư mục (thư mục nguồn của dự án). Nếu bạn đang sử dụng dự án Maven, hãy thả nó vào /main/resourcesthư mục.

Bạn cũng có thể đặt nó ở đâu đó bên ngoài đường dẫn mặc định và thêm đường dẫn của nó vào đường dẫn lớp của máy chủ ứng dụng. Trong ví dụ Tomcat, bạn có thể cấu hình nó làm shared.loadertài sản của Tomcat/conf/catalina.properties.

Nếu bạn đã đặt foo.propertiesnó trong một cấu trúc gói Java như thế nào com.example, thì bạn cần tải nó như dưới đây

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/foo.properties");
// ...

Lưu ý rằng đường dẫn này của trình nạp lớp ngữ cảnh không nên bắt đầu bằng a /. Chỉ khi bạn đang sử dụng trình nạp lớp "tương đối" SomeClass.class.getClassLoader(), thì bạn thực sự cần phải khởi động nó bằng a /.

ClassLoader classLoader = getClass().getClassLoader();
InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties");
// ...

Tuy nhiên, khả năng hiển thị của tệp thuộc tính sau đó phụ thuộc vào trình nạp lớp được đề cập. Nó chỉ hiển thị với trình nạp lớp giống như trình tải lớp. Vì vậy, nếu lớp được tải bởi vd, trình tải lớp chung của máy chủ thay vì trình tải lớp webapp và tệp thuộc tính nằm trong chính ứng dụng web, thì nó sẽ ẩn. Trình tải lớp ngữ cảnh là đặt cược an toàn nhất của bạn để bạn có thể đặt tệp thuộc tính "ở mọi nơi" trong đường dẫn lớp và / hoặc bạn dự định có thể ghi đè lên một máy chủ do webapp cung cấp.


2. Đặt nó trong liên kết web

Vì vậy, bạn có thể tải nó bằng ServletContext#getResourceAsStream()một đường dẫn liên quan đến liên kết web:

InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
// ...

Lưu ý rằng tôi đã chứng minh đặt tệp vào /WEB-INFthư mục, nếu không nó sẽ được truy cập công khai bởi bất kỳ webbrowser nào. Cũng lưu ý rằng ServletContextlà trong bất kỳ HttpServletlớp chỉ truy xuất bởi di truyền GenericServlet#getServletContext()và trong Filterbằng FilterConfig#getServletContext(). Trong trường hợp bạn không thuộc lớp servlet, nó thường chỉ được tiêm qua @Inject.


3. Đặt nó trong hệ thống tập tin đĩa cục bộ

Để bạn có thể tải nó java.iotheo cách thông thường với đường dẫn hệ thống tệp đĩa cục bộ tuyệt đối:

InputStream input = new FileInputStream("/absolute/path/to/foo.properties");
// ...

Lưu ý tầm quan trọng của việc sử dụng một đường dẫn tuyệt đối. Đường dẫn hệ thống tệp đĩa cục bộ tương đối là không có trong ứng dụng web Java EE. Xem thêm liên kết "Xem thêm" đầu tiên bên dưới.


Chọn loại nào?

Chỉ cần cân nhắc những lợi thế / bất lợi theo quan điểm của riêng bạn về khả năng bảo trì.

Nếu các tệp thuộc tính là "tĩnh" và không bao giờ cần thay đổi trong thời gian chạy, thì bạn có thể giữ chúng trong WAR.

Nếu bạn muốn có thể chỉnh sửa các tệp thuộc tính từ bên ngoài ứng dụng web mà không cần phải xây dựng lại và triển khai lại WAR mỗi lần, sau đó đặt nó vào đường dẫn bên ngoài dự án (nếu cần thêm thư mục vào đường dẫn lớp).

Nếu bạn muốn có thể chỉnh sửa các tệp thuộc tính theo chương trình từ bên trong ứng dụng web bằng Properties#store()phương pháp, hãy đặt nó bên ngoài ứng dụng web. Vì Properties#store()yêu cầu a Writer, bạn không thể sử dụng đường dẫn hệ thống tệp đĩa. Đường dẫn đó có thể lần lượt được chuyển đến ứng dụng web dưới dạng đối số VM hoặc thuộc tính hệ thống. Để phòng ngừa, không bao giờ sử dụnggetRealPath() . Tất cả các thay đổi trong thư mục triển khai sẽ bị mất khi triển khai lại vì lý do đơn giản là các thay đổi không được phản ánh lại trong tệp WAR gốc.

Xem thêm:


2
"Cá nhân tôi thích đặt nó trong đường dẫn lớp bên ngoài dự án (thêm đường dẫn mới vào đường dẫn lớp)", bạn có thể đưa ra một ví dụ không?
Blankman

4
@Blankman Có lẽ anh ta có nghĩa là tạo một thư mục mới, đặt tất cả các tệp cấu hình tùy chỉnh của bạn ở đó và thêm thư mục đó vào đường dẫn lớp. Vì vậy: 1) Tạo thư mục có tên 'appconfs' ở đâu đó (có thể là /etc/appconfs2) Thêm thư mục đó vào đường dẫn của máy chủ / miền ứng dụng. Bước thứ hai là máy chủ ứng dụng cụ thể, tôi không nghĩ có ví dụ chung cho việc đó.
Tuukka Mustonen

Re: 2: Tại sao cả hai "WEB-INF/filename.properties""/WEB-INF/filename.properties"(chú ý /ở đầu) sẽ làm việc? Có bất kỳ lý do để thích cái này hơn cái kia không?
Mr_and_Mrs_D

Tôi đã được sửa chữa trong vấn đề này trong một ngày qua. Tôi không thể tải tập tin thuộc tính của tôi. Tôi có thể tải nó từ hai nơi. Một là thư mục hệ thống và một là ổ đĩa cục bộ. Nó hoạt động với localhost. Nhưng tôi muốn triển khai nó trên amazon.
Arun Raja

Tôi đang sử dụng IDE netbeans và giữ tệp thuộc tính trong Trang web / tài nguyên. Tôi cố gắng truy cập nó dưới dạng "./Web Pages / resource / config.properIES". Tôi không thể truy cập nó. Làm ơn giúp tôi.
Arun Raja

9

Lời cảnh báo: nếu bạn đặt các tệp cấu hình trong WEB-INF/classesthư mục của mình và IDE của bạn, giả sử Eclipse, thực hiện dọn dẹp / xây dựng lại, nó sẽ nuke các tệp conf của bạn trừ khi chúng nằm trong thư mục nguồn Java. Câu trả lời tuyệt vời của BalusC ám chỉ điều đó trong lựa chọn 1 nhưng tôi muốn thêm điểm nhấn.

Tôi đã học được một cách khó khăn là nếu bạn "sao chép" một dự án web trong Eclipse, thì nó sẽ làm sạch / xây dựng lại từ bất kỳ thư mục nguồn nào. Trong trường hợp của tôi, tôi đã thêm một "thư mục nguồn được liên kết" từ thư viện java POJO của chúng tôi, nó sẽ biên dịch vào WEB-INF/classesthư mục. Làm sạch / xây dựng lại trong dự án đó (không phải dự án ứng dụng web) gây ra vấn đề tương tự.

Tôi đã nghĩ về việc đưa confs của mình vào thư mục src POJO, nhưng những conf này đều dành cho lib của bên thứ 3 (như Quartz hoặc URLRewrite) trong WEB-INF/libthư mục, vì vậy điều đó không có ý nghĩa. Tôi dự định kiểm tra việc đưa nó vào thư mục "src" của các dự án web khi tôi đi xung quanh nó, nhưng thư mục đó hiện đang trống và có các tệp conf trong đó có vẻ không phù hợp.

Vì vậy, tôi bỏ phiếu cho việc đặt các tập tin conf WEB-INF/commonConfFolder/filename.properties, bên cạnh thư mục lớp, đó là tùy chọn Balus 2.


1
nếu bạn đặt tập tin cấu hình của bạn vào một thư mục con của WEB_INF thì làm thế nào để bạn tiếp cận nó? Tôi đã không gặp may mắn khi nói 'configFiles / prop.properIES'
JesseBoyd

ok điều này không hoạt động khi đặt tệp thuộc tính trong 'Tài nguyên Java / src /' nó không hoạt động từ bên trong một trong các gói của tôi và cần phải ở gốc của src. cảnh báo của bạn về thư mục lớp bị nuked là một mối quan tâm hợp lệ.
JesseBoyd

6

Ví dụ: Trong tệp web.xml, thẻ

<context-param>
        <param-name>chatpropertyfile</param-name>
        <!--  Name of the chat properties file. It contains the name and description                   of rooms.-->     
        <param-value>chat.properties</param-value>
    </context-param>

Và chat.properies bạn có thể khai báo các thuộc tính của bạn như thế này

Ví dụ:

Jsp = Discussion about JSP can be made here.
Java = Talk about java and related technologies like J2EE.
ASP = Discuss about Active Server Pages related technologies like VBScript and JScript etc.
Web_Designing = Any discussion related to HTML, JavaScript, DHTML etc.
StartUp = Startup chat room. Chatter is added to this after he logs in.

5

Nó chỉ cần nằm trong đường dẫn lớp (còn gọi là đảm bảo rằng nó kết thúc dưới / WEB-INF / các lớp trong .war như là một phần của bản dựng).


xin cảm ơn về ý tưởng này, nhưng nó nói với tôi rằng không thể tìm thấy tệp được chỉ định, vâng, đó là vấn đề đường dẫn làm thế nào để đưa ra đường dẫn
sansknwoledge

3

Bạn có thể với thư mục nguồn của mình để bất cứ khi nào bạn xây dựng, các tệp đó sẽ tự động được sao chép vào thư mục lớp.

Thay vì sử dụng tệp thuộc tính, hãy sử dụng tệp XML.

Nếu dữ liệu quá nhỏ, bạn thậm chí có thể sử dụng web.xml để truy cập các thuộc tính.

Xin lưu ý rằng bất kỳ phương pháp nào trong số này sẽ yêu cầu khởi động lại máy chủ ứng dụng để các thay đổi được phản ánh.


Tôi đã đặt trong thư mục trang web nhưng không thể truy cập vào tệp mà không tìm thấy lỗi đang đến cách đặt đường dẫn
sansknwoledge

1
nếu tệp của bạn kết thúc trong thư mục WEB-INF / lớp, nó sẽ tự động được đặt vào đường dẫn lớp
Kalpak

2

Giả sử mã của bạn đang tìm tệp nói app.properations. Sao chép tệp này vào bất kỳ thư mục nào và thêm thư mục này vào classpath, bằng cách tạo setenv.sh trong thư mục bin của tomcat.

Trong setenv.sh của tomcat của bạn (nếu tệp này không tồn tại, hãy tạo một tệp, tomcat sẽ tải tệp setenv.sh này. #!/bin/sh CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"

Bạn không nên có các tệp thuộc tính của mình trong ./webapps//CHB-INF/groupes/app.properies

Trình tải lớp Tomcat sẽ ghi đè lên với trình tải xuống từ WEB-INF / class /

Đọc tốt: https://tomcat.apache.org/tomcat-8.0-doc/ class-loader-howto.html

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.