ตำแหน่งและวิธีการอ่านไฟล์ทรัพยากรการกำหนดค่าในแอพพลิเคชั่นที่ใช้ servlet


222

ในเว็บแอปพลิเคชันของฉันฉันต้องส่งอีเมลไปยังชุดของผู้ใช้ที่กำหนดไว้ล่วงหน้าเช่นfinance@xyz.comดังนั้นฉันต้องการที่จะเพิ่มลงใน.propertiesไฟล์และเข้าถึงเมื่อจำเป็น นี่เป็นขั้นตอนที่ถูกต้องหรือไม่ถ้าใช่ฉันควรวางไฟล์นี้ไว้ที่ไหน ฉันใช้ Netbeans IDE ซึ่งมีสองโฟลเดอร์แยกต่างหากสำหรับไฟล์ซอร์สและไฟล์ JSP


JNDIอาจจะเป็นทางออกหรือไม่?
Basil Bourque

คำตอบ:


464

มันเป็นทางเลือกของคุณ โดยทั่วไปมีสามวิธีในการเก็บถาวรแอปพลิเคชันเว็บ Java (WAR):


1. ใส่ไว้ใน classpath

เพื่อให้คุณสามารถโหลดโดยClassLoader#getResourceAsStream()ใช้พา ธ พา ธ ที่สัมพันธ์กับคลาสพา ธ :

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

นี่foo.propertiesควรจะถูกวางไว้ในหนึ่งของรากที่ได้รับความคุ้มครองโดย classpath เริ่มต้นของ webapp e กรัม webapp ของ/WEB-INF/libและ/WEB-INF/classesเซิร์ฟเวอร์ของ/libหรือ /libJDK หาก propertiesfile เป็น webapp /WEB-INF/classesเฉพาะที่ดีที่สุดคือการวางไว้ใน หากคุณกำลังพัฒนาโครงการสงครามมาตรฐานใน IDE ให้วางลงในsrcโฟลเดอร์ (โฟลเดอร์ซอร์สของโครงการ) หากคุณกำลังใช้โครงการ Maven ให้วางไว้ใน/main/resourcesโฟลเดอร์

คุณสามารถวางไว้ที่อื่นนอก classpath เริ่มต้นและเพิ่มเส้นทางไปยัง classpath ของ appserver ในตัวอย่าง Tomcat คุณสามารถกำหนดค่าเป็นทรัพย์สินของshared.loaderTomcat/conf/catalina.properties

หากคุณวางไว้foo.propertiesในโครงสร้างแพ็คเกจ Java เช่นcom.exampleนั้นคุณต้องโหลดดังต่อไปนี้

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

/โปรดทราบว่าเส้นทางของรถตักดินชั้นบริบทนี้ไม่ควรเริ่มต้นด้วย เฉพาะเมื่อคุณกำลังใช้ "ญาติ" กระบอกชั้นเช่นนั้นคุณแน่นอนจะต้องเริ่มต้นด้วยSomeClass.class.getClassLoader()/

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

อย่างไรก็ตามการมองเห็นของไฟล์คุณสมบัติจะขึ้นอยู่กับ class loader ที่เป็นปัญหา มันจะมองเห็นได้ในตัวโหลดคลาสเดียวกันกับตัวโหลดคลาส ดังนั้นหากโหลดคลาสโดยเซิร์ฟเวอร์เช่น classloader ทั่วไปแทน webapp classloader และไฟล์คุณสมบัติอยู่ใน webapp นั้นจะไม่สามารถมองเห็นได้ บริบทคลาสโหลดเดอร์เป็นเดิมพันที่ปลอดภัยที่สุดของคุณเพื่อให้คุณสามารถวางไฟล์คุณสมบัติ "ทุกที่" ใน classpath และ / หรือคุณตั้งใจจะสามารถแทนที่เซิร์ฟเวอร์ที่จัดหาให้จาก webapp บน


2. วางไว้ในเว็บคอนเทนต์

เพื่อให้คุณสามารถโหลดได้โดยServletContext#getResourceAsStream()ใช้พา ธ ของเนื้อหาบนเว็บ:

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

โปรดทราบว่าฉันได้สาธิตการวางไฟล์ไว้ใน/WEB-INFโฟลเดอร์ไม่เช่นนั้นเว็บเบราว์เซอร์ใด ๆ จะสามารถเข้าถึงได้แบบสาธารณะ นอกจากนี้ยังทราบว่าServletContextเป็นในHttpServletระดับที่สามารถเข้าถึงได้โดยการสืบทอดGenericServlet#getServletContext()และโดยFilter FilterConfig#getServletContext()ในกรณีที่คุณไม่ได้อยู่ในคลาส servlet มักจะสามารถทำการฉีด@Injectได้


3. วางไว้ในระบบไฟล์ดิสก์ในเครื่อง

เพื่อให้คุณสามารถโหลดได้ตามปกติjava.ioด้วยพา ธ ของระบบไฟล์ดิสก์ภายในระบบ:

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

