Как сохранить и восстановить вид, когда это необходимо
Моя цель - сохранить размер сессии как можно меньше. (Почему?.. это другая тема). То, что я имею, является слушателем фазы, объявленным в face-config.xml
<lifecycle>
<phase-listener>mypackage.listener.PhaseListener</phase-listener>
</lifecycle>
Я хочу сохранить все другие представления, кроме последнего (максимум два), в некотором memcache. Получение карты сеанса:
Map<String, Object> sessionMap = event.getFacesContext().getExternalContext().getSessionMap();
Метод beforePhase(событие PhaseEvent) предоставляет мне доступ ко всем представлениям. Поэтому здесь я могу сохранить все представления в memcache и удалить их из сеанса. Вопрос в том, где в jsf запрашиваются эти представления, которые все еще загружены в браузере, чтобы я мог заполнить это представление, если оно необходимо. Это вообще возможно? Спасибо.
1 ответ
Чтобы решить суть вашего вопроса, реализуйте 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);
}
}
Просто подключите свой собственный видоискатель, используя
<view-handler>com.you.customs.CustomViewHandlerImpl</view-handler>
Конечно, вы, вероятно, не хотите относиться к этому лечению со всеми вашими взглядами; Вы можете добавлять любые условия к логике выше, чтобы реализовать сохранение и восстановление условных представлений.
Вы должны также рассмотреть другие варианты. Похоже, что вы смешиваете вопросы здесь. Если ваша настоящая проблема заключается в ограничении накладных расходов, связанных с обработкой представления, вам следует рассмотреть
Просмотры без состояния, новые с JSF-2.2. Параметр представления без сохранения состояния позволяет исключить определенные страницы из механизма сохранения представления JSF, просто указав
transient="true"
наf:view
, Гораздо чище, чем калечитьUIViewRoot
рукой. Предостережение заключается в том, что представление без состояния не может быть подкреплено областями, которые зависят от сохранения состояния, т.е.@ViewScoped
, В представлении без гражданства@ViewScoped
боб будет воссоздан для каждого постбэка. Функциональность 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