我有一个JSF页面,其中显示了给定用户的详细信息:
<h:form>
<p>
<h:outputLabel value="User Name" for="userName" />
<h:outputText id="userName" value="#{userController.user.name}" />
</p>
<p>
<h:outputLabel value="Email" for="email" />
<h:outputText id="email" value="#{userController.user.email}" />
</p>
<p>
<h:commandLink value="Edit" action="#{userController.edit(userController.user.id)}" />
</p>
</h:form>
除了Edit commandLink之外,这个工作得很好。当我单击它时,我希望userController.edit
传递当前在页面上呈现的用户的ID。
然而,看起来像userController
是一个请求作用域的bean,它有一个@PostConstruct
方法,将一个新用户分配给用户字段,总是0被传递给动作方法,因为用户的新实例的ID是null
,显然被转换为0。
我如何修复这个控制器/页面,不改变控制器的范围,传递正确的ID编辑动作?下面是控制器的代码:
@Model
public class UserController {
@Inject
@UserRepository
private EntityManager entityManager;
@Inject
private UserTransaction tx;
private User user;
public String edit(Long id) {
System.out.println("id = " + id);
// fetch the user with id from the db
return "edit";
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@PostConstruct
private void init() {
user = new User();
}
}
这个方法很奇怪,但是我可以想象当你需要它的时候。(例如,你不想写会话和flash作用域不工作在分布式环境等)。如果你不能使用session作用域,可以考虑使用flash作用域。
除了方法的正确性之外,还可以尝试在bean中添加其他字段:
protected Long currentId;
public Long getCurrentId() {
return currentId == null ? user.getId() : currentId;//or simply return it, I don't know how you play with the user field
}
public void setCurrentId(Long currentId) {
this.currentId = currentId;
}
从edit
动作中删除参数并使用currentId
字段,并在您的视图中添加参数(隐藏字段在这里不起作用):
<f:viewParam name="id" value="#{userController.currentId}" />
然后在操作中,您可以从前面的视图中获取用户id,只需访问this.currentId。顺便说一句,试着从另一个地方加载你的用户,而不是@PostConstruct。如果你在@PostConstruct中创建user,那么当你在编辑方法中,currentId将来自前一个视图和user。id将来自@PostConstruct。因此,如果你不想在会话范围内存储用户,但只使用请求范围,你必须在创建后立即持久化它(例如在数据库中)。在编辑方法中,你必须使用currentId。