google-app-engine - 如何在需要时保存和检索 View

标签 google-app-engine jsf jsf-2.2

我的目标是使 session 大小尽可能小。 (为什么?.. 这是另一个话题)。 我拥有的是在 faces-config.xml 中声明的相位监听器

<lifecycle>
        <phase-listener>mypackage.listener.PhaseListener</phase-listener>   
</lifecycle>

我想在一些内存缓存中保存所有其他 View ,除了最后一个(最多两个)。获取 session 映射:

Map<String, Object> sessionMap = event.getFacesContext().getExternalContext().getSessionMap();

在 beforePhase(PhaseEvent event) 方法中,我可以访问所有 View 。所以在这里我可以将所有 View 保存到内存缓存并从 session 中删除它们。问题是在 jsf 中,这些仍然加载在浏览器中的 View 在哪里被请求,以便我可以在需要时重新填充这个 View 。有可能吗?谢谢。

最佳答案

要解决您问题的核心,请实现 ViewHandler ,您可以在其中控制 RESTORE_VIEWRENDER_RESPONSE 阶段/过程。您将在 RENDER_RESPONSE 期间保存 View ,并在 RESTORE_VIEW 阶段有选择地恢复 View 。您的 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);

      }

   }

只需插入您的自定义 View 处理程序,使用

<view-handler>com.you.customs.CustomViewHandlerImpl</view-handler>

当然,您可能不想对所有 View 都进行这种处理;您可以在上述逻辑中自由添加任何条件,以实现有条件的 View 保存和恢复。


您还应该考虑其他选择。看来您在这里混淆了问题。如果您真正关心的是限制与 View 处理相关的开销,您应该考虑

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

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

编辑:出于某种原因,UIViewRoot#getViewId() 没有返回当前 View 的名称(这可能是一个错误)。或者,您可以使用

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

关于google-app-engine - 如何在需要时保存和检索 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27039642/

相关文章:

java - java 和 python 中的 Unicode 字符串支持

javascript - 无法使用 javascript 显示 jsf 隐藏的 panelGroup

mysql - 使用 JSF 从 MySQL 中删除行

jsf - 目标无法访问,在 JSF 2.2 中标识符解析为 null

google-app-engine - Google App Engine 上的 PIL 可以使用哪些系统字体?

java - 将数据写入App Engine项目中的离线数据存储,然后导出

python - 在 GAE 中存储对象列表

validation - 如何覆盖 OmniFaces 默认验证/转换错误消息?

java - 我们可以在 Apache tomcat 中使用 @EJB 注释吗?

jsf-2 - selectBooleanCheckbox 值在 ui 内未正确设置 :repeat