11

プログラムで(サーブレットinit()内から)ManagedBeanクラスをアプリケーションスコープに登録/追加したいと思います。JSF 1.2でそれを行うにはどうすればよいですか?

4

5 に答える 5

19

すべてのスコープのマネージドBeanのアプリケーションから、プログラムでこれを実行できる可能性はほとんどありません。BalusCは、アプリケーションスコープのマネージドBeanに対してこれを行う方法をすでに指摘しています。

管理対象BeanがMojarra2.1(JSF 2.1実装)にどのように登録されているかを確認しました。セッションのプログラムによる登録とスコープ付きBeanの要求に使用できるエレガントなオプションは多くありません。簡単に言うと、実装固有のクラスを呼び出すか、JSF実装に依存するのではなく、自分でBeanを作成および破棄する、つまり管理する必要があります。

リクエストスコープとセッションスコープにBeanを設定する(管理されていない方法)

注-これは、コンテナーではなくBeanを構築しているため、「管理されていない方法」と呼ばれます。アノテーションは、自分で処理して適切なメソッドを呼び出さない限り、機能@PostConstruct@PreDestroyません。依存性注入でさえ機能しません。

EL式は常に実行時に評価されるため、評価の前にスコープにBeanを設定する十分な機会が与えられます(機会があれば、足を撃ち抜くことができます)。Mojarra(および場合によっては他のJSF実装)では、ELリゾルバーはScopeHandler(または同等のクラス)のサービスに依存してEL式の値を解決します。MojarraはクラスApplicationScopeHandlerを使用し、さまざまなスコープから値を取得しますRequestScopeHandlerSessionScopeHandler

新しいセッションが作成された後、またはリクエストがJSF実装によって処理される前に、セッションスコープとリクエストスコープのコンテンツを設定できます。

セッションスコープの作成は、以下を使用して(理想的にはを使用してHttpSessionListener)実行できます。

HttpSession session = request.getSession(false);
session == null ? null : session.setAttribute("<keyname>", new Bean());

EL式でBeanを参照するために使用している値と一致するkeyname必要があります。

同様の方法で、以下を使用してリクエストスコープにデータを入力できます(理想的にはフィルターで実行されます)。

ServletRequest request = ... // get the reference to the servlet request object
request.setAttribute("<keyname>", new Bean());

これがどのように機能するかを理解する必要がある場合は、クラスcom.sun.faces.context.SessionMapを調べて、コンテキストマップが内部com.sun.faces.context.RequestMapcom.sun.faces.context.ApplicationMapどのように管理され、によって使用されるかSessionScopeHandlerRequestScopeHandlerおよび(別の静的内部)クラスのApplicationScopeHandler静的内部クラスであるクラスを確認する必要があります。クラスScopeManagercom.sun.faces.mgbean.BeanManagerこのBeanManagerクラスは、マネージドBeanの登録を含むクラスであり、次のセクションでは、Mojarraの登録プロセスを「ハッキング」する方法について説明します。

Mojarraクラスを使用してBeanを登録する

Mojarra実装でのマネージドBeanの登録は、クラスのpublic void register(ManagedBeanInfo beanInfo)メソッドによって行われます。JSFまたはサーブレットAPIのみを使用してクラスcom.sun.faces.mgbean.BeanManagerにアクセスすることは簡単ではありません。BeanManagerただし、インスタンスApplicationAssociateを作成するMojarraのクラスがあり、メソッドBeanManagerを使用してアクセスできます。getCurrentInstance()Thomasによるもう1つの回答は、マネージドBeanをプログラムで登録する方法をすでに示しています。

ApplicationAssociate.getCurrentInstance().getBeanManager().register(...)

