Bagaimana memilih lingkup kacang yang tepat?

Jawaban:

485

pengantar

Ini mewakili ruang lingkup (masa hidup) kacang. Ini lebih mudah untuk dipahami jika Anda terbiasa dengan "di bawah penutup" bekerja dari aplikasi web servlet dasar: Bagaimana cara kerja servlets? Instansiasi, sesi, variabel bersama, dan multithreading .


@Request/View/Flow/Session/ApplicationScoped

Sebuah @RequestScopedkacang hidup selama siklus permintaan-respon tunggal HTTP (catatan bahwa Ajax permintaan dianggap sebagai satu permintaan HTTP juga). Sebuah @ViewScopedkacang hidup selama Anda berinteraksi dengan pandangan JSF yang sama oleh postbacks yang metode tindakan panggilan kembali null/ voidtanpa navigasi / redirect. Sebuah @FlowScopedkacang hidup selama Anda menavigasi melalui koleksi tertentu dari pandangan terdaftar di file konfigurasi aliran. Sebuah @SessionScopedkacang hidup selama sesi HTTP didirikan. Sebuah @ApplicationScopedkacang hidup selama berjalan aplikasi web. Perhatikan bahwa CDI @Modelpada dasarnya adalah stereotip untuk @Named @RequestScoped, jadi aturan yang sama berlaku.

Cakupan mana yang dipilih hanya bergantung pada data (negara bagian) yang dipegang dan diwakili kacang. Gunakan @RequestScopeduntuk bentuk / presentasi sederhana dan non-ajax. Gunakan @ViewScopeduntuk tampilan dinamis yang kaya ajax (validasi ajax, rendering, dialog, dll). Gunakan @FlowScopeduntuk pola "penyihir" ("kuesioner") untuk mengumpulkan data input yang tersebar di beberapa halaman. Gunakan @SessionScopeduntuk data spesifik klien, seperti pengguna yang masuk dan preferensi pengguna (bahasa, dll.) Gunakan @ApplicationScopeduntuk aplikasi luas data / konstanta, seperti daftar dropdown yang sama untuk semua orang, atau kacang yang dikelola tanpa variabel instan dan hanya memiliki metode.

Menyalahgunakan @ApplicationScopedkacang untuk data cakupan / sesi / tampilan / permintaan akan membuatnya untuk dibagikan di antara semua pengguna, sehingga orang lain dapat melihat data masing-masing yang jelas-jelas salah. Menyalahgunakan @SessionScopedkacang untuk melihat / meminta data cakupan akan membuatnya untuk dibagikan di antara semua tab / jendela dalam satu sesi browser, sehingga pengguna akhir dapat mengalami ketidakkonsistenan saat berinteraksi dengan setiap tampilan setelah beralih di antara tab yang buruk untuk pengalaman pengguna. Menyalahgunakan @RequestScopedkacang untuk melihat data cakupan akan membuat tampilan data cakupan untuk diinisialisasi ulang ke default pada setiap postback tunggal (ajax), menyebabkan kemungkinan bentuk tidak berfungsi ( lihat juga poin 4 dan 5 di sini ). Menyalahgunakan @ViewScopedkacang untuk permintaan, sesi atau data cakupan aplikasi, dan menyalahgunakan a@SessionScoped kacang untuk data cakupan aplikasi tidak mempengaruhi klien, tetapi tidak perlu menempati memori server dan jelas tidak efisien.

Perhatikan bahwa ruang lingkup sebaiknya tidak dipilih berdasarkan implikasi kinerja, kecuali jika Anda benar - benar memiliki jejak memori yang rendah dan ingin menjadi benar-benar tanpa kewarganegaraan; Anda harus menggunakan @RequestScopedkacang dan biola secara eksklusif dengan parameter permintaan untuk mempertahankan status klien. Perhatikan juga bahwa ketika Anda memiliki halaman JSF tunggal dengan data cakupan yang berbeda, maka sangat sah untuk menempatkannya di kacang latar terpisah dalam ruang lingkup yang cocok dengan ruang lingkup data. Kacang hanya dapat mengakses satu sama lain @ManagedPropertydalam kasus kacang dikelola JSF atau @Injectdalam kasus kacang dikelola CDI.

Lihat juga:


@CustomScoped/NoneScoped/Dependent

