1. พื้นหลัง
เมื่อเร็ว ๆ นี้เนื่องจากปัญหาเกี่ยวกับการสแกนแพ็คเกจของโครงการในขั้นตอนการแก้ปัญหาฉันได้ค้นพบโดยบังเอิญว่า Spring และ SpringMVC มีความสัมพันธ์ระหว่างพ่อแม่ลูกและเป็นเพราะปัญหานี้เกิดขึ้นกับปัญหาการสแกนแพ็คเกจมักเกิดขึ้น ที่นี่เราวิเคราะห์และทำความเข้าใจกับความสัมพันธ์ของคอนเทนเนอร์พ่อแม่ลูกระหว่าง Spring และ SpringMVC และให้วิธีการสแกนแพ็คเกจที่แนะนำอย่างเป็นทางการในไฟล์การกำหนดค่า SpringMVC และ SpringMVC
2. แนวคิดความเข้าใจและความรู้การวางรากฐาน
ในแนวคิดหลักของกรอบโดยรวมของฤดูใบไม้ผลิภาชนะบรรจุเป็นแนวคิดหลักซึ่งใช้ในการจัดการวงจรชีวิตทั้งหมดของถั่ว ในโครงการไม่จำเป็นต้องมีเพียงคอนเทนเนอร์เดียว สปริงสามารถรวมคอนเทนเนอร์หลายตัวและภาชนะมีระดับบนและล่าง สถานการณ์ที่พบบ่อยที่สุดในปัจจุบันคือการแนะนำสองกรอบของฤดูใบไม้ผลิและ SpringMVC ในโครงการ จริง ๆ แล้วมันเป็นสองภาชนะ ฤดูใบไม้ผลิเป็นภาชนะแม่และ SpringMVC เป็นภาชนะบรรจุเด็ก ถั่วที่ลงทะเบียนในคอนเทนเนอร์ของผู้ปกครองในฤดูใบไม้ผลิสามารถมองเห็นได้ที่ภาชนะ SpringMVC ในขณะที่ถั่วที่ลงทะเบียนในภาชนะ SpringMVC นั้นมองไม่เห็นในภาชนะบรรจุสปริงนั่นคือภาชนะเด็กสามารถเห็นถั่วที่ลงทะเบียนในภาชนะแม่ไม่เช่นนั้นจะไม่ทำงาน
เราสามารถใช้การกำหนดค่าคำอธิบายประกอบแบบครบวงจรดังนี้เพื่อลงทะเบียนแบทช์ลงทะเบียนถั่วโดยไม่ต้องกำหนดค่าถั่วแต่ละตัวโดยใช้ XML แยกกัน
<บริบท: Component-Scan base-package = "com.hafiz.www" />>>
จากคู่มืออ้างอิงที่ให้ไว้ในฤดูใบไม้ผลิเรารู้ว่าฟังก์ชั่นของการกำหนดค่านี้คือการสแกนคลาสทั้งหมดภายใต้แพ็คเกจแพคเกจฐานที่กำหนดค่าซึ่งใช้คำอธิบายประกอบ @component และลงทะเบียนโดยอัตโนมัติในคอนเทนเนอร์ ในเวลาเดียวกันพวกเขายังสแกนคำอธิบายประกอบทั้งสามของ @Controller, @Service และ @Respository เพราะพวกเขาได้รับมรดกจาก @Component
ในโครงการเรามักจะเห็นการกำหนดค่าต่อไปนี้ ในความเป็นจริงด้วยการกำหนดค่าข้างต้นสิ่งนี้สามารถละเว้นได้เนื่องจากการกำหนดค่าข้างต้นจะเปิดการกำหนดค่าต่อไปนี้ตามค่าเริ่มต้น การกำหนดค่าต่อไปนี้จะประกาศคำอธิบายประกอบเช่น @Required, @AutoWired, @PostConstruct, @PersistenceContext, @Resource, @Predestroy ฯลฯ โดยค่าเริ่มต้น
<บริบท: Annotation-config/>
นอกจากนี้ยังมีการกำหนดค่าอื่นที่เกี่ยวข้องกับ SpringMVC หลังจากการตรวจสอบแล้วสิ่งนี้จะต้องได้รับการกำหนดค่าสำหรับ SpringMVC เพราะมันประกาศ @requestmapping, @requestbody, @ResponseBody ฯลฯ นอกจากนี้การกำหนดค่านี้จะโหลดวิธีการผูกพารามิเตอร์จำนวนมากโดยค่าเริ่มต้นเช่น JSON Conversion Parser
<MVC: คำอธิบายประกอบที่ขับเคลื่อนด้วย />
เวอร์ชันการกำหนดค่าประโยคด้านบนก่อนฤดูใบไม้ผลิ 3.1 เทียบเท่ากับวิธีการกำหนดค่าต่อไปนี้
<!-กำหนดค่า Mapper Controller Annotation มันถูกใช้ใน SpringMVC เพื่อแมป URL คำขอคำขอไปยังคอนโทรลเลอร์เฉพาะ-> <bean/> <!-กำหนดค่า Mapper Controller Annotation มันถูกใช้ใน SpringMVC เพื่อแมปคำขอเฉพาะกับวิธีการเฉพาะ-> <ถั่ว/>>
เวอร์ชันหลังจาก Spring3.1 เทียบเท่ากับวิธีการกำหนดค่าต่อไปนี้
<!-กำหนดค่า Mapper Controller Annotation มันถูกใช้ใน SpringMVC เพื่อแมป URL คำขอคำขอไปยังคอนโทรลเลอร์เฉพาะ-> <bean/> <!-กำหนดค่า Mapper Controller Annotation มันถูกใช้ใน SpringMVC เพื่อแมปคำขอเฉพาะกับวิธีการเฉพาะ-> <ถั่ว/>>
3. การวิเคราะห์สถานการณ์เฉพาะ
ลองมาดูสาเหตุของความขัดแย้งระหว่างสปริงและ SpringMVC อย่างใกล้ชิด?
เรามีคอนเทนเนอร์สองตัวคือ Spring และ SpringMVC และไฟล์การกำหนดค่าของพวกเขาคือ ApplicationContext.xml และ ApplicationContext-MVC.XML ตามลำดับ
1. <บริบท: Component-Scan base-package = "com.hafiz.www" /> ได้รับการกำหนดค่าใน ApplicationContext.xml เพื่อรับผิดชอบในการสแกนและลงทะเบียนถั่วทั้งหมดที่ต้องลงทะเบียน
2. กำหนดค่า <MVC: คำอธิบายประกอบที่ขับเคลื่อนด้วย /> ใน ApplicationContext-MVC.XML เพื่อรับผิดชอบการใช้คำอธิบายประกอบที่เกี่ยวข้องกับ SpringMVC
3. เมื่อเริ่มโครงการเราพบว่า SpringMVC ไม่สามารถกระโดดได้ เราตั้งค่าระดับการพิมพ์บันทึกของบันทึกเพื่อแก้ไขข้อบกพร่องสำหรับการดีบัก เราพบว่าคำขอในคอนเทนเนอร์ SpringMVC ดูเหมือนจะไม่ถูกแมปกับคอนโทรลเลอร์เฉพาะ
4. กำหนดค่า <บริบท: Component-Scan base-package = "com.hafiz.www" /> ใน ApplicationContext-mvc.xml หลังจากรีสตาร์ทการตรวจสอบจะประสบความสำเร็จและ SpringMVC Jump นั้นใช้ได้
ลองตรวจสอบเหตุผลเฉพาะดูที่ซอร์สโค้ดและเริ่มจาก DispatchERServlet ของ SpringMVC เพื่อค้นหา เราพบว่าเมื่อ SpringMVC เริ่มต้นเราจะมองหาถั่วทั้งหมดในคอนเทนเนอร์ SpringMVC ที่ใช้คำอธิบายประกอบ @Controller เพื่อตรวจสอบว่าเป็นตัวจัดการหรือไม่ การกำหนดค่าสองขั้นตอนของ 1 และ 2 ทำให้คอนเทนเนอร์ SpringMVC ปัจจุบันไม่ได้ลงทะเบียนถั่วด้วยคำอธิบายประกอบ @Controller แต่ถั่วทั้งหมดที่มีคำอธิบายประกอบ @Controller ลงทะเบียนในคอนเทนเนอร์หลักของฤดูใบไม้ผลิดังนั้น SpringMVC จึงไม่สามารถหาโปรเซสเซอร์และกระโดดไม่ได้ ซอร์สโค้ดหลักมีดังนี้:
เป็นโมฆะที่ได้รับการป้องกัน inithandlermethods () {ถ้า (logger.isdebugenabled ()) {logger.debug ("ค้นหาการแมปคำขอในบริบทแอปพลิเคชัน:" + getApplicationContext ()); } string [] beannames = (this.detecthandlermethodsinancestorContexts? beanfactoryutils.beannamesfortypeincludedancestors (getApplicationContext (), object.class): getApplicationContext () getBeannamesfortype (Object.Class); สำหรับ (สตริง BeanName: BeanNames) {ถ้า (ishandler (getApplicationContext (). getType (BeanName))) {detecthandLermethods (BeanName); }} handlermethodsinitialized (gethandlermethods ());}ในวิธีการ Ishandler เราจะพิจารณาว่าคำอธิบายประกอบของถั่วปัจจุบันเป็นคอนโทรลเลอร์หรือไม่ ซอร์สโค้ดมีดังนี้:
บูลีนที่ได้รับการป้องกัน ishandler (คลาส <?> beantype) {return annotationutils.findannotation (Beantype, controller.class)! = null;}ในการกำหนดค่าขั้นตอนที่ 4 ถั่วทั้งหมดที่มีคำอธิบายประกอบ @Controller จะลงทะเบียนในคอนเทนเนอร์ SpringMVC ดังนั้น SpringMVC จึงสามารถค้นหาโปรเซสเซอร์สำหรับการประมวลผลได้ดังนั้นจึงกระโดดตามปกติ
เราพบเหตุผลว่าทำไมมันไม่สามารถกระโดดได้อย่างถูกต้องดังนั้นวิธีการแก้ปัญหาคืออะไร?
เราสังเกตเห็นว่าในวิธีการ Inithandlermethods (), สวิตช์ detecthandlermethodsinancestorContexts ส่วนใหญ่จะควบคุมถั่วที่ได้รับในภาชนะบรรจุและไม่ว่าจะมีคอนเทนเนอร์หลักหรือไม่ ไม่รวมอยู่ในค่าเริ่มต้น ดังนั้นวิธีแก้ปัญหาคือการกำหนดค่าคุณสมบัติ detecthandlermethodsinancestorContexts ของ handlermapping เป็นจริงในไฟล์การกำหนดค่า SpringMVC (ที่นี่คุณต้องดูว่า handlermapping ประเภทใดที่ใช้ตามโครงการเฉพาะ) เพื่อให้สามารถตรวจจับถั่วของคอนเทนเนอร์แม่ ดังนี้:
<bean> <property name = "detecthandlermethodsinancestorContexts"> <dange> true </value> </porement> </ebean>
อย่างไรก็ตามในโครงการจริงจะมีการกำหนดค่ามากมาย เราแบ่งถั่วชนิดต่าง ๆ ในภาชนะที่แตกต่างกันตามคำแนะนำอย่างเป็นทางการตามโมดูลธุรกิจที่แตกต่างกัน: ตู้คอนเทนเนอร์ของผู้ปกครองฤดูใบไม้ผลิมีหน้าที่ในการลงทะเบียนถั่วอื่น ๆ ทั้งหมดที่ไม่ได้รับการอธิบายโดย @Controller ในขณะที่ SpringMVC รับผิดชอบการลงทะเบียนของถั่ว วิธีการกำหนดค่ามีดังนี้
1. กำหนดค่าใน ApplicationContext.xml:
<!-ลงทะเบียนถั่วในคอนเทนเนอร์ฤดูใบไม้ผลิที่ไม่ได้ใส่คำอธิบายประกอบโดย @Controller-> <บริบท: Component-Scan base-package = "com.hafiz.www"> <บริบท: ยกเว้นตัวกรองประเภท = "คำอธิบายประกอบ" expression = "org.springframework.steretype.controller"
2. การกำหนดค่าใน ApplicationContext-MVC.XML
<!-เฉพาะถั่วที่มีคำอธิบายประกอบ @Controller ลงทะเบียนในคอนเทนเนอร์ SpringMVC-> <บริบท: Component-Scan ฐานแพคเกจ = "com.hafiz.www" ใช้-default-filters = "false"> <บริบท: รวมประเภท filter = "Annotation" Expression =
3. สรุป
ด้วยวิธีนี้หลังจากที่เราเข้าใจความสัมพันธ์ระหว่างพ่อแม่-ลูกระหว่างฤดูใบไม้ผลิและสปริง MVC และหลักการของการสแกนและการลงทะเบียนตามคำแนะนำอย่างเป็นทางการเราสามารถจัดสรรถั่วประเภทต่าง ๆ ให้กับภาชนะที่แตกต่างกันเพื่อการจัดการ หากมีปัญหาเช่นถั่วไม่สามารถพบได้ SpringMVC ไม่สามารถเปลี่ยนเส้นทางได้และการกำหนดค่าการทำธุรกรรมล้มเหลวเราสามารถค้นหาและแก้ปัญหาได้อย่างรวดเร็ว มีความสุขมากมี ~
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น