【问题标题】:facelets 'target unreachable'facelets“目标无法到达”
【发布时间】:2012-07-08 11:20:21
【问题描述】:

我正在使用 maven、jsf 2.0、java ee 6、jpa 和 glassfish。我有一个初始网页,询问您是否要登录或注册。如果他们说他们想登录,他们会被转发到 facelets/primefaces 3,它会显示一个带有用户名和密码文本框的登录页面。对于用户名文本字段,其值为

value="#{authenticator.username}"

我得到一个

“目标不可达,标识符‘验证器’解析为空”

我正在使用 beans.xml。我遵循 CDI bean 的命名约定。 我在 Authenticator 构造函数中插入了一条日志消息,它似乎永远不会被调用,因为我没有收到消息。

另一个奇怪的是,一旦它在一个蓝色的月亮上工作,我得到如下的东西:

07/08/2012 00:27:56.140 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:27:56.171 INFO ...Authenticator - 获取 Authenticator 用户名

07/08/2012 00:27:56.171 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:27:56.171 INFO ...验证器 - 获取验证器密码

07/08/2012 00:27:56.171 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:27:56.171 INFO ...Authenticator - 获取 Authenticator 用户名

07/08/2012 00:27:56.171 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:27:56.171 INFO ...验证器 - 获取验证器密码

07/08/2012 00:28:05.843 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:28:05.843 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:28:05.843 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:28:05.843 INFO ...Authenticator - 获取 Authenticator 用户名

07/08/2012 00:28:05.843 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:28:05.906 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:28:05.906 INFO ...验证器 - 获取验证器密码

07/08/2012 00:28:26.000 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:28:26.000 INFO ...Authenticator - 在 Authenticator 构造函数中`

07/08/2012 00:28:26.000 INFO ...Authenticator - 在 Authenticator 构造函数中

07/08/2012 00:28:26.031 INFO ...Authenticator - 在 Authenticator 构造函数中 07/08/2012 00:28:26.031 INFO ...验证器 - 获取验证器密码

当它工作时,我不明白为什么它会这么多次调用构造函数。

这里是托管 (cdi) bean:

package com.mlb.mybills.view.user;

import com.mlb.mybills.i18n.Messages;
import java.util.Locale;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Named("authenticator")
@ViewScoped
public class Authenticator
{
    private static final Logger log = LoggerFactory.getLogger(Authenticator.class);

    private String username;
    private char[] password;

    public Authenticator()
    {
      log.info("in Authenticator constructor");
    }

    public String getUsername()
    {
      log.info("getting Authenticator username");
        return username;
    }

    public void setUsername(String username)
    {
      log.info("getting Authenticator username");
        this.username = username;
    }

    public char[] getPassword()
    {
      log.info("getting Authenticator password");
        return password;
    }

    public void setPassword(char[] password)
    {
        log.info("setting Authenticator password");
      this.password = password;
    }

public void setPassword(String password)
    {
        log.info("setting Authenticator password");
      this.password = password.toCharArray();
    }


   public String authenticate()
    {
      log.info("in Authenticator.authenticate");
        String result = null;
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
        try
        {
            request.login(username, new String(password));
            //result = "/private/group.xhtml?faces-redirect=true";
         result = "/group.xhtml?faces-redirect=true";
        }
        catch (ServletException ex)
        {
            log.error("Failed to authenticate user.", ex);
            Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
         FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, Messages.getString(
                    "Login.InvalidIdPasswordMessage", locale), null);
            FacesContext.getCurrentInstance().addMessage(null, facesMessage);
        }
      log.info("result=" + result);
        return result;
    }

    public String logout()
    {
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
        try
        {
            request.logout();
        }
        catch (ServletException servletEx)
        {
            log.warn("Failed to logout the user", servletEx);
        }
        return "/Login.xhtml?faces-redirect=true";
    }
}

【问题讨论】:

  • Post Authenticator 托管 bean 代码。

标签: jsf-2 primefaces facelets cdi


【解决方案1】:

您正在混合 bean 管理 API。 @Named 来自 CDI,但 @ViewScoped 来自 JSF。您需要使用其中一个,而不是在单个 backing bean 上同时使用。现在 bean 基本上由 CDI 管理,没有任何有效范围,因此每次解析 EL 表达式 #{authenticator} 时都会构造 bean。

要解决此问题,如果您打算坚持使用 CDI,请使用 @ConversationScoped 而不是 @ViewScoped

@Named
@ConversationScoped

或者如果您打算坚持使用 JSF,请使用 @ManagedBean 而不是 @Named

@ManagedBean
@ViewScoped

CDI 方法的唯一缺点是您必须将@InjectConversation 作为属性,然后自己开始和结束它。

【讨论】:

  • +1 - 但能够开始/停止对话(通常对应于用例)绝对是一项功能,而不是劣势......
  • @jan:我并不是要暗示这本身就是一个缺点,而只是在您打算模拟 JSF 视图范围的特定情况下;使用 JSF 注释可能更容易。
  • @BalusC 谢谢,在使用@ConversationScoped 或@RequestScoped 和@Named 时使用了JSF,但没有使用CDI。我有一个空的 beans.xml。我注意到我使用了 `String result = null; ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); HttpServletRequest 请求 = (HttpServletRequest) externalContext.getRequest();尝试 { request.login(username, new String(password)); //result = "/private/group.xhtml?faces-redirect=true";结果 = "/group.xhtml?faces-redirect=true"; }` 这可能是罪魁祸首。是否有 CDI 方法来获取请求。
  • @BalusC 如果我使用 FacesContext.getCurrentInstance().getExternalContext(),这可能是我在使用 CDI 时得到“无法访问目标”的原因
  • 不,绝对不是。您的 CDI 无法正常工作的问题是由托管 bean 层之上的其他原因引起的。
【解决方案2】:

您遇到了一些问题,因为您混合了 CDI (@Named) 和 JSF (@ViewScoped) 注释。由于这场比赛,它可能被多次调用。您可以查看 Seam Faces、MyFaces CODI 或推出您自己的 ViewScoped for CDI 版本,或者放弃 CDI 并直接使用 JSF。

【讨论】:

  • 这是因为 CODI 和 Seam 3 都劫持了 JSF @ViewScoped 注释并将其转换为 CDI 范围。
【解决方案3】:

虽然我不明白,但我找到了一个解决方案。我在以下链接中找到了它:a link!我不仅在 faces-config.xml 中添加了以下条目,还添加了 @RequestScoped 和 @Named

<managed-bean>
   <managed-bean-name>authenticator</managed-bean-name>
   <managed-bean-class>com.mlb.mybills.view.user.Authenticator</managed-bean-class>
   <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

有了这个,我不再遇到目标无法访问的错误。

显然,我还纠正了 BalusC 指出的上述错误。谢谢大家。

【讨论】:

    猜你喜欢
    • 2011-11-10
    • 2016-05-28
    • 2022-12-12
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 2021-08-28
    • 2017-09-24
    • 1970-01-01
    相关资源
    最近更新 更多