我的目标是尽可能减小会话大小。 (为什么?它是其他主题)。 我所拥有的是faces-config.xml
中声明的阶段监听器<lifecycle>
<phase-listener>mypackage.listener.PhaseListener</phase-listener>
</lifecycle>
我想在一些内存缓存中保存除最后一个(最多两个)之外的所有其他视图。获取会话地图:
Map<String, Object> sessionMap = event.getFacesContext().getExternalContext().getSessionMap();
在beforePhase(PhaseEvent事件)方法中的让我可以访问所有视图。所以在这里我可以将所有视图保存到memcache并从会话中删除它们。问题是在jsf中请求仍然在浏览器中加载的这些视图,以便我可以在需要时重新填充此视图。有可能吗?谢谢。
答案 0 :(得分:4)
要解决问题的核心问题,请实施ViewHandler
,您可以在其中控制RESTORE_VIEW
和RENDER_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>
当然,你可能不想对你的所有观点给予这种处理;您可以自由地为上面的逻辑添加任何条件,以实现条件视图保存和恢复。
您还应该考虑其他选择。您似乎在这里将问题混为一谈。如果您的真正关注是限制与视图处理相关的开销,则应考虑
无状态视图,JSF-2.2的新功能。无状态视图选项允许您从JSF视图保存机制中排除特定页面,只需在transient="true"
上指定f:view
即可。比手工修剪UIViewRoot
要简洁得多。需要注意的是,无状态视图不能由依赖于状态保存的范围支持,即@ViewScoped
。在无状态视图中,将为每个回发重新创建@ViewScoped
bean。 Ajax功能在这种情况下也会受到影响,因为状态保存是ajax操作的支柱。
有选择地将标记组件设置为transient
瞬态属性可用于所有UIComponents
,这意味着,基于每个视图,您可以标记特定的具有transient="true"
的组件,有效地为您提供与1)相同的好处,但范围要小得多。没有没有ViewScoped的缺点
编辑:由于某种原因,UIViewRoot#getViewId()
未返回当前视图的名称(这可能是一个错误)。或者,您可以使用
ExternalContext extCtxt = FacesContext.getCurrentInstance().getExternalContext();
String viewName = ((HttpServletRequest)extCtxt.getRequest()).getRequestURI(); //use this id as the key to store your views instead