คำนำ
บทความนี้จะแนะนำวิธีการหลายวิธีในการรับวัตถุคำขอในระบบเว็บที่พัฒนาโดย Spring MVC และหารือเกี่ยวกับความปลอดภัยของเธรด ฉันจะไม่พูดด้านล่างมากนักลองมาดูการแนะนำรายละเอียดด้วยกัน
ภาพรวม
เมื่อพัฒนาระบบเว็บโดยใช้สปริง MVC คุณมักจะต้องใช้วัตถุคำขอเมื่อประมวลผลคำขอเช่นการได้รับที่อยู่ IP ของลูกค้า URL ที่ร้องขอคุณลักษณะในส่วนหัว (เช่นคุกกี้ข้อมูลการอนุญาต) ข้อมูลในร่างกาย ฯลฯ มีการร้องขอพร้อมกันจำนวนมากสามารถรับประกันได้หรือไม่ว่าวัตถุคำขอที่แตกต่างกันถูกใช้ในคำขอ/เธรดที่แตกต่างกัน?
มีคำถามอื่นที่ควรทราบที่นี่: ฉันจะใช้วัตถุคำขอ "เมื่อประมวลผลคำขอ" ที่กล่าวถึงก่อนหน้านี้ที่ไหน เมื่อพิจารณาว่ามีความแตกต่างเล็กน้อยในวิธีการรับวัตถุคำขอพวกเขาสามารถแบ่งออกเป็นสองประเภท:
1) ใช้วัตถุคำขอในถั่วฤดูใบไม้ผลิ: รวมทั้งถั่ว MVC เช่นคอนโทรลเลอร์บริการที่เก็บและถั่วฤดูใบไม้ผลิทั่วไปเช่นส่วนประกอบ เพื่อความสะดวกในการอธิบายถั่วในฤดูใบไม้ผลิในข้อความต่อไปนี้ทั้งหมดเรียกว่าถั่วสั้น
2) ใช้วัตถุคำขอในไม่ใช่ถั่ว: เช่นในวิธีการของวัตถุ Java ธรรมดาหรือในวิธีการคงที่ของคลาส
นอกจากนี้บทความนี้กล่าวถึงเกี่ยวกับวัตถุคำขอที่แสดงถึงคำขอ แต่วิธีที่ใช้นั้นใช้กับวัตถุตอบสนอง, อินพุตสตรีม/เครื่องอ่าน, outputstream/นักเขียน ฯลฯ ; ในกรณีที่ InputStream/Reader สามารถอ่านข้อมูลในคำขอและ OutputStream/Writer สามารถเขียนข้อมูลไปยังการตอบกลับได้
ในที่สุดวิธีการรับวัตถุคำขอก็เกี่ยวข้องกับเวอร์ชันของฤดูใบไม้ผลิและ MVC; บทความนี้จะกล่าวถึงตามฤดูใบไม้ผลิ 4 และการทดลองที่ดำเนินการล้วนใช้เวอร์ชัน 4.1.1
วิธีทดสอบความปลอดภัยของด้าย
เนื่องจากปัญหาด้านความปลอดภัยของเธรดของวัตถุคำขอจำเป็นต้องให้ความสนใจเป็นพิเศษเพื่ออำนวยความสะดวกในการอภิปรายด้านล่างให้อธิบายวิธีการทดสอบก่อนว่าวัตถุคำขอนั้นปลอดภัยหรือไม่
แนวคิดพื้นฐานของการทดสอบคือการจำลองคำขอพร้อมกันจำนวนมากบนไคลเอนต์แล้วพิจารณาว่ามีการใช้คำขอบนเซิร์ฟเวอร์หรือไม่
วิธีที่ใช้งานง่ายที่สุดในการพิจารณาว่าวัตถุคำขอเหมือนกันคือการพิมพ์ที่อยู่ของวัตถุคำขอหรือไม่ หากเหมือนกันก็หมายความว่าใช้วัตถุเดียวกัน อย่างไรก็ตามในการใช้งานเว็บเซิร์ฟเวอร์เกือบทั้งหมดใช้พูลเธรดซึ่งนำไปสู่คำขอสองคำขอที่มาถึงอย่างต่อเนื่องซึ่งอาจถูกประมวลผลโดยเธรดเดียวกัน: หลังจากประมวลผลคำขอก่อนหน้านี้พูลเธรดจะเรียกคืนเธรดและกำหนดเธรดใหม่ให้กับคำขอที่ตามมา ในเธรดเดียวกันวัตถุคำขอที่ใช้มีแนวโน้มที่จะเหมือนกัน (ที่อยู่เหมือนกันแอตทริบิวต์จะแตกต่างกัน) ดังนั้นแม้สำหรับวิธีการที่ปลอดภัยของเธรดที่อยู่วัตถุคำขอที่ใช้โดยคำขอที่แตกต่างกันอาจเหมือนกัน
เพื่อหลีกเลี่ยงปัญหานี้วิธีหนึ่งคือการปล่อยให้เธรดนอนหลับสักสองสามวินาทีในระหว่างกระบวนการประมวลผลคำขอซึ่งสามารถทำให้แต่ละเธรดทำงานได้นานพอที่จะหลีกเลี่ยงเธรดเดียวกันที่จัดสรรให้กับคำขอที่แตกต่างกัน วิธีอื่นคือการใช้แอตทริบิวต์อื่น ๆ ของคำขอ (เช่นพารามิเตอร์ส่วนหัวส่วนหัวของร่างกาย ฯลฯ ) เป็นพื้นฐานสำหรับการร้องขอว่ามีเธรดที่ปลอดภัยหรือไม่เพราะแม้ว่าคำขอที่แตกต่างกันจะใช้เธรดเดียวกันหลังจากนั้น (ที่อยู่ของวัตถุคำขอเท่ากัน) ตราบใดที่วัตถุคำขอถูกสร้างขึ้นสองครั้งโดยใช้แอตทริบิวต์ที่แตกต่างกัน บทความนี้ใช้วิธีที่สองสำหรับการทดสอบ
รหัสทดสอบไคลเอนต์มีดังนี้ (สร้าง 1,000 เธรดเพื่อส่งคำขอแยกกัน):
การทดสอบระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น {string คำนำหน้า = uuid.randomuuid (). toString (). replaceall ("-", "") + "::"; สำหรับ (int i = 0; i <1000; i ++) {ค่าสตริงสุดท้าย = คำนำหน้า+i; เธรดใหม่ () {@Override โมฆะสาธารณะเรียกใช้ () {ลอง {classeablehttpClient httpClient = httpClients.createdefault (); httpget httpget = new httpget ("http: // localhost: 8080/test? key =" + value); httpClient.execute (httpget); httpClient.close (); } catch (ioexception e) {e.printstacktrace (); } } } } } }.เริ่ม(); -รหัสคอนโทรลเลอร์ในเซิร์ฟเวอร์มีดังนี้ (รหัสสำหรับการรับวัตถุคำขอถูกละเว้นชั่วคราว):
@ControllerPublic Class TestController {// จัดเก็บพารามิเตอร์ที่มีอยู่เพื่อตรวจสอบว่าพารามิเตอร์ซ้ำกันหรือไม่ดังนั้นจึงพิจารณาว่าเธรดนั้นปลอดภัยสาธารณะเซตคงที่ <string> set = new HashSet <> (); @RequestMapping ("/ทดสอบ") การทดสอบโมฆะสาธารณะ () พ่น InterruptedException {// - - - - "/t ปรากฏซ้ำ ๆ การร้องขอการเกิดขึ้นไม่ปลอดภัย!"); } else {system.out.println (ค่า); set.add (ค่า); } // โปรแกรมการจำลองได้ถูกดำเนินการเป็นระยะเวลาหนึ่ง, thread.sleep (1,000); -หากวัตถุคำขอมีความปลอดภัยเธรดผลลัพธ์การพิมพ์ในเซิร์ฟเวอร์มีดังนี้:
หากมีปัญหาด้านความปลอดภัยของเธรดการพิมพ์ผลลัพธ์ในเซิร์ฟเวอร์อาจมีลักษณะเช่นนี้:
หากไม่มีคำอธิบายพิเศษรหัสทดสอบจะถูกตัดออกจากรหัสในภายหลังในบทความนี้
วิธีที่ 1: เพิ่มพารามิเตอร์ลงในคอนโทรลเลอร์
ตัวอย่างรหัส
วิธีนี้เป็นวิธีที่ง่ายที่สุดในการใช้งานและป้อนรหัสคอนโทรลเลอร์โดยตรง:
@ControllerPublic คลาส testController {@requestmapping ("/test") การทดสอบโมฆะสาธารณะ (คำขอ httpservletrequest) พ่น InterruptedException {// โปรแกรมจำลองได้ถูกดำเนินการเป็นระยะเวลาเธรด -หลักการของวิธีนี้คือเมื่อวิธีการคอนโทรลเลอร์เริ่มประมวลผลคำขอสปริงจะกำหนดวัตถุคำขอให้กับพารามิเตอร์เมธอด นอกเหนือจากวัตถุคำขอแล้วยังมีพารามิเตอร์มากมายที่สามารถรับได้ผ่านวิธีนี้ สำหรับรายละเอียดโปรดดูที่: https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-methods
หลังจากได้รับวัตถุคำขอในคอนโทรลเลอร์หากคุณต้องการใช้วัตถุคำขอในวิธีการอื่น (เช่นวิธีการบริการวิธีการคลาสเครื่องมือ ฯลฯ ) คุณต้องผ่านวัตถุคำขอเป็นพารามิเตอร์เมื่อเรียกวิธีการเหล่านี้
ความปลอดภัยด้าย
ผลการทดสอบ: ความปลอดภัยของด้าย
การวิเคราะห์: ในเวลานี้วัตถุคำขอเป็นพารามิเตอร์วิธีการซึ่งเทียบเท่ากับตัวแปรท้องถิ่นและไม่ต้องสงสัยอย่างไม่ต้องสงสัย
ข้อดีและข้อเสีย
ข้อเสียเปรียบหลักของวิธีนี้คือวัตถุคำขอซ้ำเกินกว่าที่จะเขียนซึ่งส่วนใหญ่สะท้อนให้เห็นในสองจุด:
1) หากต้องการวัตถุคำขอในหลายวิธีคอนโทรลเลอร์จะต้องเพิ่มพารามิเตอร์คำขอในแต่ละวิธี
2) การได้มาของวัตถุคำขอสามารถเริ่มต้นจากคอนโทรลเลอร์เท่านั้น หากสถานที่ที่มีการใช้วัตถุคำขออยู่ในสถานที่ที่ลึกกว่าของระดับการเรียกใช้ฟังก์ชันวิธีการทั้งหมดในห่วงโซ่การโทรทั้งหมดจำเป็นต้องเพิ่มพารามิเตอร์คำขอ
ในความเป็นจริงในระหว่างกระบวนการประมวลผลคำขอทั้งหมดวัตถุคำขอจะทำงานผ่านคำขอทั้งหมด นั่นคือยกเว้นกรณีพิเศษเช่นตัวจับเวลาวัตถุคำขอเทียบเท่ากับตัวแปรส่วนกลางภายในเธรด วิธีนี้เทียบเท่ากับการผ่านตัวแปรทั่วโลกนี้
วิธีที่ 2: การฉีดอัตโนมัติ
ตัวอย่างรหัส
อัปโหลดรหัสก่อนอื่น:
@ControllerPublic คลาส testController {@autowired ส่วนตัว httpservletrequest คำขอ; // คำขออัตโนมัติ @requestmapping ("/test") การทดสอบโมฆะสาธารณะ () พ่น InterruptedException {// โปรแกรมการจำลองได้ถูกดำเนินการเป็นระยะเวลา thread.sleep (1,000); - ความปลอดภัยด้าย
ผลการทดสอบ: ความปลอดภัยของด้าย
การวิเคราะห์: ในฤดูใบไม้ผลิขอบเขตของคอนโทรลเลอร์คือซิงเกิลตัน (ซิงเกิลตัน) ซึ่งหมายความว่าในระบบเว็บทั้งหมดมีการทดสอบเพียงครั้งเดียวเท่านั้น แต่คำขอที่ฉีดเป็นเธรดที่ปลอดภัยเพราะ:
ด้วยวิธีนี้เมื่อถั่ว (testcontroller ในตัวอย่างนี้) เริ่มต้นสปริงไม่ได้ฉีดวัตถุคำขอ แต่เป็นพร็อกซี; เมื่อถั่วจำเป็นต้องใช้วัตถุคำขอวัตถุคำขอจะได้รับผ่านพร็อกซี
ต่อไปนี้เป็นคำอธิบายของการใช้งานนี้ผ่านรหัสเฉพาะ
เพิ่มจุดพักลงในรหัสด้านบนและดูคุณสมบัติของวัตถุคำขอดังแสดงในรูปด้านล่าง:
ดังที่เห็นได้ในรูปที่คำขอเป็นพร็อกซี: การใช้งานของพร็อกซีจะแสดงในคลาสภายในของ autowireatils
ObjectFactoryDelegatingInvocationHandler: /*** Reflective InvocationHandler สำหรับการเข้าถึงวัตถุเป้าหมายปัจจุบันขี้เกียจ */@suppresswarnings ("อนุกรม") คลาสคงที่คลาสคงที่ ObjectFactoryDelegatingInvocationHandler ใช้การเรียกใช้งาน Handler, serializable {Private Final ObjectFactory <?> ObjectFactory; Public ObjectFactoryDelegatingInvocationHandler (ObjectFactory <?> ObjectFactory) {this.ObjectFactory = ObjectFactory; } @Override วัตถุสาธารณะเรียกใช้ (พร็อกซีวัตถุวิธีเมธอด, วัตถุ [] args) โยน throwable {// ... ละเว้นรหัสที่ไม่เกี่ยวข้องลอง {return method.invoke (this.objectFactory.getObject (), args); // การใช้งานแกนหลักรหัสหลัก} catch (InvocationTargetException Ex) {โยน ex.getTargetException (); -กล่าวอีกนัยหนึ่งเมื่อเราเรียกวิธีการของคำขอเราเรียกวิธีการวิธีการของวัตถุที่สร้างโดย ObjectFactory.getObject (); วัตถุที่สร้างโดย ObjectFactory.getObject () เป็นวัตถุคำขอจริง
ดำเนินการต่อเพื่อสังเกตตัวเลขด้านบนและพบว่าประเภท ObjectFactory เป็นคลาสภายในคลาส requestObjectFactory ของ webApplicationContextUtils; และรหัส requestObjectFactory มีดังนี้:
/*** โรงงานที่เปิดเผยวัตถุคำขอปัจจุบันตามความต้องการ */ @suppresswarnings ("อนุกรม") คลาสสแตติกคลาสส่วนตัว requestObjectFactory ใช้งาน ObjectFactory <servletRequest>, serializable {@Override public ServletRequest getObject () {ส่งคืน CurrentRequestattributes () GetRequest (); } @Override สตริงสาธารณะ toString () {return "ปัจจุบัน httpservletrequest"; -ในหมู่พวกเขาในการรับวัตถุคำขอคุณต้องเรียกเมธอด currentRequestattributes () เพื่อรับวัตถุคำขอ การใช้วิธีนี้มีดังนี้:
/*** ส่งคืนอินสแตนซ์ requestattributes ปัจจุบันเป็น servletrequestattributes */ส่วนตัวแบบคงที่ servletRequestattributes currentRequestatTributes () {requestattributes requestattr = requestcontextholder.currentrequestattributes (); if (! (requestattr อินสแตนซ์ของ ServletRequestattributes)) {โยน ungelmalStateException ใหม่ ("คำขอปัจจุบันไม่ใช่คำขอ servlet"); } return (servletrequestattributes) requestattr;}โค้ดหลักที่สร้างวัตถุ RequestAttributes อยู่ในคลาส requestcontextholder ซึ่งรหัสที่เกี่ยวข้องมีดังนี้ (รหัสที่ไม่เกี่ยวข้องในคลาสถูกละเว้น):
Public Abstract Class Requestcontextholder {Public Static Requestattributes CurrentRequestatTributes () พ่นผิดกฎหมาย regengalStateException {requestattributes attributes = getRequestatTributes (); // ตรรกะที่ไม่เกี่ยวข้องถูกละไว้ที่นี่ ...... คุณลักษณะส่งคืน; } public requestattributes getRequestattributes () {requestattributes attributes = requestattributeSholder.get (); if (attributes == null) {attributes = mandleItableRequestattributeSholder.get (); } return attributes; } private static final threadLocal <EquestAttributes> requestattributeSholder = new namedthreadLocal <EquestAttributes> ("คำขอแอตทริบิวต์"); Private Static Final ThreadLocal <EquestAtTributes> MandleItableRequestatTributeSholder = new NamedInherItableThreadLocal <EquestAtTributes> ("บริบทคำขอ");}จากรหัสนี้เราจะเห็นได้ว่าออบเจ็กต์ requestattributes ที่สร้างขึ้นเป็นตัวแปรเธรดท้องถิ่น (ThreadLocal) ดังนั้นวัตถุคำขอจึงเป็นตัวแปรเธรดท้องถิ่น สิ่งนี้ทำให้มั่นใจได้ถึงความปลอดภัยของด้ายของวัตถุคำขอ
ข้อดีและข้อเสีย
ข้อดีหลักของวิธีนี้:
1) การฉีดไม่ จำกัด เฉพาะคอนโทรลเลอร์: ในวิธีการที่ 1 สามารถเพิ่มพารามิเตอร์คำขอลงในคอนโทรลเลอร์ได้เท่านั้น สำหรับวิธีที่ 2 ไม่เพียง แต่สามารถฉีดในคอนโทรลเลอร์ แต่ยังอยู่ในถั่วใด ๆ รวมถึงบริการที่เก็บและถั่วธรรมดา
2) วัตถุที่ฉีดไม่ จำกัด เฉพาะการร้องขอ: นอกเหนือจากการฉีดวัตถุคำขอวิธีนี้ยังสามารถฉีดวัตถุอื่น ๆ ด้วยขอบเขตเป็นคำขอหรือเซสชันเช่นวัตถุตอบสนองวัตถุเซสชัน ฯลฯ ; และรับรองความปลอดภัยของด้าย
3) ลดความซ้ำซ้อนของรหัส: เพียงแค่ฉีดวัตถุคำขอลงในถั่วที่ต้องการวัตถุคำขอและสามารถใช้ในวิธีการต่าง ๆ ของถั่วซึ่งลดความซ้ำซ้อนของรหัสอย่างมากเมื่อเทียบกับวิธีที่ 1
อย่างไรก็ตามวิธีนี้ยังมีรหัสซ้ำซ้อน พิจารณาสถานการณ์นี้: มีตัวควบคุมจำนวนมากในระบบเว็บและตัวควบคุมแต่ละตัวใช้วัตถุคำขอ (สถานการณ์นี้เป็นจริงบ่อยมาก) ในเวลานี้คุณต้องเขียนโค้ดเพื่อส่งคำขอหลายครั้ง หากคุณจำเป็นต้องฉีดการตอบกลับรหัสจะยุ่งยากมากขึ้น ต่อไปนี้อธิบายถึงการปรับปรุงวิธีการฉีดอัตโนมัติและวิเคราะห์ความปลอดภัยของด้ายและข้อดีและข้อเสีย
วิธีที่ 3: การฉีดอัตโนมัติเข้าสู่ชั้นฐาน
ตัวอย่างรหัส
เมื่อเปรียบเทียบกับวิธีที่ 2 ใส่ส่วนที่ฉีดลงของรหัสลงในคลาสฐาน
รหัสคลาสพื้นฐาน:
Basecontroller ระดับสาธารณะ {@autowired ป้องกัน httpservletrequest คำขอ; -รหัสคอนโทรลเลอร์มีดังนี้ นี่คือสองคลาสที่ได้รับของ basecontroller เนื่องจากรหัสทดสอบจะแตกต่างกันในเวลานี้รหัสทดสอบเซิร์ฟเวอร์จึงไม่ถูกละเว้น ลูกค้ายังต้องทำการปรับเปลี่ยนที่สอดคล้องกัน (ส่งคำขอพร้อมกันจำนวนมากไปยัง URL ทั้งสองในเวลาเดียวกัน)
@ControllerPublic Class TestController ขยาย Basecontroller {// จัดเก็บพารามิเตอร์ที่มีอยู่เพื่อตรวจสอบว่าค่าพารามิเตอร์ซ้ำแล้วซ้ำ @RequestMapping ("/test") การทดสอบโมฆะสาธารณะ () พ่น InterruptedException {ค่าสตริง = request.getParameter ("คีย์"); // ตรวจสอบความปลอดภัยของเธรดถ้า (set.contains (value)) {system.out.println (ค่า + "/t ปรากฏซ้ำ ๆ ซ้ำ ๆ คำขอพร้อมกันไม่ปลอดภัย!"); } else {system.out.println (ค่า); set.add (ค่า); } // โปรแกรมการจำลองถูกดำเนินการเป็นระยะเวลา thread.sleep (1,000); }} @ControllerPublic คลาส test2Controller ขยาย basecontroller {@requestmapping ("/test2") โมฆะสาธารณะ test2 () โยน interruptedException {ค่าสตริง = request.getParameter ("คีย์"); // ตัดสินความปลอดภัยเธรด (ใช้ชุดที่มี testController เพื่อตัดสิน) ถ้า (testController.set.contains (ค่า)) {system.out.println (ค่า + "/t ปรากฏซ้ำ ๆ การร้องขอการเกิดขึ้นไม่ปลอดภัย!"); } else {system.out.println (ค่า); testController.set.add (ค่า); } // โปรแกรมการจำลองได้ถูกดำเนินการเป็นระยะเวลาหนึ่ง, thread.sleep (1,000); - ความปลอดภัยด้าย
ผลการทดสอบ: ความปลอดภัยของด้าย
การวิเคราะห์: ขึ้นอยู่กับการทำความเข้าใจกับความปลอดภัยของเธรดของวิธีที่ 2 มันเป็นเรื่องง่ายที่จะเข้าใจว่าวิธีที่ 3 คือเธรดที่ปลอดภัย: เมื่อสร้างวัตถุคลาสที่ได้รับที่แตกต่างกันโดเมนในคลาสฐาน (นี่คือคำขอที่ฉีด) จะใช้พื้นที่หน่วยความจำที่แตกต่างกันในวัตถุคลาสที่ได้รับ ผลการทดสอบยังพิสูจน์สิ่งนี้
ข้อดีและข้อเสีย
เมื่อเปรียบเทียบกับวิธีที่ 2 หลีกเลี่ยงการฉีดซ้ำในคอนโทรลเลอร์ที่แตกต่างกัน อย่างไรก็ตามเมื่อพิจารณาว่า Java อนุญาตให้รับมรดกของคลาสฐานเดียวเท่านั้นหากคอนโทรลเลอร์จำเป็นต้องสืบทอดคลาสอื่น ๆ วิธีนี้ไม่ง่ายต่อการใช้งานอีกต่อไป
ไม่ว่าจะเป็นวิธีที่ 2 หรือวิธีที่ 3 คุณสามารถฉีดคำขอลงในถั่วเท่านั้น หากวิธีการอื่น (เช่นวิธีการคงที่ในคลาสเครื่องมือ) จำเป็นต้องใช้วัตถุคำขอคุณต้องผ่านพารามิเตอร์คำขอเมื่อเรียกใช้วิธีการเหล่านี้ วิธีที่ 4 ที่แนะนำด้านล่างสามารถใช้โดยตรงในวิธีการคงที่เช่นคลาสเครื่องมือ (แน่นอนมันสามารถใช้ในถั่วต่างๆ)
วิธีที่ 4: โทรด้วยตนเอง
ตัวอย่างรหัส
@ControllerPublic คลาส testController {@requestmapping ("/test") การทดสอบโมฆะสาธารณะ () พ่น InterruptedException {httpservletRequest Request = ((servletRequestattributes) // โปรแกรมการจำลองได้ถูกดำเนินการเป็นระยะเวลาเธรดเวลา SLEEP (1,000); - ความปลอดภัยด้าย
ผลการทดสอบ: ความปลอดภัยของด้าย
การวิเคราะห์: วิธีนี้คล้ายกับวิธีที่ 2 (การฉีดอัตโนมัติ) ยกเว้นว่ามันถูกนำไปใช้ผ่านการฉีดอัตโนมัติในวิธีที่ 2 และวิธีนี้จะถูกนำไปใช้ผ่านการเรียกใช้วิธีด้วยตนเอง ดังนั้นวิธีนี้จึงเป็นแบบเธรดที่ปลอดภัย
ข้อดีและข้อเสีย
ข้อดี: สามารถรับได้โดยตรงในไม่ใช่ถั่ว ข้อเสีย: หากคุณใช้สถานที่เพิ่มเติมรหัสนั้นยุ่งยากมาก ดังนั้นจึงสามารถใช้ร่วมกับวิธีอื่น ๆ
วิธีที่ 5: @ModelAttribute Method
ตัวอย่างรหัส
วิธีการต่อไปนี้และตัวแปร (การกลายพันธุ์: ใส่คำขอและ bindrequest ในคลาสย่อย) มักจะเห็นออนไลน์:
@ControllerPublic คลาส TestController {คำขอ httpservletRequest ส่วนตัว; @ModelAttribute โมฆะสาธารณะ BindRequest (คำขอ httpservletRequest) {this.request = คำขอ; } @RequestMapping ("/ทดสอบ") การทดสอบโมฆะสาธารณะ () พ่น InterruptedException {// โปรแกรมการจำลองได้ถูกดำเนินการเป็นระยะเวลาเธรดเวลา SLEEEP (1,000); - ความปลอดภัยด้าย
ผลการทดสอบ: เธรดไม่ปลอดภัย
การวิเคราะห์: เมื่อ @ModelAttribute Annotation ถูกใช้เพื่อแก้ไขวิธีการในคอนโทรลเลอร์ฟังก์ชั่นของมันคือวิธีการจะถูกดำเนินการก่อนที่จะดำเนินการ @RequestMapping แต่ละวิธีในคอนโทรลเลอร์ ดังนั้นในตัวอย่างนี้ฟังก์ชั่นของ bindRequest () คือการกำหนดค่าให้กับวัตถุคำขอก่อนที่จะทำการทดสอบ () แม้ว่าคำขอพารามิเตอร์ใน bindRequest () นั้นจะปลอดภัยในเธรดเนื่องจาก TestController เป็น Singleton, คำขอเป็นฟิลด์ของ TestController แต่ไม่สามารถรับประกันความปลอดภัยของเธรดได้
สรุป
ในการสรุปการเพิ่มพารามิเตอร์ (วิธีที่ 1), การฉีดอัตโนมัติ (วิธีที่ 2 และวิธีที่ 3) และการโทรด้วยตนเอง (วิธีที่ 4) ในคอนโทรลเลอร์ล้วนปลอดภัยและสามารถใช้เพื่อรับวัตถุคำขอ หากวัตถุคำขอถูกใช้น้อยลงในระบบสามารถใช้วิธีใดวิธีหนึ่ง หากมีการใช้มากขึ้นขอแนะนำให้ใช้การฉีดอัตโนมัติ (วิธีที่ 2 และวิธีที่ 3) เพื่อลดความซ้ำซ้อนของรหัส หากคุณต้องการใช้วัตถุคำขอในการไม่ใช่ถั่วคุณสามารถส่งผ่านผ่านพารามิเตอร์เมื่อเรียกเลเยอร์ด้านบนหรือคุณสามารถรับได้โดยตรงผ่านการโทรด้วยตนเอง (วิธีที่ 4)
โอเคข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะมีค่าอ้างอิงบางอย่างสำหรับการศึกษาหรือที่ทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร ขอบคุณสำหรับการสนับสนุน Wulin.com
การอ้างอิง