首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring请求范围和JSF请求范围之间的区别?

Spring请求范围和JSF请求范围之间的区别?
EN

Stack Overflow用户
提问于 2013-09-09 21:17:02
回答 2查看 1.3K关注 0票数 0

我正在开发一个使用JSF1.2的JSR-286 portlet应用程序。我正在努力将JSF管理的bean迁移到Spring,并且我注意到Spring处理请求作用域与JSF处理请求作用域的方式有什么不同。

在我的portlet应用程序中,我有两个驻留在同一个页面上的portlet,它们都使用相同的JSF页面视图。当我使用JSF托管请求bean时,会为每个portlet创建一个单独的请求bean,这就是我正在寻找的行为。当我使用Spring时,只创建一个请求bean,并在两个portlets之间共享。这是正常行为吗?我能阻止它这样做吗?

在将bean移到Spring之前,我的原始faces-config.xml文件:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
version="1.2">
<application>
    <state-manager>com.ibm.faces.application.DevelopmentStateManager</state-manager>
    <variable-resolver>com.ibm.faces.portlet.PortletVariableResolver</variable-resolver>
</application>
<factory>
    <faces-context-factory>com.ibm.faces.context.AjaxFacesContextFactory</faces-context-factory>
    <render-kit-factory>com.ibm.faces.renderkit.AjaxRenderKitFactory</render-kit-factory>
</factory>

<managed-bean>
    <managed-bean-name>sessionBean</managed-bean-name>
    <managed-bean-class>sanitycheck.SessionBean</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

<managed-bean>
    <managed-bean-name>pc_SanityCheckProjectView</managed-bean-name>
    <managed-bean-class>sanitycheck.SanityCheckProjectView</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
        <property-name>sessionBean</property-name>
        <value>#{sessionBean}</value>
    </managed-property>
</managed-bean>

<lifecycle>
    <phase-listener>com.ibm.faces.webapp.ValueResourcePhaseListener</phase-listener>
</lifecycle>

</faces-config>

在将bean移动到Spring之后,我的faces-config.xml文件:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>

<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
version="1.2">
<application>
    <state-manager>com.ibm.faces.application.DevelopmentStateManager</state-manager>
    <variable-resolver>com.ibm.faces.portlet.PortletVariableResolver</variable-resolver>
    <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
</application>
<factory>
    <faces-context-factory>com.ibm.faces.context.AjaxFacesContextFactory</faces-context-factory>
    <render-kit-factory>com.ibm.faces.renderkit.AjaxRenderKitFactory</render-kit-factory>
</factory>

<lifecycle>
    <phase-listener>com.ibm.faces.webapp.ValueResourcePhaseListener</phase-listener>
</lifecycle>

</faces-config>

以及我的spring-web.xml文件:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans         http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

<bean id="sessionBean" class="sanitycheck.SessionBean" scope="session">
               <aop:scoped-proxy/>
    </bean>

<bean id="pc_SanityCheckProjectView" class="pagecode.SanityCheckProjectView" scope="request" init-method="init">
               <aop:scoped-proxy/>
    <property name="sessionBean" ref="sessionBean"/>
</bean>
</beans>

如果需要的话,我可以提供我的其他文件,让我知道。谢谢!

编辑:添加aop:作用域-代理到Spring。

编辑:添加portlet.xml文件:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" id="com.ibm.faces.portlet.FacesPortlet.3a22ca3014">
<portlet>
    <portlet-name>SanityCheckProject</portlet-name>
    <display-name xml:lang="en">SanityCheckProject</display-name>
    <display-name>SanityCheckProject</display-name>
    <portlet-class>com.ibm.faces.portlet.FacesPortlet</portlet-class>
    <init-param>
        <name>com.ibm.faces.portlet.page.view</name>
        <value>/SanityCheckProjectView.jsp</value>
    </init-param>
    <init-param>
        <name>whichOne</name>
        <value>Portlet1</value>
    </init-param>
    <init-param>
        <name>wps.markup</name>
        <value>html</value>
    </init-param>
    <expiration-cache>0</expiration-cache>
    <supports>
        <mime-type>text/html</mime-type>
        <portlet-mode>view</portlet-mode>
    </supports>
    <supported-locale>en</supported-locale>
    <resource-bundle>com.ibm.sanitycheckproject.nl.SanityCheckProjectPortletResource</resource-bundle>
    <portlet-info>
        <title>SanityCheckProject</title>
        <short-title>SanityCheckProject</short-title>
        <keywords>SanityCheckProject</keywords>
    </portlet-info>
