Dependency Injection in Struts2 Accessing Session Scoped Beans

不打扰是莪最后的温柔 提交于 2019-11-26 13:51:23

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.

I believe Luiggi's comment is correct. The "@Inject" needs to be on the field value itself, not on the setter.

 @Inject("session")
 private Session session;

As long as you've got the "session" bean defined in struts.xml or registered it with the Struts container it should be able to find it and inject it. From your explanation that seems to be the case.

For some more specific information check this Discussion on the Struts User list: Struts user question on built-in DI

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!