ฉันสังเกตเห็นว่ามีขอบเขตถั่วที่แตกต่างกันเช่น:
@RequestScoped
@ViewScoped
@FlowScoped
@SessionScoped
@ApplicationScoped
จุดประสงค์ของแต่ละคนคืออะไร? ฉันจะเลือกขอบเขตที่เหมาะสมสำหรับถั่วของฉันได้อย่างไร
ฉันสังเกตเห็นว่ามีขอบเขตถั่วที่แตกต่างกันเช่น:
@RequestScoped
@ViewScoped
@FlowScoped
@SessionScoped
@ApplicationScoped
จุดประสงค์ของแต่ละคนคืออะไร? ฉันจะเลือกขอบเขตที่เหมาะสมสำหรับถั่วของฉันได้อย่างไร
คำตอบ:
เพราะมันหมายถึงขอบเขต (อายุการใช้งาน) ของถั่ว สิ่งนี้ง่ายต่อการเข้าใจถ้าคุณคุ้นเคยกับการทำงานภายใต้ "หน้าปก" ของเว็บแอพพลิเคชัน servlet พื้นฐาน: servlets ทำงานอย่างไร instantiation เซสชันตัวแปรที่ใช้ร่วมกันและมัลติเธรด
@Request/View/Flow/Session/ApplicationScoped
@RequestScoped
ถั่วมีชีวิตอยู่ได้นานเท่าที่รอบ HTTP เดียวตอบสนองการร้องขอ (หมายเหตุว่านับคำขออาแจ็กซ์เป็นคำขอ HTTP เดียวเกินไป) @ViewScoped
ถั่วอาศัยอยู่ตราบเท่าที่คุณกำลังมีปฏิสัมพันธ์กับมุมมอง JSF เดียวกันโดย postbacks ซึ่งวิธีการดำเนินการโทรกลับnull
/ void
โดยไม่ต้องนำทางใด ๆ / เปลี่ยนเส้นทาง A @FlowScoped
bean มีอายุการใช้งานตราบเท่าที่คุณนำทางผ่านคอลเล็กชันมุมมองที่ระบุซึ่งลงทะเบียนในไฟล์การกำหนดค่าโฟลว์ @SessionScoped
ถั่วอาศัยอยู่ตราบเท่าที่เซสชั่น HTTP ที่จัดตั้งขึ้น @ApplicationScoped
ถั่วอาศัยอยู่ตราบเท่าที่โปรแกรมเว็บวิ่ง โปรดทราบว่า CDI @Model
นั้นเป็นแบบแผนสำหรับ@Named @RequestScoped
ดังนั้นจึงใช้กฎเดียวกัน
ขอบเขตการเลือกขึ้นอยู่กับข้อมูล (สถานะ) ที่เก็บและแสดงแทน ใช้@RequestScoped
สำหรับรูปแบบ / งานนำเสนอที่เรียบง่ายและไม่ใช่อาแจ็กซ์ ใช้@ViewScoped
สำหรับมุมมองแบบไดนามิกที่เปิดใช้งาน ajax (การตรวจสอบความถูกต้อง ajaxbased, การแสดงผล, ข้อความโต้ตอบ ฯลฯ ) ใช้@FlowScoped
สำหรับรูปแบบ "วิซาร์ด" ("แบบสอบถาม") ในการรวบรวมข้อมูลอินพุตที่กระจายอยู่ในหลาย ๆ หน้า ใช้@SessionScoped
สำหรับข้อมูลลูกค้าเฉพาะเช่นผู้ใช้ที่เข้าสู่ระบบและการตั้งค่าผู้ใช้ (ภาษา ฯลฯ ) ใช้@ApplicationScoped
สำหรับข้อมูล / ค่าคงที่ทั้งแอปพลิเคชันเช่นรายการแบบหล่นลงที่เหมือนกันสำหรับทุกคนหรือจัดการถั่วโดยไม่มีตัวแปรอินสแตนซ์และมีวิธีการเท่านั้น
การใช้@ApplicationScoped
ถั่วในทางที่ผิดสำหรับเซสชัน / ดู / ขอข้อมูลที่กำหนดขอบเขตจะทำให้สามารถแบ่งปันกับผู้ใช้ทั้งหมดได้ดังนั้นผู้อื่นจะเห็นข้อมูลของกันและกันซึ่งเป็นเรื่องที่ผิดธรรมดา การใช้@SessionScoped
ถั่วเพื่อดู / กำหนดขอบเขตข้อมูลจะทำให้ถูกแบ่งปันระหว่างแท็บ / หน้าต่างทั้งหมดในเซสชันเบราว์เซอร์เดียวดังนั้นผู้ใช้อาจพบความไม่สอดคล้องกันเมื่อโต้ตอบกับทุกมุมมองหลังจากสลับระหว่างแท็บที่ไม่ดีสำหรับประสบการณ์ของผู้ใช้ การใช้@RequestScoped
bean เพื่อดูข้อมูลที่กำหนดขอบเขตจะทำให้ข้อมูลที่กำหนดขอบเขตของมุมมองถูกกำหนดค่าเริ่มต้นเป็นค่าเริ่มต้นใหม่ในทุก ๆ โพสต์ (ajax) ทำให้เกิดรูปแบบที่ไม่ทำงาน ( ดูจุด 4 และ 5 ที่นี่ด้วย ) การใช้@ViewScoped
ถั่วเพื่อขอข้อมูลเซสชันหรือแอปพลิเคชันที่กำหนดขอบเขตและการใช้งานในทางที่ผิด@SessionScoped
bean สำหรับข้อมูลที่มีการกำหนดขอบเขตของแอปพลิเคชันไม่ส่งผลกระทบต่อไคลเอ็นต์ แต่จะใช้หน่วยความจำของเซิร์ฟเวอร์โดยไม่จำเป็นและไม่มีประสิทธิภาพในระดับธรรมดา
หมายเหตุว่าขอบเขตควร แต่ไม่ได้รับการแต่งตั้งขึ้นอยู่กับผลกระทบประสิทธิภาพการทำงานถ้าคุณจริงๆมีรอยหน่วยความจำต่ำและต้องการที่จะไปอย่างสมบูรณ์ไร้สัญชาติ; คุณจะต้องใช้@RequestScoped
ถั่วและซอโดยเฉพาะกับพารามิเตอร์คำขอเพื่อรักษาสถานะของลูกค้า นอกจากนี้โปรดทราบว่าเมื่อคุณมีเพจ JSF หน้าเดียวที่มีข้อมูลที่กำหนดขอบเขตแตกต่างกันดังนั้นจึงเป็นการดีที่จะใส่ไว้ในแบ็คอัพสำรองในขอบเขตที่ตรงกับขอบเขตของข้อมูล beans สามารถเข้าถึงซึ่งกันและกันผ่านทาง@ManagedProperty
ในกรณีของ beans ที่มีการจัดการ JSF หรือ@Inject
ในกรณีของ beans ที่มีการจัดการ CDI
@CustomScoped/NoneScoped/Dependent
มันไม่ได้กล่าวถึงในคำถามของคุณ แต่ (ดั้งเดิม) JSF ยังสนับสนุน@CustomScoped
และ@NoneScoped
ซึ่งไม่ค่อยได้ใช้ในโลกแห่งความเป็นจริง @CustomScoped
ต้องอ้างอิงที่กำหนดเองMap<K, Bean>
การดำเนินการในบางขอบเขตที่กว้างซึ่งมีแทนที่Map#put()
และ / หรือMap#get()
เพื่อให้มีการควบคุมที่ดีเม็ดเล็กที่มากกว่าการสร้างถั่วและ / หรือทำลาย
JSF @NoneScoped
และ CDI @Dependent
นั้นโดยทั่วไปแล้วจะมีชีวิตอยู่ตราบใดที่การประเมินค่า EL เดียวในถั่ว ลองนึกภาพรูปแบบการเข้าสู่ระบบที่มีช่องป้อนข้อมูลสองช่องที่อ้างถึงคุณสมบัติ bean และปุ่มคำสั่งที่อ้างถึงการกระทำ bean ดังนั้นด้วยนิพจน์ EL ทั้งหมดสามนิพจน์จากนั้นจะสร้างสามอินสแตนซ์ที่มีประสิทธิภาพ หนึ่งชุดพร้อมชื่อผู้ใช้หนึ่งชุดพร้อมรหัสผ่านและอีกหนึ่งชุดที่เรียกใช้การกระทำ โดยปกติคุณต้องการใช้ขอบเขตนี้เฉพาะในถั่วที่ควรมีชีวิตอยู่ตราบใดที่มีการฉีด ดังนั้นหาก a @NoneScoped
หรือ@Dependent
ถูกฉีดเข้าไปใน a @SessionScoped
มันจะมีชีวิตอยู่ตราบเท่าที่@SessionScoped
ถั่ว
ในที่สุด JSF ยังรองรับขอบเขตแฟลช มีการสำรองข้อมูลโดยคุกกี้อายุการใช้งานสั้น ๆ ซึ่งเชื่อมโยงกับการป้อนข้อมูลในขอบเขตเซสชัน ก่อนการเปลี่ยนเส้นทางคุกกี้จะถูกตั้งค่าในการตอบสนอง HTTP ด้วยค่าที่เกี่ยวข้องกับการป้อนข้อมูลในขอบเขตเซสชันโดยเฉพาะ หลังจากเปลี่ยนเส้นทางจะมีการตรวจสอบคุกกี้ขอบเขตแฟลชที่มีอยู่และรายการข้อมูลที่เกี่ยวข้องกับคุกกี้จะถูกลบออกจากขอบเขตเซสชันและใส่ไว้ในขอบเขตคำขอของคำขอเปลี่ยนเส้นทาง ในที่สุดคุกกี้จะถูกลบออกจากการตอบกลับ HTTP วิธีนี้คำขอที่เปลี่ยนเส้นทางมีการเข้าถึงเพื่อขอข้อมูลที่กำหนดขอบเขตซึ่งจัดทำขึ้นในคำขอเริ่มต้น
นี่ไม่สามารถใช้เป็นขอบเขตของถั่วที่ถูกจัดการได้นั่นคือไม่มีสิ่ง@FlashScoped
นั้น ขอบเขตแฟลชใช้ได้เฉพาะในแผนที่ผ่านExternalContext#getFlash()
ในถั่วที่ได้รับการจัดการและ#{flash}
ใน EL
@FlowScoped
(ไม่จำเป็นต้องเริ่ม / หยุดด้วยตนเอง)
ViewAccesscoped
และWindowScoped
ViewScoped
bean ใน MyFaces 2.2 ฉันกำลังเผชิญปัญหากับViewScoped
ถั่วและอาแจ็กซ์ซึ่งผมได้โพสต์ที่นี่ ใน MyFaces JIRA ยังมีการอภิปรายในหัวข้อนี้
@RequestScoped
@SessionScoped
@ApplicationScoped
@ConversationScoped
ทำไมขอบเขตที่คุณอธิบายแตกต่างกันอย่างไร
ตั้งแต่ JSF 2.3 ขอบเขต bean ทั้งหมดที่กำหนดในแพ็กjavax.faces.bean
เกจได้ถูกคัดค้านเพื่อจัดตำแหน่งขอบเขตกับ CDI นอกจากนี้ยังสามารถใช้งานได้ก็ต่อเมื่อถั่วของคุณกำลังใช้@ManagedBean
คำอธิบายประกอบ หากคุณกำลังใช้เวอร์ชัน JSF ด้านล่าง 2.3 อ้างอิงถึงคำตอบเดิมในตอนท้าย
จาก JSF 2.3 นี่คือขอบเขตที่สามารถใช้กับ JSF Backing Beans:
1.@javax.enterprise.context.ApplicationScoped
: ขอบเขตแอปพลิเคชันยังคงมีอยู่ตลอดระยะเวลาของแอปพลิเคชันเว็บ ขอบเขตนั้นจะถูกใช้ร่วมกันระหว่างคำขอทั้งหมดและเซสชันทั้งหมด สิ่งนี้มีประโยชน์เมื่อคุณมีข้อมูลสำหรับทั้งแอปพลิเคชัน
2.@javax.enterprise.context.SessionScoped
: ขอบเขตเซสชันยังคงอยู่นับจากเวลาที่มีการสร้างเซสชันจนกว่าการยกเลิกเซสชันจะเกิดขึ้น บริบทเซสชันถูกแชร์ระหว่างคำขอทั้งหมดที่เกิดขึ้นในเซสชัน HTTP เดียวกัน สิ่งนี้มีประโยชน์เมื่อคุณไม่บันทึกข้อมูลสำหรับไคลเอนต์ที่เฉพาะเจาะจงสำหรับเซสชันที่เฉพาะเจาะจง
3.@javax.enterprise.context.ConversationScoped
: ขอบเขตการสนทนายังคงอยู่ในลักษณะล็อกขณะที่ bean ยังมีชีวิตอยู่ ขอบเขตมี 2 วิธี: และConversation.begin()
Conversation.end()
วิธีการเหล่านี้ควรเรียกอย่างชัดเจนไม่ว่าจะเริ่มต้นหรือจบชีวิตของถั่ว
4.@javax.enterprise.context.RequestScoped
: ขอบเขตของคำขอมีอายุสั้น มันเริ่มต้นเมื่อมีการส่งคำขอ HTTP และสิ้นสุดลงหลังจากการตอบกลับถูกส่งกลับไปยังลูกค้า หากคุณวางถั่วที่ได้รับการจัดการลงในขอบเขตคำขออินสแตนซ์ใหม่จะถูกสร้างขึ้นพร้อมกับคำขอแต่ละรายการ ควรพิจารณาขอบเขตคำขอหากคุณมีความกังวลเกี่ยวกับต้นทุนของการจัดเก็บขอบเขตเซสชัน
5.@javax.faces.flow.FlowScoped
: ขอบเขตการไหลยังคงอยู่ตราบใดที่ Flow ยังมีชีวิตอยู่ การไหลอาจถูกกำหนดให้เป็นชุดของหน้า (หรือมุมมอง) ที่มีหน่วยงาน การกำหนดขอบเขตของโฟลว์นั้นใช้งานได้ตราบใดที่ผู้ใช้นำทางด้วยในโฟลว์
6.@javax.faces.view.ViewScoped
: bean ในขอบเขตการดูยังคงอยู่ในขณะที่หน้า JSF เดียวกันแสดงขึ้นมาใหม่ ทันทีที่ผู้ใช้นำทางไปยังหน้าอื่น bean ออกนอกขอบเขต
คำตอบเดิมต่อไปนี้ใช้เวอร์ชัน JSF ก่อน 2.3
ตั้งแต่ JSF 2.x มีขอบเขต 4 Bean:
- @SessionScoped
- @RequestScoped
- @ApplicationScoped
- @ViewScoped
ขอบเขตเซสชัน: ขอบเขตเซสชันยังคงอยู่จากเวลาที่มีการสร้างเซสชันจนกว่าจะสิ้นสุดเซสชัน เซสชันสิ้นสุดลงหากเว็บแอปพลิเคชันเรียกใช้วิธีการที่ไม่ถูกต้องบนวัตถุ HttpSession หรือถ้าหมดเวลา
RequestScope: ขอบเขตการร้องขอมีอายุสั้น มันเริ่มต้นเมื่อมีการส่งคำขอ HTTP และสิ้นสุดลงหลังจากการตอบกลับถูกส่งกลับไปยังลูกค้า หากคุณวางถั่วที่ได้รับการจัดการลงในขอบเขตคำขออินสแตนซ์ใหม่จะถูกสร้างขึ้นพร้อมกับคำขอแต่ละรายการ ควรพิจารณาขอบเขตคำขอหากคุณมีความกังวลเกี่ยวกับต้นทุนของการจัดเก็บขอบเขตเซสชัน
ApplicationScope: ขอบเขตแอปพลิเคชันยังคงมีอยู่ตลอดระยะเวลาของเว็บแอปพลิเคชัน ขอบเขตนั้นจะถูกใช้ร่วมกันระหว่างคำขอทั้งหมดและเซสชันทั้งหมด คุณวางถั่วที่ได้รับการจัดการลงในขอบเขตของแอปพลิเคชันถ้าถั่วเดียวควรถูกใช้ร่วมกันระหว่างอินสแตนซ์ทั้งหมดของเว็บแอปพลิเคชัน bean ถูกสร้างขึ้นเมื่อถูกร้องขอโดยผู้ใช้แอปพลิเคชันเป็นครั้งแรกและจะยังคงอยู่จนกว่าเว็บแอปพลิเคชันจะถูกลบออกจากแอปพลิเคชันเซิร์ฟเวอร์
ViewScope: เพิ่มขอบเขตการดูใน JSF 2.0 bean ในมุมมองยังคงอยู่ในขณะที่หน้า JSF เดียวกันแสดงขึ้นมาใหม่ (ข้อมูลจำเพาะ JSF ใช้มุมมองคำสำหรับหน้า JSF) ทันทีที่ผู้ใช้นำทางไปยังหน้าอื่น Bean จะออกจากขอบเขต
เลือกขอบเขตที่คุณต้องการ
ที่มา: Core Java Server Faces รุ่นที่ 3โดย David Geary & Cay Horstmann [หมายเลขหน้า] 51 - 54]
invalidate()
วิธีการหรือวิธีที่ไม่ถูกต้องหรือไม่
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
การถูกเรียกใช้ใน "logout bean" ของคุณคือสิ่งที่เขาหมายถึง