4

IceFaces ページで見つかったパターンを使用しようとしています (IceFaces は使用していませんが、PrimeFaces を使用しています)。

この場合、2 つの Bean があります。

ユーザーコントローラー とユーザーモデル

私の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;
    }

私はtemplate.xhtmlを持っています:

<ui:fragment rendered="#{userModel.loggedIn}">
            <ui:include src="../includes/top.xhtml"/>
</ui:fragment>

loggedIn問題は、それが機能しておらず、プロパティ値を取得していないことです。

私の推測では、この方法でアクセスすると、UserModelの新しいインスタンスを作成しているようなものです。もしそうなら、私のUserController はセッション スコープではなく、UserModelのみであるため、問題です。

編集

このプロパティを使用する代わりに、 UserModelloggedInプロパティが設定されているかどうかを簡単に確認できることはわかっていますが、問題はセッション スコープ Bean に関するものです。スコープ セッションではないため設定されているUserControllerからアクセスできません。 template.xhtml はすべてのページで使用されます。 userVo

4

3 に答える 3

8

(これは元々 https://stackoverflow.com/questions/10691324/working-with-3-java-beans-controller-backing-modelに投稿されましたが、OPは質問を削除し、私は捨てたくありませんでした回答、この質問への再投稿も適切だと思います)

あなたはおそらく、主にナンセンスを含むこのICEfacesブログに焦点を合わせすぎていたでしょう。

コントローラとして機能する単一のJSFマネージドBeanが必要ですが、すでにそれがありますUserController。モデルを表す単純なエンティティBeanが必要です。すでに、次のようになっていますUserVO。サービスを表すエンタープライズBeanが必要です。すでにそれがありますUserBO。これらの最後の2つは、JSFマネージドBeanである必要はありません。

Glassfishを使用している質問履歴に基づいて、JPAとEJBを利用できます。したがって、モデルクラスはJPA@Entityであり、サービスクラスは@StatelessEJBである必要があります。

ただし、「ログインユーザー」のユースケースは特別です。エンティティをセッションスコープのマネージドBeanにする必要はありません。そうしないと、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を保持するセッションスコープのBeanを作成することもできUserます。ユーザーがログインしているかどうかを確認するメソッドを追加するだけで、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;
    }

    // ...
}

<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>
于 2012-05-21T20:03:40.493 に答える
5

UserModelで新しいインスタンスを作成する代わりにUserController、で注入します@ManagedProperty

UserController

@ManagedProperty(value="#{userModel}")
private UserModel model;

// add getter and setter for userModel (important!)

次に、コンストラクターでインスタンス化する必要はなくUserModel、コントローラーでセッションスコープのインスタンスを常に取得します。

アップデート:

厳密な MVC アプローチでログイン プロセスが複雑になっていると思います。JSF では、モデル、ビュー、およびコントローラーの間の境界線が多少ぼやけたり、重なり合ったりします。

このトピックの詳細については、この興味深い質問と回答、特にこの回答を読むことをお勧めします。

あなたの具体的な問題について。理由はよくわかりませんが、絶対に避けるべきことは、マネージド Bean を自分でインスタンス化し、Bean の注入されたインスタンスと自己初期化されたインスタンスの両方をいじることです。

また、Bean を 1 つの Bean にマージすることをお勧めします。そうすれば、循環依存と null 参照の問題はありません。

于 2012-05-18T20:08:33.983 に答える
0

依存性注入を使用して、セッション スコープでその Bean から値を取得できます。

@Inject UserModel user; 

次に、このオブジェクトを UserControl Bean で使用できます。ちなみに、RequestScope Bean を扱っている場合、シリアライズ可能を実装する必要はありません。

于 2012-12-27T22:07:37.907 に答える