จดบันทึกความสำคัญของการใช้พา ธ สัมบูรณ์ พา ธ ของระบบไฟล์ดิสก์โลคัลที่สัมพันธ์กันเป็นสิ่งที่ไม่ต้องทำอย่างแน่นอนในเว็บแอ็พพลิเคชัน Java EE ดูลิงค์แรก "เห็นด้วย" ด้านล่าง


เลือกแบบไหน?

เพียงชั่งน้ำหนักข้อดี / ข้อเสียในความเห็นของคุณในการบำรุงรักษา

หากไฟล์คุณสมบัติเป็น "คงที่" และไม่จำเป็นต้องเปลี่ยนแปลงระหว่างรันไทม์คุณสามารถเก็บไว้ในสงครามได้

หากคุณต้องการความสามารถในการแก้ไขไฟล์คุณสมบัติจากภายนอกเว็บแอ็พพลิเคชันโดยไม่จำเป็นต้องสร้างและปรับใช้ WAR อีกครั้งทุกครั้งให้วางไว้ใน classpath ภายนอกโครงการ (หากจำเป็นต้องเพิ่มไดเร็กทอรีไปยัง classpath)

หากคุณต้องการความสามารถในการแก้ไขไฟล์คุณสมบัติโดยทางโปรแกรมจากภายในเว็บแอ็พพลิเคชันโดยใช้Properties#store()เมธอดวางไว้ด้านนอกเว็บแอ็พพลิเคชัน ตามที่Properties#store()ต้องการWriterคุณจึงไม่สามารถไปไหนได้โดยใช้พา ธ ของระบบไฟล์ดิสก์ สามารถส่งผ่านพา ธ นั้นไปยังเว็บแอ็พพลิเคชันเป็นอาร์กิวเมนต์ VM หรือคุณสมบัติระบบ เพื่อเป็นการป้องกัน, ไม่เคยgetRealPath()ใช้ การเปลี่ยนแปลงทั้งหมดในโฟลเดอร์การนำไปใช้งานจะสูญหายไปใน redeploy ด้วยเหตุผลง่ายๆว่าการเปลี่ยนแปลงจะไม่สะท้อนกลับมาในไฟล์ WAR ดั้งเดิม

ดูสิ่งนี้ด้วย:


2
"โดยส่วนตัวแล้วฉันชอบวางไว้ใน classpath นอกโครงการ (เพิ่มเส้นทางใหม่ไปยัง classpath)" สับสนคุณสามารถยกตัวอย่างได้หรือไม่?
Blankman

4
@Blankman เขาอาจหมายถึงการสร้างโฟลเดอร์ใหม่วางไฟล์การกำหนดค่าแบบกำหนดเองทั้งหมดของคุณไว้ที่นั่นและเพิ่มโฟลเดอร์นั้นลงใน classpath ดังนั้น: 1) สร้างโฟลเดอร์ที่เรียกว่า 'appconfs' ที่ไหนสักแห่ง (อาจเป็น/etc/appconfs2) เพิ่มโฟลเดอร์นั้นไปที่ classpath ของแอปเซิร์ฟเวอร์ / โดเมน ขั้นตอนที่สองเป็นแอพเซิร์ฟเวอร์เฉพาะฉันไม่คิดว่ามีตัวอย่างทั่วไปสำหรับสิ่งนั้น
Tuukka Mustonen

Re: 2: ทำไมทั้งสอง"WEB-INF/filename.properties"และ"/WEB-INF/filename.properties"(สังเกต/ที่จุดเริ่มต้น) ทำงานอย่างไร มีเหตุผลใดที่จะชอบอีกอันหรือไม่?
Mr_and_Mrs_D

ฉันได้รับการแก้ไขในเรื่องนี้ในช่วงหนึ่งวันที่ผ่านมา ฉันไม่สามารถโหลดไฟล์คุณสมบัติได้ ฉันสามารถโหลดได้จากสองแห่ง หนึ่งคือไดเรกทอรีของระบบและหนึ่งคือไดรฟ์ในเครื่อง มันทำงานร่วมกับ localhost แต่ฉันต้องการปรับใช้กับ amazon
อรุณราชา

ฉันใช้ netbeans IDE และเก็บไฟล์คุณสมบัติไว้ในเว็บเพจ / แหล่งข้อมูล ฉันพยายามเข้าถึงมันเป็น "./Web Pages / resources / config.properties" ฉันไม่สามารถเข้าถึงได้ โปรดช่วยฉันด้วย
อรุณราชา

9

คำเตือน: ถ้าคุณวางไฟล์ config ไว้ในWEB-INF/classesโฟลเดอร์ของคุณและ IDE ของคุณพูด Eclipse ทำการล้าง / สร้างใหม่มันจะทำหน้าที่ดักไฟล์ conf ของคุณจนกว่าจะอยู่ในไดเรกทอรีแหล่ง Java คำตอบที่ยอดเยี่ยมของ BalusC เป็นการกล่าวถึงตัวเลือกที่ 1 แต่ฉันต้องการเพิ่มความสำคัญ

