Saya akan melalui tutorial Java EE 6 dan saya mencoba memahami perbedaan antara kacang sesi stateless dan stateful. Jika kacang sesi stateless tidak mempertahankan statusnya di antara pemanggilan metode, mengapa program saya bertindak seperti itu?
package mybeans;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@LocalBean
@Stateless
public class MyBean {
private int number = 0;
public int getNumber() {
return number;
}
public void increment() {
this.number++;
}
}
Klien
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;
import mybeans.MyBean;
import java.io.PrintWriter;
@WebServlet(name = "ServletClient", urlPatterns = { "/ServletClient" })
public class ServletClient extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
MyBean mybean;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
mybean.increment();
out.println(mybean.getNumber());
}
}
Saya mengharapkan getNumber untuk mengembalikan 0 setiap kali tetapi mengembalikan 1 dan memuat ulang servlet di browser saya meningkatkannya lebih banyak. Masalahnya adalah dengan pemahaman saya tentang bagaimana kacang sesi stateless bekerja dan bukan dengan perpustakaan atau server aplikasi, tentu saja. Dapatkah seseorang memberi saya contoh tipe hello world sederhana dari kacang sesi stateless yang berperilaku berbeda ketika Anda mengubahnya menjadi stateful?
java
jakarta-ee
ejb
ejb-3.1
stateful-session-bean
Stanley kelly
sumber
sumber
Jawaban:
Perbedaan penting bukanlah variabel anggota pribadi, tetapi status pengaitan dengan pengguna tertentu (pikirkan "keranjang belanja").
Potongan stateful session bean seperti sesi di servlet. Kacang sesi yang stateful memungkinkan aplikasi Anda untuk tetap memiliki sesi tersebut meskipun tidak ada klien web. Saat server aplikasi mengambil kacang sesi stateless dari kumpulan objek, ia tahu bahwa itu bisa digunakan untuk memenuhi permintaan APA PUN, karena tidak terkait dengan pengguna tertentu.
Kacang sesi stateful harus dibagikan kepada pengguna yang mendapatkannya di tempat pertama, karena info keranjang belanja mereka harus diketahui hanya oleh mereka. Server aplikasi memastikan demikian. Bayangkan betapa populernya aplikasi Anda jika Anda dapat mulai berbelanja dan kemudian server aplikasi memberikan kacang sesi stateful Anda kepada saya ketika saya datang!
Jadi anggota data pribadi Anda memang "negara bagian", tetapi bukan "keranjang belanja". Coba ulangi contoh Anda (sangat bagus) untuk membuatnya sehingga variabel yang ditambahkan dikaitkan dengan pengguna tertentu. Tingkatkan, buat pengguna baru, dan lihat apakah mereka masih dapat melihat nilai yang ditambahkan. Jika dilakukan dengan benar, setiap pengguna hanya akan melihat versi penghitung mereka.
sumber
Stateless Session Beans (SLSB) tidak terikat pada satu klien dan tidak ada jaminan bagi satu klien untuk mendapatkan instans yang sama dengan setiap pemanggilan metode (beberapa kontainer dapat membuat dan menghancurkan kacang dengan setiap sesi pemanggilan metode, ini adalah keputusan khusus implementasi , tetapi contoh biasanya dikumpulkan - dan saya tidak menyebutkan lingkungan berkerumun). Dengan kata lain, meskipun kacang stateless mungkin memiliki variabel instance, kolom ini tidak spesifik untuk satu klien, jadi jangan mengandalkannya di antara panggilan jarak jauh.
Sebaliknya, Stateful Session Beans (SFSB) didedikasikan untuk satu klien seumur hidup mereka, tidak ada pertukaran atau penggabungan contoh (mungkin dikeluarkan dari memori setelah pasif untuk menghemat sumber daya tetapi itu cerita lain) dan mempertahankan status percakapan . Ini berarti bahwa variabel instan kacang dapat menyimpan data relatif terhadap klien di antara pemanggilan metode. Dan ini memungkinkan untuk memiliki panggilan metode yang saling bergantung (perubahan yang dibuat oleh satu metode memengaruhi panggilan metode selanjutnya). Proses multi-langkah (proses pendaftaran, keranjang belanja, proses pemesanan ...) adalah kasus penggunaan khas untuk SFSB.
Satu hal lagi. Jika Anda menggunakan SFSB, Anda harus menghindari menyuntikkannya ke dalam kelas yang bersifat multithread, seperti Servlets dan kacang yang dikelola JSF (Anda tidak ingin itu dibagikan oleh semua klien). Jika Anda ingin menggunakan SFSB dalam aplikasi web Anda, maka Anda perlu melakukan pencarian JNDI dan menyimpan instance EJB yang dikembalikan dalam
HttpSession
objek untuk aktivitas di masa mendatang. Sesuatu seperti itu:try { InitialContext ctx = new InitialContext(); myStateful = (MyStateful)ctx.lookup("java:comp/env/MyStatefulBean"); session.setAttribute("my_stateful", myStateful); } catch (Exception e) { // exception handling }
sumber
Stateless dan stateful dalam konteks ini tidak berarti seperti yang Anda harapkan.
Statefulness dengan EJB mengacu pada apa yang saya sebut keadaan percakapan . Contoh klasiknya adalah pemesanan penerbangan. Jika terdiri dari tiga langkah:
Bayangkan masing-masing adalah panggilan metode ke kacang sesi. Kacang sesi yang stateful dapat mempertahankan jenis percakapan ini sehingga dapat mengingat apa yang terjadi di antara panggilan.
Kacang sesi tanpa negara tidak memiliki kapasitas seperti itu untuk keadaan percakapan.
Variabel global di dalam kacang sesi (stateless atau stateful) adalah sesuatu yang sama sekali berbeda. Kacang sesi stateful akan memiliki kumpulan kacang yang dibuat (karena kacang hanya dapat digunakan dalam satu percakapan pada satu waktu) sedangkan kacang sesion stateless seringkali hanya memiliki satu contoh, yang akan membuat variabel global berfungsi, tetapi saya tidak berpikir ini tentu dijamin.
sumber
Pertanyaan bagus,
coba kode ini (ubah MyBean Stateful / Stateless.):
import javax.ejb.LocalBean; import javax.ejb.Stateful; import javax.ejb.Stateless; @LocalBean @Stateless public class MyBean { private int number = 0; public int getNumber() { return number; } public void increment() { this.number++; } }
Servlet_1
import java.io.IOException; import javax.ejb.EJB; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.WebServlet; import java.io.PrintWriter; @WebServlet(name = "ServletClient", urlPatterns = { "/ServletClient" }) public class ServletClient extends HttpServlet { private static final long serialVersionUID = 1L; @EJB MyBean mybean; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); mybean.increment(); out.println(mybean.getNumber()); } }
Servlet_2
import java.io.IOException; import javax.ejb.EJB; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.WebServlet; import java.io.PrintWriter; @WebServlet(name = "NewServletClient", urlPatterns = { "/NewServletClient" }) public class NewServletClient extends HttpServlet { private static final long serialVersionUID = 1L; @EJB MyBean mybean; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); mybean.increment(); out.println(mybean.getNumber()); } }
kasus: MyBean - @ Stateless
http: // localhost: 8080 / MYServletDemo / ServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
2
http: // localhost: 8080 / MYServletDemo_war_exploded / newServletClient
3
http: // localhost: 8080 / MYServletDemo / ServletClient
4
kasus: MyBean - @ Stateful
http: // localhost: 8080 / MYServletDemo / ServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
2
http: // localhost: 8080 / MYServletDemo / newServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
3
sumber
Utama perbedaan antara dua jenis utama dari kacang sesi adalah:
Kacang Tanpa Negara
Kacang Stateful
sumber
Hal ini terjadi karena container hanya memiliki satu instance bean di pool yang digunakan kembali untuk semua panggilan. Jika Anda menjalankan klien secara paralel, Anda akan melihat hasil yang berbeda karena wadah akan membuat lebih banyak instance kacang di kumpulan.
sumber
Jawabannya bagus. Saya ingin menambahkan jawaban kecil. Stateless Bean tidak boleh digunakan untuk menyimpan data klien apa pun. Ini harus digunakan untuk "memodelkan tindakan atau proses yang dapat dilakukan dalam satu kesempatan".
sumber