</portlet>
<portlet>
    <portlet-name>SanityCheckPortlet2</portlet-name>
    <display-name xml:lang="en">SanityCheckPortlet2</display-name>
    <display-name>SanityCheckPortlet2</display-name>
    <portlet-class>com.ibm.faces.portlet.FacesPortlet</portlet-class>
    <init-param>
        <name>com.ibm.faces.portlet.page.view</name>
        <value>/SanityCheckProjectView.jsp</value>
    </init-param>
    <init-param>
        <name>whichOne</name>
        <value>Portlet2</value>
    </init-param>
    <init-param>
        <name>wps.markup</name>
        <value>html</value>
    </init-param>
    <expiration-cache>0</expiration-cache>
    <supports>
        <mime-type>text/html</mime-type>
        <portlet-mode>view</portlet-mode>
    </supports>
    <supported-locale>en</supported-locale>
    <resource-bundle>com.ibm.sanitycheckproject.nl.SanityCheckPortlet2PortletResource</resource-bundle>
    <portlet-info>
        <title>SanityCheckPortlet2</title>
        <short-title>SanityCheckPortlet2</short-title>
        <keywords>SanityCheckPortlet2</keywords>
    </portlet-info>
</portlet>
<default-namespace>http://SanityCheckProject/</default-namespace>
</portlet-app>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-18 20:34:25

我不知道这是否是最好的解决方案,甚至是非常好的解决方案,但我最终所做的是创建两个自定义portlet作用域,一个用于请求作用域,另一个用于会话作用域。本质上,我的自定义作用域的作用是,它们在请求的对象的名称前加上portlet的名称空间,这似乎使所有内容都保持了分离。

下面是我为我的作用域使用的代码:

请求范围:

代码语言:javascript
复制
import javax.faces.context.FacesContext;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.web.context.request.RequestScope;
import com.ibm.faces.portlet.httpbridge.ActionResponseWrapper;
import javax.portlet.RenderResponse;
import javax.portlet.filter.RenderResponseWrapper;

