Java-сервлет и JSP обращаются к одному и тому же сессионному компоненту - PullRequest
10 голосов
/ 18 апреля 2010

Допустим, у меня есть простой сервлет входа в систему, который проверяет переданный name и создает User объект и сохраняет его в сеансе.

User user = new User();
user.setId(name);

request.getSession().setAttribute("user", user);
response.sendRedirect("index.jsp");

На странице index.jsp я обращаюсь к объекту пользователя через jsp:useBean

<jsp:useBean id="user" scope="session"
             class="package.name.User"/>

<div class="panel">
    Welcome ${user.id}
</div>

Пока это работает.

Из документации по JSP Beans

Чтобы найти или создать экземпляр Боба, принимает следующее шаги, в следующем порядке:

  1. Пытается найти Бин с указанной вами областью и именем.
  2. Определяет переменную ссылки на объект с указанным вами именем.
  3. Если он находит Бин, сохраняет ссылку на него в переменной. Если Вы указали тип, дает Боб этот тип.
  4. Если он не находит Боб, создаёт его экземпляр из класса, который вы указать, сохранив ссылку на него в новая переменная. Если имя класса представляет сериализованный шаблон, Бин создается java.beans.Beans.instantiate.
  5. Если был создан экземпляр (а не расположен) Боба, и если имеет теги тела или элементы (между а также ), выполняет теги тела.

Вопросы:

Попытки найти Бин с указанными областью и именем

Он не определяет процесс "locate". Означает ли это, что он проверит HttpServletRequest.getSession() или просто проверит, создали ли другие компоненты этот компонент или нет?

Если он не находит Бин, создает его экземпляр из указанного вами класса, сохраняя ссылку> на него в новой переменной.

На самом деле это означает, что Jsp может связать вновь созданный компонент с сеансом, используя jsp_internal_name_user . Нет ни слова о том, как Jsp хранит и находит бины в сеансе.

Существует возможность доступа к объектам сеанса с помощью ${sessionScope.user}, и это гарантирует, что будет получен «пользователь» из объекта сеанса Java. Тот же, который я положил в себя.

Пример Java EE 5 «Book Store» для доступа к объектам сеанса с использованием подхода ${sessionScope.name}.

Использование только ${user} работает. И это то, что меня беспокоит. Я хотел бы видеть в спецификации конкретное предложение о locate процессе и о том, должен ли ${user} работать или о реализации JSP и / или JSTL.

Ответы [ 3 ]

6 голосов
/ 18 апреля 2010

В случае контроллера (сервлета), который заботится о модели, jsp:useBean полезен только в том случае, если экземпляр по умолчанию (созданный с помощью конструктора no-arg) демонстрирует другое поведение / состояние, чем несуществующий экземпляр. Например. если вы хотели бы иметь имя пользователя по умолчанию «Неизвестный пользователь», вы должны сделать:

public User {
    this.id = "Unknown User";
}

В противном случае конечный пользователь может столкнуться с надписью «Добро пожаловать» вместо «Добро пожаловать, неизвестный пользователь». В вашем конкретном случае вы можете безопасно удалить его. Это лишнее.

Однако я также видел аргумент, что это полезно для чистой документации. Вы можете объявить «бесполезные» экземпляры jsp:useBean в верхней части страницы JSP, чтобы у вас был обзор, какие именно модели использовались на конкретной странице JSP. Хотя я нахожу это довольно умным, у меня никогда не было потребности в таком способе документирования модели в JSP. Согласно комментариям, еще один аргумент заключается в том, что таким образом IDE, такие как IDEA и Eclipse, могут автоматически заполнять свойства bean в EL.

Обновление : что касается определения местоположения, для этого он использует PageContext#findAttribute(), а затем использует рефлексию / javabean-самоанализ для вызова методов-получателей. Э.Г.

${user.name}

примерно разрешается до

out.print(pageContext.findAttribute("user").getName())

Также см. Спецификацию JSP и спецификацию JSP EL .

Обновление 2 : <jsp:useBean> , безусловно, не использует внутреннее имя или так в качестве префикса атрибута сеанса. Переберите все атрибуты сеанса самостоятельно, чтобы увидеть фактические ключи и значения:

<c:forEach items="${sessionScope}" var="entry">
    ${entry.key} = ${entry.value}<br>
</c:forEach>

или в сервлете

for (String name : Collections.list(session.getAttributeNames())) {
   System.out.println(name + " = " + session.getAttribute(name));
}
4 голосов
/ 20 апреля 2010

Цитирование спецификации JSP JSP.5.1

Основная семантика пытается найти существующий объект, используя идентификатор и объем. Если объект не найден, он попытается создать объект, используя другой атрибутов.

Другими словами,

<jsp:useBean id="user" scope="session" class="package.name.User"/>

будет примерно переводиться в Java как:

package.name.User user = (package.name.User)session.getAttribute("user");
if (user == null){
  user = new package.name.User();
  session.setAttribute("user", user);
}
2 голосов
/ 18 апреля 2010

Из документации:

Элемент <jsp:useBean> находит или создает экземпляр компонента JavaBeans. <jsp:useBean> первая попытка найти экземпляр Бина. Если Бин не существует, <jsp:useBean> создает его экземпляр из класса или сериализует шаблон.

Так как "определение местоположения" bean-компонента совершенно нормально, мы можем предположить, что bean-компонент может быть сделан доступным с помощью инстанцирования через <jsp:useBean> Например, создав его в сервлете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...