Java-бины Enterprise с сохранением состояния и состоянием

Я изучаю руководство по Java EE 6 и пытаюсь понять разницу между сессионными компонентами без сохранения состояния и с состоянием. Если сессионные компоненты без сохранения состояния не сохраняют свое состояние между вызовами методов, почему моя программа работает так, как она есть?

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

клиент

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 будет возвращать 0 каждый раз, но он возвращает 1, и перезагрузки сервлета в моем браузере увеличивают его больше. Проблема в том, что я понимаю, как работают сессионные компоненты без сохранения состояния, а не с библиотеками или сервером приложений. Может кто-нибудь дать мне простой пример типа "привет" в мире сессионного компонента без сохранения состояния, который ведет себя по-разному, когда вы изменяете его на состояние?

87 голосов | спросил Stanley kelly 28 FebruaryEurope/MoscowbSun, 28 Feb 2010 16:52:27 +0300000000pmSun, 28 Feb 2010 16:52:27 +030010 2010, 16:52:27

6 ответов


0

Важным отличием являются не личные переменные-члены, а связь состояния с конкретным пользователем (например, «корзина»).

Часть с сохранением состояния сессионного компонента похожа на сессию в сервлетах. Сессионные компоненты с сохранением состояния позволяют вашему приложению продолжать этот сеанс, даже если нет веб-клиента. Когда сервер приложений выбирает сессионный компонент без сохранения состояния из пула объектов, он знает, что его можно использовать для удовлетворения ЛЮБОГО запроса, поскольку он не связан с конкретным пользователем.

Сессионный компонент с состоянием должен быть передан пользователю, который получил его в первую очередь, потому что информация об их корзине должна быть известна только им. Сервер приложений гарантирует, что это так. Представьте себе, насколько популярным было бы ваше приложение, если бы вы могли начать делать покупки, а затем сервер приложений дал мне ваш сессионный компонент с состоянием, когда я пришел вместе!

Таким образом, ваш личный элемент данных действительно "состояние", но это не "корзина покупок". Попробуйте повторить ваш (очень хороший) пример, чтобы сделать так, чтобы увеличенная переменная ассоциировалась с конкретным пользователем. Увеличьте его, создайте нового пользователя и посмотрите, смогут ли они увидеть увеличенное значение. Если все сделано правильно, каждый пользователь должен видеть только свою версию счетчика.

ответил duffymo 28 FebruaryEurope/MoscowbSun, 28 Feb 2010 16:57:09 +0300000000pmSun, 28 Feb 2010 16:57:09 +030010 2010, 16:57:09
0

Сессионные компоненты без состояния (SLSB) не привязаны к одному клиенту, и нет гарантии , чтобы один клиент получал один и тот же экземпляр при каждом вызове метода (некоторые контейнеры могут создавать и уничтожать bean-компоненты с каждым сеансом вызова метода, это решение зависит от реализации, но экземпляры обычно объединяются в пул - и я не упоминаю кластерные среды). Другими словами, хотя bean-компоненты без состояния могут иметь переменные экземпляра, эти поля не являются специфичными для одного клиента, поэтому не полагайтесь на них между удаленными вызовами.

Напротив, Stateful Session Bean (SFSB) выделены одному клиенту на всю жизнь, обмен или пул экземпляров не производится (его можно удалить из памяти после пассивации для экономии ресурсов, но это другая история) и поддерживать разговорное состояние . Это означает, что переменные экземпляра компонента могут хранить данные относительно клиента между вызовами методов. И это позволяет иметь взаимозависимые вызовы методов (изменения, сделанные одним методом, влияют на последующие вызовы методов). Многоэтапные процессы (процесс регистрации, корзина покупок, процесс бронирования ...) являются типичными сценариями использования SFSB.

Еще одна вещь. Если вы используете SFSB, то вы должны избегать внедрения их в классы, которые являются многопоточными по своей природе, например, в Servlets и управляемые bean-компоненты JSF (вы не хотите, чтобы он использовался всеми клиентами). Если вы хотите использовать SFSB в своем веб-приложении, вам нужно выполнить поиск JNDI и сохранить возвращенный экземпляр EJB в объекте HttpSession для будущей деятельности. Примерно так:

try {
    InitialContext ctx = new InitialContext();
    myStateful = (MyStateful)ctx.lookup("java:comp/env/MyStatefulBean");
    session.setAttribute("my_stateful", myStateful);
} catch (Exception e) {
    // exception handling
}
ответил Pascal Thivent 28 FebruaryEurope/MoscowbSun, 28 Feb 2010 18:21:30 +0300000000pmSun, 28 Feb 2010 18:21:30 +030010 2010, 18:21:30
0

В этом контексте лица без состояния и с состоянием не означают совсем то, что вы могли бы ожидать.

Состояние с EJB-компонентами относится к тому, что я называю диалоговым состоянием . Классический пример - бронирование авиабилетов. Если он состоит из трех этапов:

  • Резервное место
  • зарядить кредитную карту
  • Issue Ticket

Представьте, что каждый из них является вызовом метода для сессионного компонента. Сессионный компонент с сохранением состояния может поддерживать такой разговор , чтобы он запоминал, что происходит между вызовами.

Сессионные компоненты без сохранения состояния не имеют такой возможности для диалогового состояния.

Глобальные переменные внутри сессионного компонента (без состояния или с состоянием) - это нечто совершенно другое. Сессионным компонентам с сохранением состояния будет создан пул компонентов (поскольку компонент может использоваться только в одном диалоге за раз), в то время как компоненты тестирования с состоянием без состояния часто будут иметь только один экземпляр, что обеспечит работу глобальной переменной, но я не думаю это обязательно гарантировано.

ответил cletus 28 FebruaryEurope/MoscowbSun, 28 Feb 2010 16:59:06 +0300000000pmSun, 28 Feb 2010 16:59:06 +030010 2010, 16:59:06
0

Это происходит потому, что у контейнера есть только один экземпляр компонента в пуле, который повторно используется для всех вызовов. Если вы запустите клиенты параллельно, вы увидите другой результат, потому что контейнер создаст больше экземпляров бинов в пуле.

ответил Neyma 29 Mayam13 2013, 02:25:29
0

У него хорошие ответы. Я хотел бы добавить небольшой ответ. Bean без сохранения состояния не должен использоваться для хранения данных клиента. Его следует использовать для «моделирования действий или процессов, которые можно выполнить за один раз».

ответил malatesh 27 MaramSun, 27 Mar 2016 08:26:22 +03002016-03-27T08:26:22+03:0008 2016, 08:26:22
0

Хороший вопрос,

попробуйте этот код (измените 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());
    }

}

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

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

ответил ZURA Tikaradze 23 +03002018-10-23T11:22:16+03:00312018bEurope/MoscowTue, 23 Oct 2018 11:22:16 +0300 2018, 11:22:16

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132