public class PortletRequestScope extends RequestScope {

@Override
public Object get(String name, ObjectFactory objectFactory) {
    Object response = FacesContext.getCurrentInstance().getExternalContext().getResponse();
    if (response instanceof RenderResponse) {
        String namespace=((RenderResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        return super.get(namespace + name, objectFactory);
    }
    else if (response instanceof RenderResponseWrapper) {
        String namespace=((RenderResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        return super.get(namespace + name, objectFactory);
    }
    else if (response instanceof ActionResponseWrapper) {
        String namespace=((ActionResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        return super.get(namespace + name, objectFactory);
    }
    else {
        writeError(response);
    }
    return super.get(name, objectFactory);
}

@Override
public void registerDestructionCallback(String name, Runnable callback) {
    Object response = FacesContext.getCurrentInstance().getExternalContext().getResponse();
    if (response instanceof RenderResponse) {
        String namespace=((RenderResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        super.registerDestructionCallback(namespace+name, callback);
    }
    else if (response instanceof RenderResponseWrapper) {
        String namespace=((RenderResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        super.registerDestructionCallback(namespace+name, callback);
    }
    else if (response instanceof ActionResponseWrapper) {
        String namespace=((ActionResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        super.registerDestructionCallback(namespace+name, callback);
    }
    else {
        writeError(response);
    }
    super.registerDestructionCallback(name, callback);
}

@Override
public Object remove(String name) {
    Object response = FacesContext.getCurrentInstance().getExternalContext().getResponse();
    if (response instanceof RenderResponse) {
        String namespace=((RenderResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        return super.remove(namespace+name);
    }
    else if (response instanceof RenderResponseWrapper) {
        String namespace=((RenderResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        return super.remove(namespace+name);
    }
    else if (response instanceof ActionResponseWrapper) {
        String namespace=((ActionResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        return super.remove(namespace+name);
    }
    else {
        writeError(response);
    }
    return super.remove(name);
}

protected void writeError(Object response) {
    System.err.println("Error in PortletRequestScope");
    System.err.println("Response is unrecognized class: " + response.getClass().getCanonicalName());
    System.err.println("Please modify code to handle class");
}

}

会议范围:

代码语言:javascript
复制
import javax.faces.context.FacesContext;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.web.context.request.SessionScope;
import com.ibm.faces.portlet.httpbridge.ActionResponseWrapper;
import javax.portlet.RenderResponse;
import javax.portlet.filter.RenderResponseWrapper;

public class PortletSessionScope extends SessionScope {

@Override
public Object get(String name, ObjectFactory objectFactory) {
        Object response =  FacesContext.getCurrentInstance().getExternalContext().getResponse();
        if (response instanceof RenderResponse) {
            String namespace=((RenderResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
            return super.get(namespace + name, objectFactory);
        }
        else if (response instanceof RenderResponseWrapper) {
            String namespace=((RenderResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
            return super.get(namespace + name, objectFactory);
        }
        else if (response instanceof ActionResponseWrapper) {
            String namespace=((ActionResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
            return super.get(namespace + name, objectFactory);
        }
        else {
            writeError(response);
        }
    return super.get(name, objectFactory);
}

@Override
public void registerDestructionCallback(String name, Runnable callback) {
    Object response = FacesContext.getCurrentInstance().getExternalContext().getResponse();
    if (response instanceof RenderResponse) {
        String namespace=((RenderResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        super.registerDestructionCallback(namespace+name, callback);
    }
    else if (response instanceof RenderResponseWrapper) {
        String namespace=((RenderResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        super.registerDestructionCallback(namespace+name, callback);
    }
    else if (response instanceof ActionResponseWrapper) {
        String namespace=((ActionResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        super.registerDestructionCallback(namespace+name, callback);
    }
    else {
        writeError(response);
    }
    super.registerDestructionCallback(name, callback);
}

@Override
public Object remove(String name) {
    Object response = FacesContext.getCurrentInstance().getExternalContext().getResponse();
    if (response instanceof RenderResponse) {
        String namespace=((RenderResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        return super.remove(namespace+name);
    }
    else if (response instanceof RenderResponseWrapper) {
        String namespace=((RenderResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        return super.remove(namespace+name);
    }
    else if (response instanceof ActionResponseWrapper) {
        String namespace=((ActionResponseWrapper)FacesContext.getCurrentInstance().getExternalContext().getResponse()).getNamespace();
        return super.remove(namespace+name);
    }
    else {
        writeError(response);
    }
    return super.remove(name);
}

protected void writeError(Object response) {
    System.err.println("Error in PortletSessionScope");
    System.err.println("Response is unrecognized class: " + response.getClass().getCanonicalName());
    System.err.println("Please modify code to handle class");
}

}

然后,在spring-web.xml中,我定义了我的自定义范围:

代码语言:javascript
复制
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
    <map>
        <entry key="portletRequestScope">
            <bean class="com.test.scope.PortletRequestScope"/>
        </entry>
        <entry key="portletSessionScope">
            <bean class="com.test.portlet.scope.PortletSessionScope"/>
        </entry>
    </map>
</property>
</bean>

在定义实际Spring时,我使用了自定义作用域而不是常规作用域--例如:

代码语言:javascript
复制
<bean id="sessionBean" class="com.test.managedbeans.SessionBean"
scope="portletSessionScope" lazy-init="true"/>

至少,在我在WebSphere门户上使用JSF + Spring的特定情况下,这样做似乎是可行的,希望这将对其他人有所帮助。

票数 0
EN

Stack Overflow用户

发布于 2013-09-09 21:45:15

在Spring中,必须使用<aop:scoped-proxy/>标记。

http://static.springsource.org/spring/docs/3.0.x/reference/beans.html#beans-factory-scopes-other-injection

代码语言:javascript
复制
<!-- an HTTP Session-scoped bean exposed as a proxy -->
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
    <!-- this next element effects the proxying of the surrounding bean -->
    <aop:scoped-proxy/>
</bean>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18707169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档