Инъекция зависимостей в Struts2 Доступ к фазам с включенным сеансом

Недавно мне нужно было использовать DI в Struts2. Я знаю, что он использует собственную реализацию DI, такую ​​как Guice, но не Guice, поскольку я не мог найти некоторые annotations, подходящие для установки области для инжектируемых компонентов. Короче говоря, я создал bean-компонент

//@Repository //@Scope("session") public class Session { private Map map = new HashMap(); public Map getMap() { return map; } public void setMap(Map map) { this.map = map; } } 

Я прокомментировал annotations, используемые с весенними бобами. Я был успешно создан тот же компонент через Spring DI и задал область, в которую были введены мои объекты. Теперь я хочу сделать то же самое с Struts2 и DI. Для этого я создал определение bean-компонента в struts.xml

  

и простое действие, чтобы получить этот компонент, созданный и введенный в действие

 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 myMap = new HashMap(); public Map getMyMap() { return myMap; } public void setMyMap(Map 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 я использую простой 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) 

В исключении указано, что мне нужно установить страtagsю области. Итак, мой вопрос заключается в том, что такое эта страtagsя и как она может быть реализована в моем простом приложении. Кроме того, есть аннотация @Scoped , как это annotations применять в моем случае?

Мои примеры ссылок:

  1. конфигурация боба

Давайте начнем с поиска того, что такое Scope.Strategy , посмотрев на документы. В нем говорится:

Страtagsя охвата плагинов. Позволяет пользователям предоставлять пользовательские реализации областей запроса, сеанса и мастера. Container.setScopeStrategy(com.opensymphony.xwork2.inject.Scope.Strategy) и перейдите в Container.setScopeStrategy(com.opensymphony.xwork2.inject.Scope.Strategy)

Хорошо, предположим, что я хочу реализовать область сеанса. Затем мне нужно знать место, где я мог бы его реализовать. В инфраструктуре есть свои точки расширения, где вы можете подключать свои расширения или просто расширять реализацию по default и предоставлять свои собственные пользовательские реализации. Это легко сделать, посмотрев на BeanSelectionProvider . Затем, проанализировав stacktraces, я решил, что лучшим вариантом будет расширение DefaultActionProxyFactory . Для его расширения DefaultActionProxy также расширение 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 findInRequest(Class type, String name, Callable factory) throws Exception { return null; } @Override public  T findInSession(Class type, String name, Callable factory) throws Exception { ActionContext context = ActionContext.getContext(); SessionMap sessionMap = (SessionMap) context.getSession(); if (sessionMap == null) { sessionMap = new SessionMap(ServletActionContext.getRequest()); context.setSession((Map) sessionMap); } T obj = sessionMap.get(name); if (obj == null) { obj = factory.call(); sessionMap.put(name, obj); } return obj; } @Override public  T findInWizard(Class type, String name, Callable factory) throws Exception { return null; } } 

В файле конфигурации struts.xml вы должны установить свойство

  

Это все, что вам нужно, чтобы ввести Session компонента с областью сеанса. Подобные реализации могут быть выполнены для других областей. Обратите внимание, что другие области, такие как singlton (используется по умолчанию), stream и значение по умолчанию, не требуют такого подключаемого расширения. И последнее слово о @Scoped annotations. Он не используется, если вы предоставляете bean-компоненты через xml-конфигурацию. Но если вы предоставите ContainerBuilder компонентом любым другим способом, он сможет найти аннотацию на нем и установить соответствующую область.

Я считаю, что комментарий Луиджи верен. «@Inject» должен быть на самом значении поля, а не на установщике.

  @Inject("session") private Session session; 

До тех пор, пока у вас есть бит сеанса, определенный в struts.xml или зарегистрированный в контейнере Struts, он должен найти его и ввести. Из вашего объяснения, похоже, это так.

Для получения дополнительной информации проверьте эту дискуссию в списке пользователей Struts : задайте вопрос пользователю о встроенном DI

  • Logging, Aspect Oriented Programming и Injection Dependency Injection - Попытка понять все это
  • ContextLoaderListener или нет?
  • Инъекция зависимостей - требуется новый экземпляр для нескольких методов classов
  • Инъекция зависимостей и JavaFX
  • Spring: namespace vs contextConfigИнтересные параметры размещения в web.xml
  • Передача данных в дочерние компоненты маршрутизатора-выхода (угловые 2)
  • Доступ к инжектору Guice в его модуле?
  • Включение зависимостей в фильтры действия ASP.NET MVC 3. Что не так с этим подходом?
  • Как я могу вводить в @FacesConverter?
  • Вопросы об использовании Ninject
  • Инъекция зависимости: Черепахи полностью вниз?
  • Давайте будем гением компьютера.