如何在需要时保存和检索视图

时间:2014-11-20 12:27:42

标签: google-app-engine jsf jsf-2.2

我的目标是尽可能减小会话大小。 (为什么?它是其他主题)。 我所拥有的是faces-config.xml

中声明的阶段监听器
<lifecycle>
        <phase-listener>mypackage.listener.PhaseListener</phase-listener>   
</lifecycle>

我想在一些内存缓存中保存除最后一个(最多两个)之外的所有其他视图。获取会话地图:

Map<String, Object> sessionMap = event.getFacesContext().getExternalContext().getSessionMap();
在beforePhase(PhaseEvent事件)方法中的

让我可以访问所有视图。所以在这里我可以将所有视图保存到memcache并从会话中删除它们。问题是在jsf中请求仍然在浏览器中加载的这些视图,以便我可以在需要时重新填充此视图。有可能吗?谢谢。

1 个答案:

答案 0 :(得分:4)

要解决问题的核心问题,请实施ViewHandler,您可以在其中控制RESTORE_VIEWRENDER_RESPONSE阶段/流程。您将在RENDER_RESPONSE期间保存视图,并在RESTORE_VIEW阶段有选择地恢复。您的视图处理程序可能类似于以下

   public class CustomViewHandlerImpl extends ViewHandlerWrapper{

        @Inject ViewStore viewStore; //hypothetical storage for the views. Could be anything, like a ConcurrentHashMap
        ViewHandler wrapped;

        public CustomViewHandlerImpl(ViewHandler toWrap){          
           this.wrapped = toWrap;
        }

        public UIViewRoot restoreView(FacesContext context, String viewId) throws IOException{

            //this assumes you've previously saved the view, using the viewId

            UIViewRoot theView = viewStore.get(viewId);

            if(theView == null){

               theView = getWrapped().restoreView(context, viewId);              
            }

           return theView;       
        } 


      public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException{

          viewStore.put(viewToRender.getId(),viewToRender);

          getWrapped().renderView(context, viewToRender);

      }

   }

只需使用

插入自定义viewhandler即可
<view-handler>com.you.customs.CustomViewHandlerImpl</view-handler>

当然,你可能不想对你的所有观点给予这种处理;您可以自由地为上面的逻辑添加任何条件,以实现条件视图保存和恢复。


您还应该考虑其他选择。您似乎在这里将问题混为一谈。如果您的真正关注是限制与视图处理相关的开销,则应考虑

  1. 无状态视图,JSF-2.2的新功能。无状态视图选项允许您从JSF视图保存机制中排除特定页面,只需在transient="true"上指定f:view即可。比手工修剪UIViewRoot要简洁得多。需要注意的是,无状态视图不能由依赖于状态保存的范围支持,即@ViewScoped。在无状态视图中,将为每个回发重新创建@ViewScoped bean。 Ajax功能在这种情况下也会受到影响,因为状态保存是ajax操作的支柱。

  2. 有选择地将标记组件设置为transient 瞬态属性可用于所有UIComponents,这意味着,基于每个视图,您可以标记特定的具有transient="true"的组件,有效地为您提供与1)相同的好处,但范围要小得多。没有没有ViewScoped的缺点

  3. 编辑:由于某种原因,UIViewRoot#getViewId()未返回当前视图的名称(这可能是一个错误)。或者,您可以使用

    ExternalContext extCtxt = FacesContext.getCurrentInstance().getExternalContext();
    String viewName = ((HttpServletRequest)extCtxt.getRequest()).getRequestURI();  //use this id as the key to store your views instead