Как получить доступ к управляемым bean и сеансу bean от сервлета
Вот как работает мой commandLink
<p:dataTable value="#{myBean.users}" var="item">
<p:column>
<h:commandLink value="#{item.name}" action="#{myBean.setSelectedUser(item)}" />
</p:column>
</p:dataTable>
то в myBean.java
public String setSelectedUser(User user){
this.selectedUser = user;
return "Profile";
}
Предположим, что имя пользователя Peter
. Затем, если я нажму на Peter
, я установил selectedUser
как пользовательский объект Peter, а затем перенаправляется на страницу профиля, которая теперь отображает информацию из selectedUser
. Я хочу создать тот же эффект только с помощью <h:outputText>
, поэтому на этот вопрос приходит запрос GET. Поэтому я делаю это
<h:outputText value="{myBean.text(item.name,item.id)}" />
то метод text(String name, Long id)
возвращает
"<a href=\"someURL?userId=\"" + id + ">" + name + "</a>"
все, что осталось, это создание сервлета, поймать id
, запросить базу данных, чтобы получить объект user
, установить на selectedUser
, перенаправление.
Итак, вот мой сервлет
public class myServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Long userId = Long.parseLong(request.getParameter("userId"));
}
}
Теперь у меня есть id
, как мне получить доступ к сеансу bean, чтобы запросить базу данных для user
, а затем получить доступ к управляемому bean, чтобы установить user
в selectedUser
, а затем перенаправить на profile.jsf
?
Ответы
Ответ 1
JSF хранит управляемый сеанс beans как атрибут сеанса с использованием управляемого bean имени в качестве ключа. Таким образом, следующее должно работать (предполагая, что JSF уже создал bean раньше в сеансе):
MyBean myBean = (MyBean) request.getSession().getAttribute("myBean");
Тем не менее, я чувствую, что вы ищете неправильное направление решения. Вы также можете просто сделать следующее:
<a href="profile.jsf?userId=123">
со следующим в области запроса bean, связанной с profile.jsf
@ManagedProperty(value="#{param.userId}")
private Long userId;
@ManagedProperty(value="#{sessionBean}")
private SessionBean sessionBean;
@PostConstruct
public void init() {
sessionBean.setUser(em.find(User.class, userId));
// ...
}
Ответ 2
Вы можете добавить аннотации Inject и EJB в поля сервлета, если вы используете сервер приложений Java EE 6, например Glassfish v3. Некоторым это нравится:
@Inject
private AppManagedBean appmanaged;
@EJB
private SessionBean sessbean;
Помните, эти аннотации являются частью Injection Context и Dependecy или CDI, поэтому вы должны добавить дескриптор развертывания beans.xml.
Но если вы не можете использовать аннотации CDI, найдите интерфейс BeanManager в java: comp/BeanManager и используйте его для доступа (только) управляемого beans (внутри управляемого bean можно добавить сеанс beans с помощью аннотации @EJB). Также не забудьте добавить дескриптор развертывания beans.xml.
Класс полезности для поиска java: comp/BeanManager:
package mavenproject4;
import java.util.Set;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class ManagedBeans {
private static final BeanManager beanManager;
static {
try {
InitialContext ic = new InitialContext();
beanManager = (BeanManager) ic.lookup("java:comp/BeanManager");
} catch (NamingException ex) {
throw new IllegalStateException(ex);
}
}
private ManagedBeans() {
}
public static <T> T getBean(Class<T> clazz, String name) {
Set<Bean<?>> beans = beanManager.getBeans(name);
Bean<? extends Object> resolve = beanManager.resolve(beans);
CreationalContext<? extends Object> createCreationalContext = beanManager.createCreationalContext(resolve);
return (T) beanManager.getReference(resolve, clazz, createCreationalContext);
}
}
Использование класса утилиты в методе сервлета processRequest или эквиваленте:
response.setContentType("text/html;charset=UTF-8");
AppManagedBean appmanaged = ManagedBeans.getBean(AppManagedBean.class, "app");
PrintWriter out = response.getWriter();
try {
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet BeanManager</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>" + appmanaged.getHelloWorld() + "</h1>");
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
Пример управляемого bean с вложенным сеансом bean:
package mavenproject4;
import java.io.Serializable;
import javax.annotation.ManagedBean;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
@ManagedBean
@ApplicationScoped
@Named("app")
public class AppManagedBean implements Serializable {
private int counter = 0;
@EJB
private SessionBean sessbean;
public AppManagedBean() {
}
public String getHelloWorld() {
counter++;
return "Hello World " + counter + " times from Pachuca, Hidalgo, Mexico!";
}
}
Я не знаю, правильно ли работает код в классе утилиты, но работает. Также код не проверяет исключение NullPointerException и друзей.