-3

最近、Struts2 で DI を使用する必要がありました。注入された Bean のスコープを設定するのに適した注釈が見つからない限り、Guice ではなく Guice のような独自の DI 実装を使用していることはわかっています。要するに、私はBeanを作成しました

//@Repository
//@Scope("session")
public class Session {

    private Map<String, Object> map = new HashMap<>();

    public Map<String, Object> getMap() {
        return map;
    }

    public void setMap(Map<String, Object> map) {
        this.map = map;
    }
}

Spring Bean で使用される注釈についてコメントしました。Spring DI を介して同じ Bean を正常に作成し、オブジェクトが注入されるスコープを設定しました。今、私は Struts2 と DI で同じことをしたいと考えています。この目的のために、私は Bean 定義を作成しましたstruts.xml

<bean name="session" class="jspbean.struts.Session" scope="session"/>

そして、その Bean を作成してアクションに注入するための単純なアクション

public class DefaultAction extends ActionSupport {

    private Session session;

    //  @Autowired
    @Inject("session")
    public void setSession(Session session) {
        this.session = session;
    }

    public Session getSession() {
        return session;
    }

    private Map<String, String> myMap = new HashMap<String, String>();

    public Map<String, String> getMyMap() {
        return myMap;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    @Override
    public String execute() throws Exception {
        //populate my bean with sample data
        myMap.put("q1", "Question1");
        myMap.put("q2", "Question2");
        session.getMap().put("myMap", myMap);
        return SUCCESS;
    }
}

JSP では、セッション Bean で単純なイテレータを使用します

<s:iterator value="session.map['myMap']">
  <s:textfield name="myMap['%{key}']" value="%{value}" theme="simple" size="10" /><br>
</s:iterator>

さて、このサンプルアプリケーションを実行していると、例外が発生しました

Stacktraces
Unable to instantiate Action, jspbean.struts.DefaultAction, defined for '' in namespace '/'java.lang.IllegalStateException: Scope strategy not set. Please call Container.setScopeStrategy().

    com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:316)
    com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:397)
    com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:194)
    org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
    org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
    com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
    org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:536)
    org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)


java.lang.RuntimeException: java.lang.IllegalStateException: Scope strategy not set. Please call Container.setScopeStrategy().

    com.opensymphony.xwork2.inject.ContainerImpl$MethodInjector.inject(ContainerImpl.java:301)
    com.opensymphony.xwork2.inject.ContainerImpl.inject(ContainerImpl.java:492)
    com.opensymphony.xwork2.inject.ContainerImpl$6.call(ContainerImpl.java:530)
    com.opensymphony.xwork2.inject.ContainerImpl$6.call(ContainerImpl.java:528)
    com.opensymphony.xwork2.inject.ContainerImpl.callInContext(ContainerImpl.java:584)
    com.opensymphony.xwork2.inject.ContainerImpl.inject(ContainerImpl.java:528)
    com.opensymphony.xwork2.ObjectFactory.injectInternalBeans(ObjectFactory.java:139)
    com.opensymphony.xwork2.spring.SpringObjectFactory.autoWireBean(SpringObjectFactory.java:208)
    com.opensymphony.xwork2.spring.SpringObjectFactory.buildBean(SpringObjectFactory.java:183)
    com.opensymphony.xwork2.spring.SpringObjectFactory.buildBean(SpringObjectFactory.java:154)
    com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:151)
    com.opensymphony.xwork2.ObjectFactory.buildAction(ObjectFactory.java:121)
    com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:297)
    com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:397)
    com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:194)
    org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
    org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
    com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
    org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:536)
    org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)


java.lang.IllegalStateException: Scope strategy not set. Please call Container.setScopeStrategy().

    com.opensymphony.xwork2.inject.InternalContext.getScopeStrategy(InternalContext.java:53)
    com.opensymphony.xwork2.inject.Scope$5$1.create(Scope.java:130)
    com.opensymphony.xwork2.inject.ContainerImpl$ParameterInjector.inject(ContainerImpl.java:469)
    com.opensymphony.xwork2.inject.ContainerImpl.getParameters(ContainerImpl.java:484)
    com.opensymphony.xwork2.inject.ContainerImpl.access$000(ContainerImpl.java:34)
    com.opensymphony.xwork2.inject.ContainerImpl$MethodInjector.inject(ContainerImpl.java:299)
    com.opensymphony.xwork2.inject.ContainerImpl.inject(ContainerImpl.java:492)
    com.opensymphony.xwork2.inject.ContainerImpl$6.call(ContainerImpl.java:530)
    com.opensymphony.xwork2.inject.ContainerImpl$6.call(ContainerImpl.java:528)
    com.opensymphony.xwork2.inject.ContainerImpl.callInContext(ContainerImpl.java:584)
    com.opensymphony.xwork2.inject.ContainerImpl.inject(ContainerImpl.java:528)
    com.opensymphony.xwork2.ObjectFactory.injectInternalBeans(ObjectFactory.java:139)
    com.opensymphony.xwork2.spring.SpringObjectFactory.autoWireBean(SpringObjectFactory.java:208)
    com.opensymphony.xwork2.spring.SpringObjectFactory.buildBean(SpringObjectFactory.java:183)
    com.opensymphony.xwork2.spring.SpringObjectFactory.buildBean(SpringObjectFactory.java:154)
    com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:151)
    com.opensymphony.xwork2.ObjectFactory.buildAction(ObjectFactory.java:121)
    com.opensymphony.xwork2.DefaultActionInvocation.createAction(DefaultActionInvocation.java:297)
    com.opensymphony.xwork2.DefaultActionInvocation.init(DefaultActionInvocation.java:397)
    com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:194)
    org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
    org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
    com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
    org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:536)
    org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)

