JSF Lifecycle и пользовательские компоненты - PullRequest
17 голосов
/ 29 августа 2008

Есть несколько вещей, которые мне трудно понять в связи с разработкой пользовательских компонентов в JSF. Для целей этих вопросов можно предположить, что все пользовательские элементы управления используют привязки значений / выражения (не буквальные привязки), но мне также интересны пояснения к ним.

  1. Где я могу установить значение для привязки значений? Это должно произойти в декодировании? Или декодировать нужно сделать что-то еще, а затем установить значение в encodeBegin?
  2. Чтение из привязки значений - когда мне нужно читать данные из привязки значений или читать из переданного значения и помещать их в привязку значений?
  3. Когда слушатели действия в формах вызываются по отношению ко всему этому? На всех страницах жизненного цикла JSF упоминаются события, происходящие на разных этапах, но мне не совсем ясно, когда просто вызывается простой слушатель командной кнопки

Я пробовал несколько комбинаций, но всегда получаю трудно найти ошибки, которые, как мне кажется, происходят из-за основных недоразумений жизненного цикла события.

Ответы [ 4 ]

19 голосов
/ 29 августа 2008

В спецификации JSF есть довольно хорошая диаграмма, которая показывает жизненный цикл запроса - это важно для понимания этого.

Шаги:

  • Восстановить вид . Дерево UIComponent перестраивается.
  • Применить значения запроса . Редактируемые компоненты должны реализовывать EditableValueHolder. Этот этап проходит по дереву компонентов и вызывает методы processDecodes . Если компонент не является чем-то сложным, как UIData, он ничего не сделает, кроме как вызовет собственный метод decode . Метод decode ничего не делает, кроме как находит его средство визуализации и вызывает его метод decode , передавая себя в качестве аргумента. Задача средства визуализации - получить любое переданное значение и установить его с помощью setSubmittedValue .
  • Проверки процесса . Эта фаза вызывает processValidators , что вызывает validate . Метод validate принимает переданное значение, преобразует его с любыми преобразователями, проверяет его с помощью любых валидаторов и (при условии, что данные проходят эти тесты) вызывает setValue . Это сохранит значение как локальную переменную. Хотя эта локальная переменная не равна нулю, она будет возвращена, а не значение из привязки значения для любых вызовов getValue .
  • Обновление значений модели . Эта фаза вызывает processUpdates . Во входном компоненте это вызовет updateModel , который получит ValueExpression и вызовет его для установки значения в модели.
  • Вызов приложения . Здесь будут вызываться прослушиватели событий кнопок и т. Д. (Как и навигация, если память служит).
  • Render Response . Дерево отображается через средства визуализации, и состояние сохраняется.
  • Если какой-либо из этих этапов завершится неудачно (например, значение недопустимо), жизненный цикл переходит к ответу визуализации.
  • После большинства этих фаз могут запускаться различные события, при необходимости вызывая прослушиватели (например, прослушиватели изменения значения после проверки процесса).

Это несколько упрощенная версия событий. Обратитесь к спецификации для получения более подробной информации.

Я бы спросил, почему вы пишете свой собственный UIComponent. Это нетривиальная задача, и для ее правильного понимания требуется глубокое понимание архитектуры JSF. Если вам нужен пользовательский элемент управления, лучше создать конкретный элемент управления, который расширяет существующий UIComponent (как это делает HtmlInputText) с помощью эквивалентного средства визуализации.

Если заражение не является проблемой, существует реализация JSF с открытым исходным кодом в форме Apache MyFaces.

3 голосов
/ 29 августа 2008

Слушатели действий, такие как CommandButton , вызываются во время фазы Invoke Application , которая является последней фазой перед последней фазой Responder Response . Это показано в Жизненный цикл JSF - рисунок 1 .

2 голосов
/ 29 августа 2008

Это единственная структура, которую я имею когда-либо использовался там, где создание компонента глубокий сложный процесс, как это. Ни один из других веб-фреймворков (в мире .net или нет) сделать это так больно, что совершенно необъяснимо для меня.

Некоторые из проектных решений, стоящих за JSF, начинают обретать немного больше смысла, когда вы рассматриваете цели. JSF был спроектирован так, чтобы его можно было обрабатывать - он предоставляет множество метаданных для IDE. JSF - это не веб-фреймворк - это фреймворк MVP , который можно использовать в качестве веб-фреймворка. JSF обладает широкими возможностями расширения и настройки - вы можете заменить 90% реализации для каждого приложения.

Большая часть этого материала только усложняет вашу работу, если все, что вам нужно, - это добавить дополнительный элемент управления HTML.

Компонент представляет собой композицию несколько входных текстовых (и других) баз компоненты, кстати.

Я предполагаю, что фрагменты страницы на основе JSP-инструментов / инструментов не соответствуют вашим требованиям.

Я хотел бы рассмотреть возможность использования UIComponentELTag.createComponent для создания составного элемента управления с базой UIPanel и создания всех его дочерних элементов из существующих реализаций. (Я предполагаю, что вы используете JSP / taglibs и делаете несколько других предположений.) Возможно, вы захотите использовать пользовательский рендер, если бы ни один из существующих рендеров UIPanel не выполнил эту работу, но рендеры просты.

1 голос
/ 16 сентября 2008

Лучшая статья, которую я нашел, это Jsf Component Writing , что касается 2, где я должен прочитать значение для привязки значения в вашем компоненте, у вас есть геттер, который выглядит следующим образом


public String getBar() {  
     if (null != this.bar) {  
         return this.bar ;  
     }  
     ValueBinding _vb = getValueBinding("bar");  
     return (_vb != null) ? (bar) _vb.getValue(getFacesContext()) : null;  
}
  

как это попало в getValueBinding? В вашем классе тэгов метод setProperties

  if (bar!= null) {  
         if (isValueReference(bar)) {  
             ValueBinding vb = Util.getValueBinding(bar);  
             foo.setValueBinding("bar", vb);  
         } else {  
             throw new IllegalStateException("The value for 'bar' must be a ValueBinding.");  
         }  
     }  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...