Vatansız ve Durum Bilgili Kurumsal Java Fasulyeleri


94

Java EE 6 öğreticisinden geçiyorum ve durum bilgisi olmayan ve durum bilgisi olan oturum çekirdekleri arasındaki farkı anlamaya çalışıyorum. Durum bilgisi olmayan oturum çekirdekleri durumlarını yöntem çağrıları arasında korumuyorsa, programım neden olduğu gibi davranıyor?

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++;
    }
}

Müşteri

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());
    }

}

GetNumber'ın her seferinde 0 döndürmesini bekliyordum, ancak 1 döndürüyor ve tarayıcımdaki sunucu uygulamasının yeniden yüklenmesi bunu daha da artırıyor. Sorun, elbette kütüphaneler veya uygulama sunucusuyla değil, durumsuz oturum çekirdeklerinin nasıl çalıştığını anlamamla ilgili. Biri bana, durum bilgisine sahip olarak değiştirdiğinizde farklı şekilde davranan bir vatansız oturum fasulyesinin merhaba dünya tipi basit bir örneğini verebilir mi?


6
İlgili: stackoverflow.com/questions/8887140/… Bu yanıtın anlaşılması daha basit olabilir. Sunucu uygulamalarının temelde uygulama kapsamlı olduğunu unutmayın (tüm HTTP isteklerinde / oturumlarında paylaşılan / yeniden kullanılan uygulama genelinde yalnızca 1 sunucu uygulaması vardır.
BalusC

merhaba, ilk artışı yaparsınız ve sonra değeri alırsınız .... bu yüzden 0 değerini bekleyemezsiniz.
rzur2004

Bunu sorduğun için sana teşekkür etmek istiyorum, şu anda sorunumu çözüyor. Bunu daha iyi
soramazdım

Yanıtlar:


94

Önemli fark, özel üye değişkenleri değil, durumu belirli bir kullanıcıyla ilişkilendirmektir ("alışveriş sepeti" ni düşünün).

Durum bilgisi olan oturum çekirdeği, sunucu uygulamalardaki oturum gibidir. Durum bilgili oturum çekirdekleri, bir web istemcisi olmasa bile uygulamanızın o oturuma sahip olmasına izin verir. Uygulama sunucusu nesne havuzundan durum bilgisi olmayan bir oturum çekirdeği aldığında, belirli bir kullanıcıyla ilişkili olmadığı için HERHANGİ bir isteği karşılamak için kullanılabileceğini bilir.

Durum bilgisi olan bir oturum çekirdeği, onu ilk alan kullanıcıya dağıtılmalıdır, çünkü alışveriş sepeti bilgileri yalnızca onlar tarafından bilinmelidir. Uygulama sunucusu bunun böyle olmasını sağlar. Alışverişe başlayabilirseniz uygulamanızın ne kadar popüler olacağını bir düşünün ve sonra uygulama sunucusu, ben geldiğimde bana durum bilgisi olan oturum fasulyesini verdi!

Yani özel veri üyeniz gerçekten "eyalet" tir, ancak "alışveriş sepeti" değildir. Arttırılmış değişkenin belirli bir kullanıcıyla ilişkilendirilmesi için (çok iyi) örneğinizi yeniden yapmaya çalışın. Arttırın, yeni bir kullanıcı oluşturun ve artan değeri hala görebileceklerine bakın. Doğru yapılırsa, her kullanıcı yalnızca kendi sayaç sürümünü görmelidir.


Bir yorumda açık bir cevap verebilir misiniz? Bu örnekteki vatansız fasulye neden her zaman değeri elinde tutuyor ve her seferinde artırıyor? Tek bir kullanıcı olduğu için mi?
arjacsoh

2
Sayaç, kullanıcı sayısına bakılmaksızın artacaktır. Dolayısıyla, kullanıcı1 gelir ve sayacı 1'e yükseltirse ve aynı anda kullanıcı2 gelir ve onu artırırsa, değer 2 olacaktır. Aslında, kullanıcı1'in 1'e sahip olduğunu ve kullanıcı2'nin 1'e sahip olduğunu göstermelidir (eğer niyetiniz buysa. Alışveriş sepeti yukarıdaki gibi örnek).
Krishna

138

Stateless Session Beans (SLSB) tek bir istemciye bağlı değildir ve bir istemcinin her yöntem çağrısıyla aynı örneği almasının garantisi yoktur (bazı kapsayıcılar her yöntem çağırma oturumunda çekirdekleri oluşturabilir ve yok edebilir, bu uygulamaya özgü bir karardır. , ancak örnekler genellikle havuzda toplanır - ve kümelenmiş ortamlardan bahsetmiyorum). Diğer bir deyişle, durum bilgisi olmayan fasulye örneklerinin örnek değişkenleri olabilir, ancak bu alanlar tek bir istemciye özel değildir, bu nedenle uzak aramalar arasında bunlara güvenmeyin.

Buna karşılık, Durum Bilgili Oturum Fasulyeleri (SFSB) tüm yaşamları boyunca bir müşteriye adanmıştır , örneklerin değiştirilmesi veya havuzlanması yoktur (kaynakları korumak için pasifleştirmeden sonra bellekten çıkarılabilir, ancak bu başka bir hikaye) ve konuşma durumunu sürdürür . Bu, bean'in örnek değişkenlerinin, yöntem çağrıları arasında istemciye göre verileri tutabileceği anlamına gelir. Ve bu, birbirine bağlı yöntem çağrılarına sahip olmayı mümkün kılar (bir yöntem tarafından yapılan değişiklikler sonraki yöntem çağrılarını etkiler). Çok adımlı süreçler (bir kayıt işlemi, alışveriş sepeti, rezervasyon süreci ...) SFSB için tipik kullanım durumlarıdır.

Bir şey daha. SFSB kullanıyorsanız, bunları Servletler ve JSF tarafından yönetilen fasulye gibi doğası gereği çok iş parçacıklı sınıflara enjekte etmekten kaçınmalısınız (tüm istemciler tarafından paylaşılmasını istemezsiniz). Web uygulamanızda SFSB kullanmak istiyorsanız, bir JNDI araması yapmanız ve döndürülen EJB örneğini HttpSessiongelecekteki etkinlik için nesnede depolamanız gerekir . Bunun gibi bir şey:

try {
    InitialContext ctx = new InitialContext();
    myStateful = (MyStateful)ctx.lookup("java:comp/env/MyStatefulBean");
    session.setAttribute("my_stateful", myStateful);
} catch (Exception e) {
    // exception handling
}

Açıklık için teşekkürler. İstemci için bağımsız bir komut satırı programı kullandığımda, farkı görmek çok açık.
Stanley Kelly

yorumlarınız için teşekkürler, daha aydınlatıcılar. Önce soyut tanımı verin, ardından her durum için bazı kullanım durumlarını belirtin ve ardından bazı tuzaklara dikkat edin. Harika +1
arthur

Enjeksiyondan kaçınma kısmı EJB 3.1 için de çıkıyor mu?
jacktrades

7
@Pascal "Stateful Session Beans (SFSB) tüm yaşamları boyunca bir istemciye adanmışsa", yani bu yetenek SFSB'de oluşturulmuşsa, o zaman neden onları HttpSession nesnesinde depolamalısınız?
user1169587

2
Zaten 'oturum açmışsa' neden oturumda durum bilgili fasulye tutmaya ihtiyacımız var? Bu şekilde her nesneyi oturum açabiliriz. Pls açıklayın
Georgy Gobozov

18

Bu bağlamda vatansız ve durum bilgisi tam olarak ne beklediğiniz anlamına gelmez.

EJB'lerle durumsallık, konuşma durumu dediğim şeyi ifade eder . Klasik örnek bir uçuş rezervasyonu. Üç adımdan oluşuyorsa:

  • Yedek koltuk
  • Kredi kartından ödeme al
  • Bilet Düzenleme

Bunların her birinin bir seans fasulyesine yapılan bir yöntem çağrısı olduğunu hayal edin. Durum bilgisi olan bir oturum bean, bu tür konuşmayı sürdürebilir, böylece görüşmeler arasında ne olduğunu hatırlayabilir.

Vatansız oturum fasulyelerinin konuşma durumu için böyle bir kapasitesi yoktur.

Bir oturum parçacığı içindeki genel değişkenler (durum bilgisi olmayan veya durum bilgisi olmayan) tamamen başka bir şeydir. Durum bilgisi olan oturum çekirdeklerinin oluşturulmuş bir çekirdek havuzu olacaktır (çünkü bir fasulye bir seferde yalnızca bir görüşmede kullanılabilir), oysa devletsiz susion çekirdeklerinin genellikle yalnızca bir örneği olacak, bu da genel değişkenin çalışmasını sağlayacaktır, ancak ben düşünmüyorum bu mutlaka garantilidir.


5

İyi soru,

bu kodu deneyin (MyBean Stateful / Stateless'ı değiştirin.):

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());
    }

}

