当restored view 在postback 期间返回null 时,您可以手动create 和build 视图。您可以在自定义 ViewHandler 中执行此操作。这是一个启动示例:
public class RestorableViewHandler extends ViewHandlerWrapper {
private ViewHandler wrapped;
public RestorableViewHandler(ViewHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public UIViewRoot restoreView(FacesContext context, String viewId) {
UIViewRoot restoredView = wrapped.restoreView(context, viewId);
if (!(restoredView == null && context.isPostback())) {
return restoredView;
}
UIViewRoot createdView = createView(context, viewId);
context.setViewRoot(createdView);
try {
getViewDeclarationLanguage(context, viewId).buildView(context, createdView);
} catch (IOException e) {
throw new FacesException(e);
}
return createdView;
}
@Override
public ViewHandler getWrapped() {
return wrapped;
}
}
您可能希望扩展if 检查以检查viewId 是否代表登录页面。
要让它运行,在faces-config.xml注册它如下:
<application>
<view-handler>com.example.RestorableViewHandler</view-handler>
</application>
但是存在技术限制:重新创建的视图与初始请求期间完全相同,因此此后对 JSF 组件树进行的任何修改,无论是通过标记处理程序还是基于某些视图的条件渲染组件,甚至会话范围的变量,完全丢失。为了准确地重新创建所需的视图,您需要确保这些修改是基于请求范围的变量(阅读:请求参数)而不是视图或会话范围的变量。
换句话说,视图的状态不应依赖于视图或会话范围的托管 bean,而应纯粹依赖于请求范围的托管 bean。
更新:OmniFaces JSF 实用程序库在当前 1.3 快照中具有 <o:enableRestorableView> 风格的可重用解决方案,可以嵌入到 <f:metadata> 中。另请参阅 <o:enableRestorableView> showcase page on snapshot site 以获取演示。