Ini tidak disebutkan dalam pertanyaan Anda, tetapi (warisan) JSF juga mendukung @CustomScopeddan @NoneScoped, yang jarang digunakan di dunia nyata. Mereka @CustomScopedharus merujuk Map<K, Bean>implementasi kustom dalam beberapa lingkup yang lebih luas yang telah menimpa Map#put()dan / atau Map#get()untuk memiliki kontrol yang lebih baik atas pembuatan dan / atau penghancuran kacang.

JSF @NoneScopeddan CDI @Dependentpada dasarnya hidup selama EL-evaluasi tunggal pada kacang. Bayangkan formulir login dengan dua bidang input yang merujuk ke properti kacang dan tombol perintah yang merujuk pada tindakan kacang, sehingga dengan total tiga ekspresi EL, maka secara efektif tiga instance akan dibuat. Satu dengan set nama pengguna, satu dengan set kata sandi dan satu di mana tindakan dipanggil. Anda biasanya ingin menggunakan ruang lingkup ini hanya pada kacang yang harus hidup selama kacang disuntikkan. Jadi jika a @NoneScopedatau @Dependentdisuntikkan dalam @SessionScoped, maka itu akan hidup selama @SessionScopedkacang.

Lihat juga:


Lingkup flash

Seperti yang terakhir, JSF juga mendukung lingkup flash. Itu didukung oleh cookie hidup pendek yang terkait dengan entri data dalam cakupan sesi. Sebelum pengalihan, cookie akan ditetapkan pada respons HTTP dengan nilai yang secara unik terkait dengan entri data dalam cakupan sesi. Setelah pengalihan, keberadaan cookie lingkup flash akan diperiksa dan entri data yang terkait dengan cookie akan dihapus dari cakupan sesi dan dimasukkan ke dalam lingkup permintaan permintaan yang diarahkan. Akhirnya cookie akan dihapus dari respons HTTP. Dengan cara ini permintaan yang dialihkan memiliki akses untuk meminta data cakupan yang telah disiapkan dalam permintaan awal.

Ini sebenarnya tidak tersedia sebagai ruang lingkup kacang dikelola, yaitu tidak ada hal seperti itu @FlashScoped. Cakupan flash hanya tersedia sebagai peta melalui ExternalContext#getFlash()kacang yang dikelola dan #{flash}EL.

Lihat juga:

BalusC
sumber
4
Saya pikir referensi untuk jawaban Anda untuk pertanyaan " Bagaimana dan kapan kacang lingkup tampilan hancur di JSF? " Relevan di sini.
Lii
3
@ Dingin: itu lingkup CDI lama dan di JSF 2.2 diganti dengan @FlowScoped(tidak perlu secara manual memulai / menghentikannya).
BalusC
1
Dan DeltaSpike juga memiliki ViewAccesscopeddanWindowScoped
Kukeltje
@ BalusC, saya pikir ada masalah, dengan ViewScopedkacang di MyFaces 2.2. Saat ini saya menghadapi masalah dengan ViewScopedkacang dan Ajax, yang telah saya posting di sini . Di MyFaces JIRA, ada juga diskusi tentang topik ini.
Tapas Bose
CDI mendefinisikan empat cakupan bawaan: @RequestScoped @SessionScoped @ApplicationScoped @ConversationScoped mengapa cakupan yang Anda gambarkan berbeda?
Hosein Aqajani
122

Karena JSF 2.3 semua cakupan bean yang didefinisikan dalam paket javax.faces.beanpaket telah ditinggalkan untuk menyelaraskan cakupan dengan CDI. Selain itu mereka hanya berlaku jika kacang Anda menggunakan @ManagedBeananotasi. Jika Anda menggunakan versi JSF di bawah 2.3, lihat jawaban lawas di bagian akhir.


Dari JSF 2.3 berikut ini adalah cakupan yang dapat digunakan pada JSF Backing Beans:

1@javax.enterprise.context.ApplicationScoped .: Cakupan aplikasi berlanjut selama seluruh durasi aplikasi web. Cakupan itu dibagi di antara semua permintaan dan semua sesi. Ini berguna ketika Anda memiliki data untuk seluruh aplikasi.

2@javax.enterprise.context.SessionScoped .: Cakupan sesi berlanjut dari saat sesi ditetapkan hingga sesi dihentikan. Konteks sesi dibagi antara semua permintaan yang terjadi dalam sesi HTTP yang sama. Ini berguna ketika Anda tidak ingin menyimpan data untuk klien tertentu untuk sesi tertentu.

