1. interceptors และตัวกรอง
ก่อนที่จะพูดคุยเกี่ยวกับการบูตฤดูใบไม้ผลิก่อนอื่นมาดูตัวกรองและตัวดักจับ ทั้งสองมีความคล้ายคลึงกันมากในแง่ของฟังก์ชั่น แต่ยังมีช่องว่างขนาดใหญ่ในการใช้งานทางเทคนิคเฉพาะ ก่อนที่จะวิเคราะห์ความแตกต่างระหว่างทั้งสองให้เราเข้าใจแนวคิดของ AOP ก่อน AOP ไม่ใช่เทคโนโลยีเฉพาะ แต่เป็นแนวคิดการเขียนโปรแกรม ในกระบวนการของการเขียนโปรแกรมเชิงวัตถุมันเป็นเรื่องง่ายสำหรับเราที่จะแก้ปัญหาการขยายตัวในแนวตั้งผ่านการสืบทอดและความหลากหลาย อย่างไรก็ตามสำหรับฟังก์ชั่นแนวนอนเช่นการเปิดใช้งานการทำธุรกรรมในวิธีการบริการทั้งหมดหรือการบันทึกแบบครบวงจรฟังก์ชั่นเชิงวัตถุไม่สามารถแก้ไขได้ ดังนั้นการเขียนโปรแกรมที่เน้น AOP จึงเป็นส่วนเสริมของแนวคิดการเขียนโปรแกรมเชิงวัตถุ ตัวกรองและตัวดักจับที่เรากำลังพูดถึงในวันนี้เป็นทั้งการใช้งานเฉพาะของการเขียนโปรแกรมเชิงภาพ ความแตกต่างหลักระหว่างทั้งสองรวมถึงแง่มุมต่อไปนี้:
1. ตัวกรองขึ้นอยู่กับคอนเทนเนอร์ servlet และเป็นส่วนหนึ่งของข้อกำหนด servlet Interceptors มีอยู่อย่างอิสระและสามารถใช้งานได้ไม่ว่าในกรณีใด ๆ
2. การดำเนินการของตัวกรองเสร็จสมบูรณ์โดยการเรียกกลับคอนเทนเนอร์ servlet และตัวดักจับมักจะดำเนินการผ่านพร็อกซีแบบไดนามิก
3. วงจรชีวิตของตัวกรองได้รับการจัดการโดยคอนเทนเนอร์ servlet ในขณะที่ตัวดักจับสามารถจัดการผ่านคอนเทนเนอร์ IOC ดังนั้นอินสแตนซ์ของถั่วอื่น ๆ สามารถรับได้ผ่านการฉีดและวิธีการอื่น ๆ ดังนั้นจึงสะดวกกว่าในการใช้งาน
2. การกำหนดค่าตัวกรอง
ตอนนี้เราใช้ตัวกรองเพื่อรับรู้ฟังก์ชั่นของการบันทึกเวลาดำเนินการตามคำขอซึ่งดำเนินการดังนี้:
Public Class LogCostFilter ใช้ตัวกรอง {@Override โมฆะสาธารณะเริ่มต้น (FilterConfig FilterConfig) พ่น servletexception {} @Override โมฆะสาธารณะ dofilter (servletrequest servletrequest, servletResponseStresponse FilterChain.dofilter (ServletRequest, ServletResponse); System.out.println ("ดำเนินการ cost ="+(system.currenttimeMillis ()-เริ่มต้น)); } @Override โมฆะสาธารณะทำลาย () {}}ตรรกะของรหัสนี้ค่อนข้างง่ายซึ่งคือการบันทึกการประทับเวลาก่อนที่จะดำเนินการวิธีการแล้วดำเนินการตามคำขอผ่านห่วงโซ่ตัวกรองและคำนวณเวลาดำเนินการระหว่างผลลัพธ์ที่ส่งคืน สิ่งสำคัญที่นี่คือคลาสนี้จะต้องสืบทอดคลาสตัวกรอง นี่คือข้อกำหนดของ Servlet ซึ่งไม่แตกต่างจากโครงการเว็บก่อนหน้านี้ อย่างไรก็ตามด้วยคลาสตัวกรองโครงการเว็บก่อนหน้านี้สามารถกำหนดค่าได้ใน web.xml แต่โครงการ Spring Boot ไม่มีไฟล์ web.xml ดังนั้นจะกำหนดค่าได้อย่างไร ใน Spring Boot เราจำเป็นต้องมีการลงทะเบียน FilterRegistrationBean เพื่อให้การกำหนดค่าเสร็จสมบูรณ์ กระบวนการดำเนินการมีดังนี้:
@ConfigurationPublic คลาส FilterConfig {@Bean Public FilterRegistrationBean ลงทะเบียน Filter () {FilterRegistrationBean ลงทะเบียน = ใหม่ FilterRegistrationBean (); ลงทะเบียน SetFilter (ใหม่ LogCostFilter ()); ลงทะเบียน. addurlpatterns ("/*"); ลงทะเบียน SetName ("LogCostFilter"); การลงทะเบียน SetOrder (1); การลงทะเบียนคืน; -การกำหนดค่านี้เสร็จสมบูรณ์ ตัวเลือกที่จำเป็นต้องได้รับการกำหนดค่าส่วนใหญ่จะรวมถึงการสร้างอินสแตนซ์คลาสตัวกรองจากนั้นระบุรูปแบบการจับคู่ของ URL การตั้งค่าชื่อตัวกรองและลำดับการดำเนินการ กระบวนการนี้ไม่แตกต่างจากการกำหนดค่าใน web.xml แต่แบบฟอร์มนั้นแตกต่างกัน ตอนนี้เราสามารถเริ่มต้นเซิร์ฟเวอร์เพื่อเข้าถึง URL ใด ๆ :
คุณจะเห็นว่าการกำหนดค่าข้างต้นมีผล นอกเหนือจากการกำหนดค่าผ่าน FilterRegistrationBean แล้วยังมีวิธีที่ตรงกว่าซึ่งสามารถทำได้โดยตรงผ่านคำอธิบายประกอบ:
@WebFilter (urlpatterns = "/*", filtername = "logfilter2") คลาสสาธารณะ LogCostFilter2 ใช้ตัวกรอง {@Override โมฆะสาธารณะ init (FilterConfig FilterConfig) การส่ง servletexception FilterChain) พ่น IOException, ServleTexception {Long Start = System.CurrentTimeMillis (); FilterChain.dofilter (ServletRequest, ServletResponse); System.out.println ("logFilter2 ดำเนินการ cost =" + (system.currentTimeMillis () - เริ่มต้น)); } @Override โมฆะสาธารณะทำลาย () {}}ที่นี่คุณสามารถกำหนดค่าได้โดยตรงด้วย @webfilter ในทำนองเดียวกันคุณสามารถตั้งค่าโหมดการจับคู่ URL ชื่อตัวกรอง ฯลฯ สิ่งหนึ่งที่ควรทราบที่นี่คือคำอธิบายประกอบ @WebFilter เป็นข้อกำหนดของ Servlet 3.0 และไม่ได้รับการจัดเตรียมโดย Spring Boot นอกเหนือจากคำอธิบายประกอบนี้แล้วเรายังต้องเพิ่มคำอธิบายประกอบอื่นในคลาสการกำหนดค่า: @ServletComponetScan โดยระบุแพ็คเกจสแกน
@springbootapplication@mapperscan ("com.pandy.blog.dao")@servletComponentscan ("com.pandy.blog.filters") แอปพลิเคชันระดับสาธารณะ - ตอนนี้มาเยี่ยมชม URL ใด ๆ อีกครั้ง:
อย่างที่คุณเห็นตัวกรองทั้งสองที่เรากำหนดค่ามีผล ผู้อ่านอย่างระมัดระวังจะพบว่าเราไม่ได้ระบุลำดับของการดำเนินการของตัวกรองที่สอง แต่ดำเนินการก่อนตัวกรองแรก ควรอธิบายที่นี่ว่าคำอธิบายประกอบ @WebFilter ไม่ได้ระบุแอตทริบิวต์คำสั่งการดำเนินการ ลำดับการดำเนินการขึ้นอยู่กับชื่อของตัวกรองและจัดเรียงตามลำดับย้อนกลับตามลำดับตัวอักษรของชื่อคลาสตัวกรอง (โปรดทราบว่าไม่ใช่ชื่อของตัวกรองที่กำหนดค่า) ลำดับความสำคัญของตัวกรองที่ระบุโดย @WebFilter สูงกว่าตัวกรองที่กำหนดค่าโดย FilterRegistrationBean เพื่อนที่สนใจสามารถทดลองได้ด้วยตนเอง
3. การกำหนดค่า interceptor
เราได้แนะนำวิธีการกำหนดค่าตัวกรองด้านบนแล้ว จากนั้นมาดูวิธีการกำหนดค่าการสกัดกั้น เราใช้ Interceptor เพื่อใช้ฟังก์ชั่นเดียวกันข้างต้นบันทึกเวลาดำเนินการของคำขอ ก่อนอื่นเราใช้คลาส Interceptor:
LogCostInterceptor คลาสสาธารณะใช้ HandlerInterceptor {Long Start = System.currentTimeMillis (); @Override บูลีนสาธารณะ prehandle (httpservletrequest httpservletrequest, httpservletResponse httpservletResponse, วัตถุ o) โยนข้อยกเว้น {start = system.currentTimeMillis (); กลับมาจริง; } @Override โมฆะสาธารณะ Postthandle (httpservletRequest httpservletrequest, httpservletResponse httpservletResponse, Object O, ModelandView ModelandView) โยนข้อยกเว้น {system.out.println ( } @Override โมฆะสาธารณะหลังการรวม (httpservletRequest httpservletRequest, httpservletResponse httpservletResponse, วัตถุ o, ข้อยกเว้น e) โยนข้อยกเว้น {}}}ที่นี่เราจำเป็นต้องใช้อินเทอร์เฟซ HandlerInterceptor อินเทอร์เฟซนี้มีสามวิธี prehandle จะดำเนินการก่อนที่จะดำเนินการคำขอและ Posthandler จะถูกดำเนินการหลังจากดำเนินการคำขอ แต่จะดำเนินการเฉพาะเมื่อเมธอด prehandle ส่งคืนจริง AfterCompletion จะดำเนินการหลังจากการแสดงผลมุมมองเสร็จสิ้น Prehandle ยังต้องกลับมาเป็นจริง วิธีนี้มักใช้สำหรับการทำความสะอาดทรัพยากรและงานอื่น ๆ นอกเหนือจากการใช้อินเทอร์เฟซข้างต้นแล้วเรายังต้องกำหนดค่า:
@ConfigurationPublic คลาส InterceptorConfig ขยาย WebMVCCONFigurerAdapter {@Override โมฆะสาธารณะ AddInterceptors (InterceptorRegistry Registry) {registry.addinterceptor (ใหม่ logCostInterceptor ()). addPathPatterns ("/**"); super.addinterceptors (รีจิสทรี); -ที่นี่เราสืบทอด webmvcconfigureradapter เพื่อนที่ได้อ่านบทความก่อนหน้านี้ควรได้เห็นชั้นนี้ เราได้ใช้คลาสนี้เมื่อกำหนดค่าไดเรกทอรีทรัพยากรคงที่ ที่นี่เราได้เขียนเมธอด addInterceptors ใหม่เพื่อกำหนดค่า interceptor มีสองรายการการกำหนดค่าหลัก: หนึ่งคือการระบุ interceptor และอีกรายการหนึ่งคือการระบุ URL interceptor ตอนนี้เราเริ่มระบบและเข้าถึง URL ใด ๆ :
อย่างที่คุณเห็นเราได้รับฟังก์ชั่นเดียวกันผ่านตัวดักจับ อย่างไรก็ตามควรสังเกตที่นี่ว่าการใช้งานนี้เป็นปัญหาจริง ๆ เพราะ prehandle และ postthandle เป็นสองวิธีดังนั้นเราต้องตั้งค่าตัวแปรที่ใช้ร่วมกันเพื่อจัดเก็บค่าเริ่มต้น แต่จะมีปัญหาด้านความปลอดภัยของเธรด แน่นอนว่าเราสามารถแก้ปัญหานี้ได้ด้วยวิธีการอื่น ๆ เช่น Threadlocal ซึ่งสามารถแก้ไขได้ดีและนักเรียนที่สนใจสามารถนำไปใช้เองได้ อย่างไรก็ตามด้วยสิ่งนี้เราจะเห็นได้ว่าแม้ว่าตัวดักจับจะดีกว่าตัวกรองในหลาย ๆ สถานการณ์ในสถานการณ์นี้ตัวกรองนั้นง่ายกว่าการใช้งาน
4. สรุป
บทความนี้ส่วนใหญ่จะอธิบายการกำหนดค่าของตัวกรองและตัวดักจับตามสปริงบูต ทั้งตัวกรองและตัวดักจับอยู่ในการใช้งานเฉพาะของแนวคิด AOP (การเขียนโปรแกรมแบบส่วนที่มุ่งเน้น) นอกเหนือจากการใช้งานทั้งสองนี้เรายังได้เห็นเทคโนโลยีการใช้งาน AOP ที่ยืดหยุ่นอีกอย่างหนึ่งคือแง่มุมที่เราสามารถทำหน้าที่ที่ทรงพลังให้เสร็จสมบูรณ์ได้มากขึ้นผ่านด้าน ฉันจะแบ่งปันสิ่งนี้กับคุณในภายหลัง