gpt4 book ai didi

java - JSF 在调用操作方法之前不更新值

转载 作者:行者123 更新时间:2023-12-01 23:29:00 25 4
gpt4 key购买 nike

我正在使用 JSF 创建一个时间表应用程序,目前正在处理登录部分。这是一个直接的登录,需要一个登录 ID 和一个密码,并检查它是否是一个有效的组合(尽管此时我正在处理管理员登录)。

我的问题似乎是 JSF 在调用验证操作方法之前没有更新我的登录 ID 和密码字段,因为当我单击登录时,它会抛出 NullPointerException。这是我的验证方法。

/**
* Verifies that the loginID and password is the super user combination.
* @return true if it is, false if it is not.
*/
public String verifyUser() {
ResourceBundle login = getSuperUserLogin();
String user = getLoginID();
String checkPassword = getPassword();
if(!login.containsKey(user) || !checkPassword.equals(login.getString(user))) {
return "regular";
}
return "super";
}

和我的登录页面

<body>
<div class = "content" align = "center">
<h:form>
<h3>#{msgs.loginTitle}</h3>
<h:panelGrid columns="2" cellpadding = "4">
<h:outputText value = "#{msgs.userID}" styleClass="title" />
<h:inputText value="#{user.loginID}" styleClass="rounded" />
<h:outputText value = "#{msgs.password}" styleClass="title" />
<h:inputSecret value="#{user.password}" styleClass="rounded" />
</h:panelGrid>
<p><h:commandButton value="#{msgs.login}" styleClass="button" action="#{superUser.verifyUser}"/></p>
</h:form>
</div>

现在,如果我将登录 ID 和密码硬编码到 user 和 checkPassword 字段中,那么它就没有问题了。所以我认为问题在于 loginID 和密码字段为空(因为 getLoginID() 和 getPassword() 只是返回这些字段的常规旧 getter)。我知道答案会很愚蠢,而且我会因为错过它而感到尴尬,但此时我的头正撞在墙上。

这样信息就完整了,loginID 和密码字段位于 User 类中(提供了适当的 setter),而 verifyUser 方法位于子类 SuperUser 中。我不知道为什么这会很重要,但这将是我第一个使用父类(super class)和子类的 JSF 应用程序,所以你永远不会知道。

编辑:根据要求,这里是我的用户类代码

package ca.bcit.infosys.timesheet.model;
import java.util.ResourceBundle;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;

@Named
@ApplicationScoped
public class User implements java.io.Serializable {
/** The user's name */
private String name;
/** The user's employee number */
private int empNumber;
/** The user's login ID */
private String loginID;
/** The user's password */
private String password;
/** Is the user currently in an editable state (i.e. the user's information can be edited on the webpage) */
private boolean editable;
private ResourceBundle superUserLogin = ResourceBundle.getBundle("ca.bcit.infosys.timesheet.model.messages");

/**
* @return the name
*/
public String getName() {
return name;
}

/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}

/**
* @return the empNumber
*/
public int getEmpNumber() {
return empNumber;
}

/**
* @param empNumber the empNumber to set
*/
public void setEmpNumber(int empNumber) {
this.empNumber = empNumber;
}

/**
* @return the loginID
*/
public String getLoginID() {
return loginID;
}

/**
* @param loginID the loginID to set
*/
public void setLoginID(String loginID) {
this.loginID = loginID;
}

/**
* @return the password
*/
public String getPassword() {
return password;
}

/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}

/**
* @return the isEditable
*/
public boolean isEditable() {
return editable;
}

/**
* @param isEditable the isEditable to set
*/
public void setEditable(boolean editable) {
this.editable = editable;
}

/**
* @return the Property containing the super user login information.
*/
public ResourceBundle getSuperUserLogin() {
return superUserLogin;
}

}

最佳答案

您当前的方法存在很多误解。我建议首先学习并掌握 JSF 的基本概念来完成此任务。

为了实现此目的,您需要一个仅在每次向服务器发出请求时都处于 Activity 状态的 bean。该 bean 将负责从 JSF 表单获取数据并执行验证操作。然后,您只需将字段和登录方法绑定(bind)到 JSF 表单即可。

Java代码

//Looks like you use CDI (or probably you just think this is what you need)
@Named
//The bean just needs to be alive on each request
//Since you're using CDI, make sure this annotation comes from
//javax.enterprise.context package
@RequestScoped
//Usually, the managed beans used in JSF are named with "Bean" suffix
//Since it is for learning purposes, I'll name this bean UserBean
public class UserBean {
//fields to hold username and password
//they both are Strings
private String username;
private String password;
//getters and setters methods
//I won't add them since it is boilerplate code for this sample
//...

//Method to handle your login action
//If successful login, then returns the name of the next view
//If unsuccessful, returns null to stay in the current view
public String login() {
//Sample implementation, remember to change it for A REAL ONE
if ("admin".equals(username) &&
"adminPass".equals(password)) {
//Successful login
//Make sure to have a file index.xhtml in the same folder
//where the login JSF page resides (for sample purposes)
return "index";
}
//Unsuccessful login
//Also, it is a good idea to show a message for end user
FacesMessage message = new FacesMessage("Invalid login.");
FacesContext.getCurrentInstance().addMessage(null, message);
return null;
}
}

JSF 代码

<h:form>
<h3>Login Title</h3>
<h:panelGrid columns="2">
<h:outputText value="User Id" />
<h:inputText value="#{userBean.username}" />
<h:outputText value="Password" />
<h:inputSecret value="#{userBean.password}" />
</h:panelGrid>
<h:commandButton value="Login" action="#{userBean.login}" />
<br />
<h:messages />
</h:form>

在继续之前,您需要了解一些事情:

  • JSF bean 与 CDI bean 不同。这里有更好的解释:Backing beans (@ManagedBean) or CDI Beans (@Named)? 。我建议阅读 Bozho 和 BalusC 的答案。
  • 定义托管 Bean 的范围。 JSF 初学者面临的主要问题之一是为 bean 选择正确的范围。例如,您开始将 bean 标记为 @ApplicationScoped,这意味着整个应用程序有一个 User bean,这意味着两个不同的最终用户将拥有相同的用户对象(现在你开始担心了)。您可以在这里了解更多信息:How to choose the right bean scope?
  • 正如您从上面的链接中看到的,有一个 View 范围。如果您使用 Java EE 7,那么您会发现此范围也适用于您的 CDI bean。如果您使用 Java EE 6,那么您会发现没有对此的注释。但别担心,OmniFaces从 1.6 版本开始,使用自定义 @ViewScoped 解决了这个问题来自 org.omnifaces.cdi 包的注释。
  • 由于您是从 JSF/CDI 开始,所以我建议每个 View 使用一个 bean。当你有更多经验时,你可以在同一个 View 中使用两个或多个bean。这是一个很好的例子:Can I use multiple managed bean in the same xhtml page?

关于java - JSF 在调用操作方法之前不更新值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19614608/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com