3@javax.enterprise.context.ConversationScoped .: Ruang lingkup percakapan tetap sebagai log seperti kacang hidup. Ruang lingkup menyediakan 2 metode: Conversation.begin()dan Conversation.end(). Metode-metode ini harus disebut secara eksplisit, baik untuk memulai atau mengakhiri kehidupan kacang.

4@javax.enterprise.context.RequestScoped .: Ruang lingkup permintaan berumur pendek. Itu dimulai ketika permintaan HTTP diajukan dan berakhir setelah respons dikirim kembali ke klien. Jika Anda menempatkan kacang yang dikelola ke dalam ruang lingkup permintaan, instance baru dibuat dengan setiap permintaan. Sebaiknya pertimbangkan cakupan permintaan jika Anda khawatir tentang biaya penyimpanan lingkup sesi.

5@javax.faces.flow.FlowScoped .: Lingkup Flow tetap ada selama Flow hidup. Alur dapat didefinisikan sebagai kumpulan halaman (atau tampilan) yang terkandung yang mendefinisikan unit kerja. Flow scoped telah aktif selama pengguna menavigasi dalam Flow.

6@javax.faces.view.ViewScoped .: Kacang dalam lingkup tampilan tetap ada sementara halaman JSF yang sama ditampilkan ulang. Segera setelah pengguna menavigasi ke halaman yang berbeda, kacang keluar dari ruang lingkup.


Jawaban warisan berikut berlaku versi JSF sebelum 2.3

Pada JSF 2.x ada 4 Bean Scopes:

  • @SessionScoped
  • @RequestScoped
  • @ApplicationScoped
  • @ViewScoped

Ruang Lingkup Sesi: Lingkup sesi tetap ada sejak saat sesi ditetapkan hingga sesi berakhir. Sesi berakhir jika aplikasi web memanggil metode tidak valid pada objek HttpSession, atau jika waktu habis.

RequestScope: Ruang lingkup permintaan berumur pendek. Itu dimulai ketika permintaan HTTP diajukan dan berakhir setelah respons dikirim kembali ke klien. Jika Anda menempatkan kacang yang dikelola ke dalam ruang lingkup permintaan, instance baru dibuat dengan setiap permintaan. Sebaiknya pertimbangkan cakupan permintaan jika Anda khawatir tentang biaya penyimpanan lingkup sesi.

ApplicationScope: Lingkup aplikasi bertahan selama durasi aplikasi web. Cakupan itu dibagi di antara semua permintaan dan semua sesi. Anda menempatkan kacang yang dikelola ke dalam ruang lingkup aplikasi jika satu kacang harus dibagikan di antara semua contoh aplikasi web. Kacang dibuat ketika pertama kali diminta oleh pengguna aplikasi, dan tetap hidup sampai aplikasi web dihapus dari server aplikasi.

ViewScope: View scope ditambahkan di JSF 2.0. Kacang dalam lingkup tampilan tetap ada sementara halaman JSF yang sama ditampilkan ulang. (Spesifikasi JSF menggunakan tampilan istilah untuk halaman JSF.) Segera setelah pengguna menavigasi ke halaman yang berbeda, kacang keluar dari ruang lingkup.

Pilih ruang lingkup Anda berdasarkan kebutuhan Anda.

Sumber: Core Java Server Faces 3rd Edition oleh David Geary & Cay Horstmann [Halaman no. 51 - 54] masukkan deskripsi gambar di sini

Kishor Prakash
sumber
Bisakah Anda menjelaskan, apa yang Anda maksud dengan "metode tidak valid pada objek HttpSession": invalidate()metode, atau metode tidak valid?
Alexander Pozdneev
1
Agak tua dan mungkin terlambat untuk menjawab, tetapi untuk memperjelasnya: FacesContext.getCurrentInstance().getExternalContext().invalidateSession();dipanggil dalam "kacang logout" Anda adalah apa yang ia maksudkan.
Roland
1
itu menjadi jawaban warisan, saat ini ada 8 lingkup
Ewoks
@KishorPrakash: sebentar sekarang 6 bulan lalu. ;-)
Kukeltje
@Kelteltje: Maaf, saya ada di sana.
Kishor Prakash