Боб с областью действия сеанса доступа из боба с областью действия запроса
Я пытаюсь использовать шаблон, найденный на странице IceFaces.(Я не использую IceFaces, используя PrimeFaces)
В этом случае у меня есть два боба:
UserController и Usermodel
На моей UserModel у меня есть экземпляр UserVO (созданный другим программистом). На моем UserController у меня есть это:
@ManagedBean
@RequestScoped
public class UserController implements Serializable
{
private static final long serialVersionUID = 1L;
private UserBO bo;
private UserModel model;
public UserController()
{
bo = new UserBO();
model = new UserModel();
}
public void Login() throws IOException
{
model.setUserVo(bo.executeLogin(model.getUserVo()));
ExternalContext externalContent = FacesContext.getCurrentInstance().getExternalContext();
if (!model.getUserVo().isError())
{
model.setLoggedIn(true);
externalContent.getSessionMap().put("userSession", model);
externalContent.redirect(externalContent.getRequestContextPath() + "/views/request/search.html");
} else
{
model.setLoggedIn(false);
FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, model.getUserVo().getMessage(), model.getUserVo().getLogin());
FacesContext.getCurrentInstance().addMessage(null, facesMessage);
}
}
public UserBO getBo()
{
return bo;
}
public void setBo(UserBO bo)
{
this.bo = bo;
}
public UserModel getModel()
{
return model;
}
public void setModel(UserModel model)
{
this.model = model;
}
}
Как вы можете видеть, я создаю новый экземпляр UserModel и устанавливаю его с тем, что было возвращено из bo.executeLogin()
и это работает, мой объект возвращается.
Чтобы убедиться, что пользователь вошел в систему, у меня есть свойство на моей UserModel :
@ManagedBean
@SessionScoped
public class UserModel
{
private UserVO userVo;
private Boolean loggedIn = false;
public UserModel()
{
userVo = new UserVO();
}
public UserVO getUserVo()
{
return userVo;
}
public void setUserVo(UserVO userVo)
{
this.userVo = userVo;
}
public Boolean getLoggedIn()
{
return loggedIn;
}
public void setLoggedIn(Boolean loggedIn)
{
this.loggedIn = loggedIn;
}
У меня есть шаблон .xhtml С:
<ui:fragment rendered="#{userModel.loggedIn}">
<ui:include src="../includes/top.xhtml"/>
</ui:fragment>
И дело в том, что он не работает, не получает значения свойства loggedIn
.
Я предполагаю, что доступ таким образом я как бы создаю новый экземпляр UserModel , Если это так, то это проблема, потому что мой UserController не является областью действия сеанса, только модель пользователя
EDIT
Вместо использования этого свойства loggedIn
я знаю, что могу просто проверить, если UserModel userVo
свойство задано, но проблема заключается в области сеанса Боба, я не могу получить доступ к нему из UserController , где он установлен, потому что это не область сеанса, и мой шаблон.xhtml будет использоваться каждой страницей.
3 ответа:
Вместо того, чтобы создавать новый экземпляр
UserModel
в вашемUserController
, введите его с@ManagedProperty
.В
UserController
:@ManagedProperty(value="#{userModel}") private UserModel model; // add getter and setter for userModel (important!)
Тогда вам не нужно создавать его экземпляр в конструкторе, и вы всегда получите экземпляр
UserModel
с областью действия сеанса в вашем контроллере.Обновление:
Я думаю, что вы усложняете процесс входа в систему своим строгим подходом MVC. В JSF границы между моделью, видом и контроллером несколько размыты или перекрываются.
Рекомендую прочтите Этот интересный вопрос и ответы и особенно этот ответ для получения дополнительной информации по этой теме.
Что касается вашей конкретной проблемы. Я не совсем уверен, в чем причина, но чего вам определенно следует избегать, так это создавать управляемые бобы самостоятельно и возиться с введенными и самоинициализированными экземплярами бобов.
Также я бы рекомендовал объединить ваши бобы вместе в один боб. Тогда у вас нет проблем с круговым движением зависимости и нулевые ссылки.
(это было первоначально опубликовано на https://stackoverflow.com/questions/10691324/working-with-3-java-beans-controller-backing-model, но ОП удалил вопрос и я не хотел выбрасывать ответ, думаю репост на этот вопрос тоже подойдет)
Вы, вероятно, слишком много внимания уделяли этому блогуICEfaces , который содержитВ основном чепуху .У вас должен быть один управляемый Боб JSF, который действует как контроллер, у вас уже есть:
UserController
. У вас должен быть простой объект bean, который представляет модель, у вас уже есть:UserVO
. У вас должен быть корпоративный боб, который представляет службу, он уже есть:UserBO
. Эти последние два не должны быть управляемыми бобами JSF.Основываясь на истории ваших вопросов, вы используете Glassfish, таким образом, вы можете использовать JPA и EJB. Таким образом, класс модели должен быть JPA
@Entity
, А класс обслуживания-EJB@Stateless
.Использование случай с "пользователем входа", однако, особенный. Вы не хотите, чтобы сущность была управляемым Бобом с областью действия сеанса, иначе она будет неявно создана JSF. Вам лучше самому внести его в область сеанса, чтобы вы могли проверить
#{not empty user}
, вошел ли пользователь в систему или нет.Все вместе это должно выглядеть примерно так:
@Entity public class User { private String username; private String password; // ... }
@Stateless public class UserService { @PersistenceContext private EntityManager em; public User find(String username, String password) { return em.createQuery("SELECT u FROM User u WHERE username = :username AND password = MD5(:password)", User.class) .setParameter("username", username) .setParameter("password", password) .getSingleResult(); } }
@ManagedBean @ViewScoped public class UserController { private String username; private String password; @EJB private UserService service; public String login() { FacesContext context = FacesContext.getCurrentInstance(); try { User user = userService.find(username, password); context.getExternalContext().getSessionMap().put("user", user); return "/views/commons/home.html?faces-redirect=true"; } catch (NoResultException) { context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unknown login, please try again", null)); return null; } } public String logout() { FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); return "/views/commons/login.html?faces-redirect=true"; } // ... }
С
<h:form> <h:inputText value="#{userController.username}" required="true" /> <h:inputSecret value="#{userController.password}" required="true" /> <h:commandButton value="login" action="#{userController.login}"/> <h:messages /> </h:form>
Альтернативно, вы можете сделать
UserController
сеансовым Бобом, который содержит сущностьUser
, Вы бы нужно только добавить дополнительный метод, чтобы проверить, вошел ли пользователь в систему или нет, чтобы вы могли использовать его в EL by#{userController.loggedIn}
.@ManagedBean @SessionScoped public class UserController { private User user = new User(); @EJB private UserService service; public String login() { FacesContext context = FacesContext.getCurrentInstance(); try { user = userService.find(user.getUsername(), user.getPassword()); return "/views/commons/home.html?faces-redirect=true"; } catch (NoResultException) { context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unknown login, please try again", null)); return null; } } public String logout() { FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); return "/views/commons/login.html?faces-redirect=true"; } public boolean isLoggedIn() { return user.getId() != null; } // ... }
С
<h:form> <h:inputText value="#{userController.user.username}" required="true" /> <h:inputSecret value="#{userController.user.password}" required="true" /> <h:commandButton value="login" action="#{userController.login}"/> <h:messages /> </h:form>