Допустим, у меня есть простой сервлет входа в систему, который проверяет переданный 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
Чтобы найти или создать экземпляр Bean, выполните следующие шаги в указанном порядке:
- Пытается найти Bean с указанной вами областью действия и именем.
- Определяет переменную ссылки на объект с указанным вами именем.
- Если он находит Bean, сохраняет ссылку на него в переменной. Если вы указали тип, присваивает Бину этот тип.
- Если он не находит Bean, создает его экземпляр из указанного вами класса, сохраняя ссылку на него в новой переменной. Если имя класса представляет собой сериализованный шаблон, экземпляр Bean создается с помощью java.beans.Beans.instantiate.
- Если был создан (а не обнаружен) объект Bean, и если он имеет теги или элементы body (между и ), выполняет теги body.
Вопросы:
Попытки найти Bean с указанной вами областью действия и именем
Он не определяет процесс "найти". Означает ли это, что он проверит HttpServletRequest.getSession() или просто проверит, создали ли другие страницы этот компонент или нет?
Если он не находит Bean, создает его экземпляр из указанного вами класса, сохраняя ссылку > на него в новой переменной.
На самом деле это означает, что Jsp может связать вновь созданный компонент с сеансом, используя jsp_internal_name_user. Нет ни слова о том, как Jsp хранит и находит bean-компоненты в сеансе.
Существует возможность доступа к объектам сеанса с помощью ${sessionScope.user}, что гарантирует получение "пользователя" из объекта сеанса Java. Тот самый, который я поставил сам.
Пример Java EE 5 "Книжный магазин" доступ к объектам сеанса с использованием подхода ${sessionScope.name}.
Использование только ${user} работает. И вот что меня беспокоит. Я хотел бы увидеть в спецификации конкретное предложение о процессе locate и о том, должен ли работать ${user} или это зависит от эталонной реализации JSP и/или JSTL.
Ответ 1 · рейтинг 6 · BalusC
В случае контроллера (сервлета), который заботится о модели, jsp:useBean полезен только в том случае, если экземпляр по умолчанию (созданный с помощью конструктора без аргументов) предоставляет поведение/состояние, отличное от несуществующего экземпляра. Например. если вы хотите иметь имя пользователя по умолчанию "Неизвестный пользователь", вы должны сделать:
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));
}
Ответ 2 · рейтинг 5 · evnafets
Цитирование спецификации 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);
}