vaka: MyBean - @ Durumsuz

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

vaka: 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


1
Evet, işte bu ve işe yarıyor! Çok kolay açıklama, teşekkürler!
Nesquik27

5

İki ana seans fasulyesi türü arasındaki ana farklar şunlardır:

Vatansız Fasulye

  1. Vatansız Oturum Fasulye sahip olanlardır hiçbir Conversationa yöntemlerini çağırdı müşteri ile l devlet. Bu nedenle, birden çok istemciyle etkileşim kurmak için kullanılabilecek bir nesne havuzu oluşturabilirler .
  2. Performans akıllıca Vatansız fasulye vardır iyi onlar beri yok istemci başına durumları vardır.
  3. Birden fazla işleyebilirler çok istemciden gelen birden isteği paralel olarak .

Durum bilgili Fasulye

  1. Durum bilgisi olan oturum çekirdekleri, aynı anda birden çok istemciyle konuşma durumunu sürdürebilir ve görev istemciler arasında paylaşılmaz.
  2. Oturum tamamlandıktan sonra durum değildir korudu.
  3. Kap, durumu ileride kullanmak üzere eski bir durum olarak seri hale getirebilir ve depolayabilir . Bu, uygulama sunucusunun kaynaklarını korumak ve fasulye hatalarını desteklemek için yapılır.

4

Bu durum, kapsayıcı havuzda tüm çağrılar için yeniden kullanılan tek bir bean örneğine sahip olduğu için olur. İstemcileri paralel olarak çalıştırırsanız, farklı bir sonuç görürsünüz çünkü konteyner havuzda daha fazla fasulye örneği oluşturacaktır.


4

İyi cevapları var. Küçük bir cevap eklemek istiyorum. Durumsuz Bean, herhangi bir müşteri verisini tutmak için kullanılmamalıdır. "Tek seferde yapılabilecek eylemleri veya işlemleri modellemek" için kullanılmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.