ฉันได้เรียนรู้วิธีที่ยากว่าถ้าคุณ "คัดลอก" โครงการเว็บใน Eclipse มันจะทำความสะอาด / สร้างใหม่จากโฟลเดอร์ต้นทางใด ๆ ในกรณีของฉันฉันได้เพิ่ม "linked source dir" จาก POJO java library ของเรามันจะรวบรวมไปยังWEB-INF/classesโฟลเดอร์ การทำความสะอาด / สร้างใหม่ในโครงการนั้น (ไม่ใช่โครงการแอปพลิเคชันเว็บ) ทำให้เกิดปัญหาเดียวกัน

ฉันคิดเกี่ยวกับการวาง confs ของฉันในโฟลเดอร์ POJO src แต่ confs เหล่านี้มีไว้สำหรับ libs บุคคลที่สาม (เช่น Quartz หรือ URLRewrite) ที่อยู่ในWEB-INF/libโฟลเดอร์ดังนั้นจึงไม่สมเหตุสมผล ฉันวางแผนที่จะทดสอบวางไว้ในโฟลเดอร์ "src" ของโครงการเว็บเมื่อฉันไปถึงที่นั่น แต่โฟลเดอร์นั้นว่างเปล่าในขณะนี้และมีไฟล์ conf อยู่ในนั้นดูเหมือนไม่เหมาะสม

ดังนั้นผมจึงลงคะแนนเสียงสำหรับการวาง conf ไฟล์ในWEB-INF/commonConfFolder/filename.properties, ต่อไปจากการเรียนโฟลเดอร์ซึ่งเป็น Balus ทางเลือกที่ 2


1
ถ้าคุณวางไฟล์ปรับแต่งของคุณลงในโฟลเดอร์ย่อยของ WEB_INF คุณจะไปถึงมันได้อย่างไร? ฉันไม่ได้โชคด้วยพูด 'configFiles / prop.properties'
JesseBoyd

ตกลงสิ่งนี้จะทำงานวางไฟล์คุณสมบัติภายใต้ 'Java Resources / src /' มันไม่ทำงานจากภายในหนึ่งในแพ็คเกจของฉันและต้องอยู่ที่ root ของ src คำเตือนของคุณเกี่ยวกับโฟลเดอร์คลาสที่รับ nuked เป็นข้อกังวลที่ถูกต้อง
JesseBoyd

6

เช่นในไฟล์ web.xml ให้แท็ก

<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>

และ chat.properties คุณสามารถประกาศคุณสมบัติของคุณเช่นนี้

สำหรับอดีต:

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

มันเพียงแค่ต้องอยู่ใน classpath (หรือที่เรียกว่าตรวจสอบให้แน่ใจว่ามันอยู่ภายใต้ / WEB-INF / คลาสใน. war ซึ่งเป็นส่วนหนึ่งของบิลด์)


สวัสดีขอบคุณสำหรับความคิด แต่มันบอกฉันว่าไม่สามารถหาไฟล์ที่ระบุใช่มันเป็นปัญหาของเส้นทางวิธีการให้เส้นทาง
sansknwoledge

3

คุณสามารถมีโฟลเดอร์ซอร์สของคุณดังนั้นเมื่อใดก็ตามที่คุณสร้างไฟล์เหล่านั้นจะถูกคัดลอกไปยังไดเรกทอรีคลาสโดยอัตโนมัติ

แทนที่จะใช้ไฟล์คุณสมบัติใช้ไฟล์ XML

หากข้อมูลมีขนาดเล็กเกินไปคุณสามารถใช้ web.xml เพื่อเข้าถึงคุณสมบัติได้

โปรดทราบว่าวิธีการใด ๆ เหล่านี้จะต้องเริ่มต้นเซิร์ฟเวอร์แอปใหม่เพื่อให้การเปลี่ยนแปลงมีผล


ฉันวางไว้ในหน้าเว็บโฟลเดอร์ แต่ไม่สามารถเข้าถึงไฟล์ไม่พบข้อผิดพลาดที่กำลังจะมาถึงวิธีการเส้นทางการตั้งค่า
sansknwoledge

1
หากไฟล์ของคุณสิ้นสุดลงในโฟลเดอร์ WEB-INF / คลาสมันจะถูกตั้งค่าเป็น classpath โดยอัตโนมัติ
Kalpak

2

สมมติว่ารหัสของคุณกำลังมองหาไฟล์ที่ว่า app.properties คัดลอกไฟล์นี้ไปยัง dir ใด ๆ และเพิ่ม dir นี้ไปที่ classpath โดยสร้าง setenv.sh ใน bin dir ของ tomcat

ใน setenv.sh ของ tomcat ของคุณ (หากไฟล์นี้ไม่มีอยู่ให้สร้างขึ้นใหม่แล้ว tomcat จะโหลดไฟล์ setenv.sh นี้ #!/bin/sh CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"

คุณไม่ควรมีไฟล์คุณสมบัติใน. /webapps//WEB-INF/classes/app.properties

โหลดคลาสของ Tomcat จะแทนที่ด้วยด้วยจาก WEB-INF / classes /

อ่านดี: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.