例外は、スコープ戦略を設定する必要があることを示しています。したがって、私の質問は、このスコープ戦略とは何か、そしてそれを私の単純なアプリケーションにどのように実装できるかということです。また、注釈があり@Scopedますが、この注釈を私の場合にどのように適用しますか?

私の例の参照:

  1. Bean 構成
4

2 に答える 2

4

Scope.Strategyドキュメントを見て、とは何かを調べることから始めましょう。それは言う

プラグ可能なスコープ戦略。ユーザーが要求、セッション、およびウィザードのスコープのカスタム実装を提供できるようにします。実装して渡す Container.setScopeStrategy(com.opensymphony.xwork2.inject.Scope.Strategy)

セッションスコープを実装したいとします。次に、それを実装できる場所を知る必要があります。フレームワークには、拡張機能をプラグインするか、単に実装を拡張しdefaultて独自のカスタム実装を提供できる拡張ポイントがあります。これは、 を参照して簡単に実行できBeanSelectionProviderます。次に、スタック トレースを分析して、DefaultActionProxyFactory. それを拡張するには、 も拡張する必要がDefaultActionProxyあります。

public class MyActionProxyFactory extends DefaultActionProxyFactory {

    public MyActionProxyFactory() {
        super();
    }

    @Override
    public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {

        MyActionProxy proxy = new MyActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
        container.inject(proxy);
        container.setScopeStrategy(new MyScopeStrategy());
        proxy.prepare();
        return proxy;
    }
}

public class MyActionProxy extends DefaultActionProxy {

    protected MyActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
        super(inv, namespace, actionName, methodName, executeResult, cleanupContext);
    }

    @Override
    protected void prepare() {
        super.prepare();
    }
}

public class MyScopeStrategy implements Scope.Strategy {

    @Override
    public <T> T findInRequest(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
        return null;
    }

    @Override
    public <T> T findInSession(Class<T> type, String name, Callable<? extends T> factory) throws Exception {

        ActionContext context = ActionContext.getContext();
        SessionMap<String, T> sessionMap = (SessionMap<String, T>) context.getSession();

        if (sessionMap == null) {
            sessionMap = new SessionMap<String, T>(ServletActionContext.getRequest());
            context.setSession((Map<String, Object>) sessionMap);
        }

        T obj = sessionMap.get(name);

        if (obj == null) {
            obj = factory.call();
            sessionMap.put(name, obj);
        }
        return obj;
    }

    @Override
    public <T> T findInWizard(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
        return null;
    }
}

構成ファイルstruts.xmlで、プロパティを設定する必要があります

<constant name="struts.actionProxyFactory" value="jspbean.struts.factory.MyActionProxyFactory"/>

Sessionセッション スコープでBean を注入するために必要なのはこれだけです。他のスコープに対しても同様の実装を行うことができます。シングルトン (デフォルトで使用)、スレッド、およびデフォルトなどの他のスコープは、そのようなプラグ可能な拡張機能を必要としないことに注意してください。そして最後の言葉は@Scoped注釈についてです。xml 構成を介して Bean を提供する場合は使用されません。ただし、ContainerBuilder他の方法で Bean を指定すると、その上の注釈を見つけて、対応するスコープを設定できます。

于 2013-06-30T21:16:12.317 に答える
2

ルイージのコメントは正しいと思います。「@Inject」は、セッターではなく、フィールド値自体にある必要があります。

 @Inject("session")
 private Session session;

「セッション」Bean が struts.xml で定義されているか、Struts コンテナーに登録されている限り、それを見つけて注入できるはずです。あなたの説明からすると、そのように思われます。

より具体的な情報については、Struts ユーザー リストのこのディスカッションを確認してください:ビルトイン DI に関する Struts ユーザーの質問

于 2013-06-26T16:48:36.633 に答える