Ger*_*rep 4 jsf session-scope jsf-2
我正在尝试使用在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;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我创建了一个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;
}
Run Code Online (Sandbox Code Playgroud)
我有一个template.xhtml:
<ui:fragment rendered="#{userModel.loggedIn}">
<ui:include src="../includes/top.xhtml"/>
</ui:fragment>
Run Code Online (Sandbox Code Playgroud)
事情是,它没有工作,没有得到loggedIn
财产价值.
我的猜测是访问这种方式我有点创建UserModel的新实例,如果是这样,这是一个问题,因为我的UserController 不是会话作用域,只有UserModel
编辑
而不是使用这个loggedIn
属性,我知道我可以简单地检查是否设置了UserModel userVo
属性但是问题是关于会话范围的bean,我无法从UserController访问它,因为它不是作用域会话而设置它,我的template.xhtml 将被每个页面使用.
(这最初发布在/sf/ask/748392711/上,但是OP删除了这个问题,我不想扔掉回答,我认为这个问题的转发也是合适的)
你可能过分关注这个ICEfaces博客,其主要包含废话.
您应该拥有一个充当控制器的JSF托管bean,您已经拥有它:UserController
.你应该有一个代表模型的简单实体bean,你已经拥有它:UserVO
.您应该有一个代表该服务的企业bean,您已经拥有它:UserBO
.最后两个不需要是JSF托管bean.
根据您的问题历史记录,您正在使用Glassfish,因此您可以使用JPA和EJB.因此模型类应该是JPA @Entity
,服务类应该是@Stateless
EJB.
然而,"登录用户"的用例是特殊的.您不希望将实体作为会话范围的托管bean,或者它将由JSF隐式创建.你最好自己直接在会话范围内,这样你就可以检查#{not empty user}
用户是否登录.
所有这一切应该看起来像这样:
@Entity
public class User {
private String username;
private String password;
// ...
}
Run Code Online (Sandbox Code Playgroud)
@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();
}
}
Run Code Online (Sandbox Code Playgroud)
@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";
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
同
<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>
Run Code Online (Sandbox Code Playgroud)
或者,您可以创建UserController
一个包含User
实体的会话范围bean ,您只需要添加一个额外的方法来检查用户是否已登录,以便您可以在EL中使用它#{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;
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
同
<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>
Run Code Online (Sandbox Code Playgroud)
不要UserModel
在你的UserController
脑中创建一个新实例,而是注入它@ManagedProperty
.
在UserController
:
@ManagedProperty(value="#{userModel}")
private UserModel model;
// add getter and setter for userModel (important!)
Run Code Online (Sandbox Code Playgroud)
然后,您不必在构造函数中实例化它,并始终UserModel
在控制器中获取会话范围的实例.
更新:
我认为您使用严格的MVC方法使登录过程变得复杂.在JSF中,模型,视图和控制器之间的边界有些模糊或重叠.
我建议阅读这个有趣的问题和答案,特别是这个答案,以获得有关该主题的更多信息.
至于你的具体问题.我不太确定是什么原因,但你应该避免的是你自己实例化托管bean并且使用注入和自我初始化的bean实例.
我也建议将你的bean合并到一个bean中.然后你没有循环依赖和空引用的问题.
归档时间: |
|
查看次数: |
13835 次 |
最近记录: |