上記のアプローチには注意が必要です。メソッドがインスタンスを取得するためにThreadLocal変数に依存しているServletという単純な理由から、このアプローチがのinitメソッドで機能する可能性は低いです。スレッドローカル変数はクラスによって初期化されるため、インスタンスにアクセスするには、クラスが使用するメソッドを呼び出すメカニズムを再現する必要があります。したがって、次のコードは、Mojarra固有のクラスを使用する場合は、(私は使用を試みていませんが)より適切なコードである可能性があります。getCurrentInstanceApplicationAssociatecom.sun.faces.application.WebappLifecycleListenerWebappLifecycleListenerApplicationAssociate getInstance(ServletContext context)ApplicationAssociate

ServletContext sc = ... //get the ServletContext reference;
ApplicationAssociate.getInstance(sc).getBeanManager().register(...)

一部のMojarraクラスおよびインスタンスがサーブレットの前にロードまたは初期化されていない可能性が高いため、このメカニズムから生じる癖に注意する必要があります。したがって、load-on-startupによって使用される値よりも高い値でサーブレットを構成しようとしてロードすることをお勧めしますFacesServlet

于 2011-07-19T12:32:10.027 に答える
14

サーブレット内からinit()

したがって、JSF以外の要求に関係します。ここにFacesContext#getCurrentInstance()戻るnullので、ここでは役に立ちません。

JSFアプリケーションスコープのマネージドBeanは、基本的にの属性として格納されることを知っておくとよいでしょうServletContext。このinit()メソッドServletContextでは、継承されたメソッドを使用できますgetServletContext()。したがって、次のようにする必要があります。

@Override
public void init() {
    getServletContext().setAttribute("managedBeanName", new BackingBean());
}

それでおしまい。によってJSFで利用できるようになります#{managedBeanName}

于 2011-07-19T11:37:43.887 に答える
3

試してみてくださいFacesContext.currentInstance().getExternalContext().getApplicationMap().put(name, bean);。つまり、式で使用する名前を使用して、マネージドBeanインスタンスをマップに配置します。

編集:

Beanを登録するには、次の呼び出しを試してください。入力ApplicationAssociate.getCurrentInstance().getBeanManager().register(...)したaを渡しManagedBeanInfoます。

于 2011-07-19T11:22:06.627 に答える
1

次のコードは、を使用してマネージドBeanを正しく登録しFacesContextますが、サーブレットの要求と応答が必要です。コードを使用して、初期化中ではなくサーブレットを使用して遅延的に初期化することができます。

使用法:

UserBean ub = (UserBean) 
    Example.getBean(servletRequest, servletResponse, "user", UserBean.class);

ソース:

import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.FactoryFinder;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

class Example {

    public static Object getBean(HttpServletRequest request, HttpServletResponse response, String beanName, Class expectedType){
        FacesContext ctx = getFacesContext(request, response);
        ValueExpression vex = ctx.getApplication().getExpressionFactory().createValueExpression(ctx.getELContext(), "#{"+beanName+"}", expectedType);
        return vex.getValue(ctx.getELContext());
    }

    private static FacesContext getFacesContext(HttpServletRequest request, HttpServletResponse response) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        if (facesContext == null) {
            facesContext = ((FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY)).
                getFacesContext(request.getSession().getServletContext(), request, response, 
                ((LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY))
                .getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE));

            InnerFacesContext.setFacesContextAsCurrentInstance(facesContext);
            facesContext.setViewRoot(facesContext.getApplication().getViewHandler().createView(facesContext, ""));
        }
        return facesContext;
    }

    private abstract static class InnerFacesContext extends FacesContext {
        protected static void setFacesContextAsCurrentInstance(FacesContext facesContext) {
            FacesContext.setCurrentInstance(facesContext);
        }
    }
}
于 2014-09-04T15:54:01.987 に答える
-1

を使用してBeanを登録したとします

ApplicationAssociate.getInstance(sc).getBeanManager().register(...)

これで正常に動作していますが、サーバーが再起動し、Beanが破棄されます。起動時に、同じBeanを登録するにはどうすればよいですか。

于 2015-10-21T10:09:36.983 に答える