Инъекция зависимостей в 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
и простое действие, чтобы получить этот компонент, созданный и введенный в действие
- Как использовать контейнер DI / IoC с привязкой модели в ASP.NET MVC 2+?
- Каковы преимущества контейнеров для инъекций зависимостей?
- Шаблон страtagsи и зависимость от использования с помощью Unity
- Как передать значения конструктору в моей службе wcf?
- Фабричный метод с DI и IoC
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 применять в моем случае?
Мои примеры ссылок:
- конфигурация боба
- Инъекция Мокито издевается над весенним бобаном
- Включение зависимостей Spring в объект EntityListener
- Как интегрировать поставщика членства IoC с ASP.NET MVC
- Модульный ввод / вывод файлов
- Инъекционная инъекция с использованием Azure WebJobs SDK?
- Вставить услугу в Action Filter
- Регистрация фаз (прототип) во время выполнения весной
- Циркулярная зависимость впрыска угловая 2
Давайте начнем с поиска того, что такое 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 extends T> factory) throws Exception { return null; } @Override public T findInSession(Class type, String name, Callable extends T> 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 extends T> 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