Struts2中的依赖注入访问会话范围的bean [英] Dependency Injection in Struts2 Accessing Session Scoped Beans

查看:131
本文介绍了Struts2中的依赖注入访问会话范围的bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我需要在Struts2中使用DI。我知道它使用自己的DI实现,如Guice,但不是Guice,只要我找不到适合设置注入bean范围的注释。简而言之,我创建了一个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定义

  ; bean name =sessionclass =jspbean.struts.Sessionscope =session/> 

和简单的操作来创建并注入到我的动作

  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异常{
//用样本数据填充我的bean
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 =simplesize =10/>< br&
< / s:iterator>

现在,当我运行这个smple应用程序时,我有异常

  Stacktraces 
无法实例化Action,jspbean.struts.DefaultAction,为''在命名空间中定义'/'java.lang.IllegalStateException:范围策略未设定。请调用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(Applicatio nFilterChain.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 $ AbstractConnectionH andler.process(AbstractProtocol.java:589)
org.apache.tomcat.util.net.JIoEndpoint $ SocketProcessor.run(JIoEndpoint.java:312)
java.util.concurrent.ThreadPoolExecutor.runWorker(未知源)
java.util.concurrent.ThreadPoolExecutor $ Worker.run(Unknown Source)
java.lang.Thread.run(未知来源)


java .lang.RuntimeException:java.lang.IllegalStateException:范围策略未设置。请调用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(ObjectFacto ry.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。准备(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.jav a: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(Abstract Http11Processor.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(未知源)
java.util.concurrent.ThreadPoolExecutor $ Worker.run(Unknown Source)
java.lang.Thread。 run(Unknown Source)


java.lang.IllegalStateException:范围策略未设置。请调用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:
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来源)
java.lang.Thread.run(未知来源)

异常说我需要设置范围策略。所以,我的问题是这个范围策略是什么,以及如何在我的简单应用程序中实现。另外,有注释 @Scoped ,我的情况下如何应用注释?



我的示例参考:


  1. bean配置


解决方案

让我们从看看什么是$ c> Scope.Strategy 通过查看文档。它说


可插拔范围设定策略。使用户能够提供请求,会话和向导范围的自定义
实现。实现和
传递给
Container.setScopeStrategy(com.opensymphony.xwork2.inject.Scope.Strategy)


好的,假设我想实现会话范围。然后我需要知道我可以实现的地方。该框架具有扩展点,您可以在哪里插入扩展,或者只是扩展默认实现并提供自己的自定义实现。这可以通过查看 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();
返回代理;
}
}

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实现Scope.Strategy {

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

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

ActionContext context = ActionContext.getContext();
会话映射< 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(类< T> type,String name,Callable<?extends T>工厂)throws Exception {
return null;
}
}

在配置文件 struts你应该设置属性

 < constant name =struts.actionProxyFactoryvalue = jspbean.struts.factory.MyActionProxyFactory/> 

这就是你需要注入一个bean Session 与会话范围。可以对其他范围进行类似的实现。注意,像singlton(默认使用),线程和默认的其他范围似乎不需要这种可插拔扩展。最后一个字是关于 @Scoped 注释。如果您通过xml配置提供bean,则不会使用它。但是,如果您以任何其他方式向bean提供 ContainerBuilder ,则可以在其上查找注释并设置相应的范围。


Recently I needed to use DI in Struts2. I know it uses it's own DI implementation like Guice but not Guice, as far as I couldn't find some annotations suitable to set the scope for injected beans. To be short, I created a 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;
    }
}

I have commented the annotations used with Spring beans. I was successfully created the same bean via spring DI and set the scope in which my objects were injected. Now, I want to do the same with Struts2 and DI. For this purpose I created the bean definition in struts.xml

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

and simple action to get that bean created and injected into my action

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;
    }
}

in the JSP I use simple iterator over session bean

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

Now, when I'm running this smple application I've got the exception

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)

The exception says that I need to set the scope strategy. So, my question is what is this scope strategy and how it could be implemented in my simple application. Also, there is annotation @Scoped, how this annotations to apply in my case?

My example references:

  1. bean configuration

解决方案

Let's start from looking what is a Scope.Strategy by looking at the docs. It says

Pluggable scoping strategy. Enables users to provide custom implementations of request, session, and wizard scopes. Implement and pass to Container.setScopeStrategy(com.opensymphony.xwork2.inject.Scope.Strategy)

Ok, assume I want to implement session scope. Then I need to know the place where I could implement it. The framework has it's extension points where where you could plug your extensions or simply extend the default implementation and provide your own custom implementations. This is easy done via looking at the BeanSelectionProvider. Then analyzing the stacktraces I decided the best point would be to extend the DefaultActionProxyFactory. Extending it requires to extend the DefaultActionProxy also.

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;
    }
}

In the configuration file struts.xml you should set the property

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

That's all you need to inject a bean Session with the session scope. Similar implementations could be done for other scopes. Notice, that other scopes like singlton (used by default), thread, and default seems don't require such pluggable extension. And the last word is about @Scoped annotation. It's not used if you provide the beans via xml configuration. But if you supply the ContainerBuilder with the bean in any other way it's able to find annotation on it and set the corresponding scope.

这篇关于Struts2中的依赖注入访问会话范围的bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