Spring 3 and the JSF 2 View Scope(spring 2及JSF 2 bean作用域) - weijiguang/OA GitHub Wiki
Spring 3 and the JSF 2 View Scope Introduction In addition to the existing JSF 1.x scopes – Request, Session, and Application, JSF 2 introduced two new scopes to the managed bean lifecycle.
View Scope This scope persists the state of request parameters in the FacesContext View Map until the current view being rendered is discarded. As long as a user is interacting with the current page, request parameter state is maintained.
Flash Scope First seen in the Ruby on Rails framework, this scope is for short lived conversations that only need to propagate parameters from one request to the next in the request processing lifecycle. Thereafter, the state of request parameters is discarded from the FacesContext View Map.
Implementing the JSF View Scope in Spring 3 Spring 3 supports the following bean scopes out-of-the-box:
singleton – Scopes a single bean definition to a single object instance per Spring IoC container. prototype – Scopes a single bean definition to any number of object instances. request – Scopes a single bean definition to the lifecycle of a single HTTP request; that is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext. session – Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext. globalSession – Scopes a single bean definition to the lifecycle of a global HTTP Session. Typically only valid when used in a portlet context. Only valid in the context of a web-aware Spring ApplicationContext. In addition to the above scopes it is possible to create custom scopes. To support the JSF2 managed bean View Scope in the Spring Spring IoC container it is necessary to create a custom scope which implements the org.springframework.beans.factory.config.Scope interface. Beans created using this interface should then be registered with the Spring Custom Scope Configurer.
First, create the View Scope bean implementing the required logic for the get() and remove() methods.
`import java.util.Map; import javax.faces.context.FacesContext; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.config.Scope;
public class ViewScope implements Scope {
public Object get(String name, ObjectFactory<?> objectFactory) {
if (FacesContext.getCurrentInstance().getViewRoot() != null) {
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
if (viewMap.containsKey(name)) {
return viewMap.get(name);
} else {
Object object = objectFactory.getObject();
viewMap.put(name, object);
return object;
}
} else {
return null;
}
}
public Object remove(String name) {
if (FacesContext.getCurrentInstance().getViewRoot() != null) {
return FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(name);
} else {
return null;
}
}
public void registerDestructionCallback(String name, Runnable callback) {
}
public Object resolveContextualObject(String key) {
return null;
}
public String getConversationId() {
return null;
}
}`
To enable the View Scope implementation in your web application, register the custom Scope implementation in your application context.
`
<b:beans xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<b:bean
class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<b:property name="scopes">
<b:map>
<b:entry key="view">
<b:bean class="net.comdynamics.myapp.web.spring.customscope.ViewScope" />
<!--ajax方式删除链接。触发时弹出确认对话框并通过ajax参数更新页面bean的指定属性值。
如果bean的scope为request或更小的作用域。该值在结束本次ajax参数调用后不再维持(即丢失)。
要维持页面参数bean的scope最低应为view级别的作用域。
-->
</b:entry>
</b:map>
</b:property>
</b:bean>
</b:beans> `
If you specify @Scope("view") in your managed bean and the JSF page is loaded, failure to register the custom scope bean in your Spring application context will result in an error similar to the following:
javax.servlet.ServletException: No Scope registered for scope 'view' javax.faces.webapp.FacesServlet.service(FacesServlet.java:323)
The following class from a previous article on the JSF2 JSR-330 annotations has been updated to use the new View Scope in the @Scope annotation.
` package net.comdynamics.myapp.web;
import javax.inject.Named; import org.springframework.context.annotation.Scope;
/**
-
ReportListPage JSF backing bean. */ @Named("reportListPage") @Scope("view") public class ReportListPage extends BasePage {
@Inject @Named("reportService") private ReportService reportService;
public ReportListPage() { }
public ReportService getReportService() { return reportService; }
public void setReportService(ReportService ReportService) { this.reportService = reportService; }
// etc…
}
` When the user loads the page bound to the above backing bean, request parameters entered in form fields will be persisted in the FacesContext View Map on form submissions until they navigate to another page in the application.
Support for the JSF 2 View Scope in Spring 3 can be realised by implementing a custom Scope and registering it as a bean in the Spring application context.