-3

最近我需要在Struts2中使用DI。我知道它使用它自己的DI實現,如Guice,但不是Guice,只要我找不到適合爲注入Bean設置範圍的註釋。簡而言之,我創建了一個beanStruts2中的依賴注入訪問會話作用域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一起使用的註釋。我通過彈簧DI成功創建了同一個bean,並設置了我的對象注入的範圍。現在,我想對Struts2和DI做同樣的事情。爲了這個目的,我創建了struts.xml

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

和簡單的動作bean定義得到該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> 

現在,當我運行這個smple應用程序時,我有例外

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 configuration
+0

這個'@ Inject'註釋來自哪個包? –

+0

另一個問題是,你想使用Guice作爲DI經理還是Spring? –

+0

好的。嘗試將'@ Injection'註釋移到該字段,而不是如[這裏]所示的setter(http://mahendraunlimited.wordpress.com/2012/10/06/struts2-dependency-injection/)。 –

回答

3

讓我們從尋找通過查看文檔什麼是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"/> 

這就是你需要用會話範圍注入一個bean Session。類似的實現可以爲其他範圍完成。注意,像singlton(默認使用),線程和默認的其他作用域似乎不需要這樣的可插入擴展。最後一個字是關於@Scoped的註釋。如果您通過xml配置提供bean,則不會使用它。但是,如果您以任何其他方式向ContainerBuilder提供bean,則可以在其上找到註釋並設置相應的作用域。

+1

你的答案是完美的,非常適合@羅曼C的問題 – Jagadeesh

2

相信Luiggi的評論是正確的。 「@Inject」需要在字段值本身上,而不是在setter上。

@Inject("session") 
private Session session; 

只要你已經得到了「會話」豆在struts.xml中定義或與Struts的容器中註冊它,它應該能夠找到它,並把它注射。從你的解釋看來是這樣。

對於一些更具體的信息,請查閱Struts的用戶列表此討論:Struts user question on built-in DI

+0

我不這麼認爲,如果你不是我熟悉的東西。 – Durandal

+0

對不起,意思是說如果可能,這不是我熟悉的東西。我以前只使用了Struts容器來做一些相當基本的事情。如果我需要的不僅僅是非常基本的DI功能,我通常會去Spring或者Guice。您可能可以在需要會話時使用攔截器進行設置,但這會非常粗糙。 – Durandal

+0

是的,我們所做的一切只是默認行爲,但我們所做的並不需要更改bean的範圍。 – Durandal

相關問題