2009-02-12 2 views
1

На самом деле в моем JSF приложения у меня есть этот код для вычисления компонент ClientId от его ID:Эффективный способ вычисления идентификатора клиента UIComponent?

public static String getComponentClientId(String id) { 
    try { 
    FacesContext fctx = FacesContext.getCurrentInstance(); 
    UIComponent found = getComponentWithId(fctx.getViewRoot(), id); 
    if (found!=null) 
     return found.getClientId(fctx);   
    else 
     return null; 
    } catch (Exception e) { 
    return null; 
    }  
} 
public static UIComponent getComponentWithId(UIComponent parent, String id) { 
    for (Iterator<UIComponent> chs = parent.getFacetsAndChildren(); chs.hasNext();) { 
    UIComponent ch = chs.next(); 
    if (ch.getId().equalsIgnoreCase(id)) 
    return ch;  
    else { 
    UIComponent found = getComponentWithId(ch, id); 
    if (found!=null) 
     return found; 
    } 
    } 
    return null; 
} 

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

+0

FYI: этот алгоритм будет работать только в том случае, если идентификатор уникален для представления.Возвращаясь к спецификации недавно, я заметил, что идентификаторы компонентов должны быть уникальными только для ближайшего NamingContainer. – McDowell

ответ

1

Не знаю, о чем я знаю.

трудно кэшировать эту информацию, потому что:

  1. Взаимосвязь между экземпляром UIComponent и его ClientID сек может быть 1: N. Это необходимо для таких компонентов, как UIData, которые управляют состоянием их детей. Возвращаемое значение от getClientId может быть контекстно-зависимым.
  2. Срок службы UIComponent экземпляр, вероятно, не будет превышать запрос. Некоторые реализации StateManager могут быть сконфигурированы так, чтобы сохранять состояние просмотра в сеансе, и в этом случае время жизни объектов может быть больше, но заставляя ваш код полагаться на это делает его хрупким, и было бы легко ввести утечки памяти.
  3. Виды могут быть динамическими. По общему признанию, это кросс-кейс, но программно можно использовать add, remove and move.

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


Вы не говорите, что вам нужен ClientId с для, но я предполагаю, что для некоторой формы поддержки JavaScript. Рассмотрим writing a custom component и выпустите свою разметку через свой рендер. Это можно использовать с атрибутом for, аналогичным label control. Найти соседа в том же NamingContainer относительно легко. Вы можете использовать код, как это в вашей реализации визуализатора:

// untested code! 
String clientId = mycomponent.getClientId(context); 
// get id of target control 
String _for = mycomponent.getFor(); 
int n = clientId.lastIndexOf(NamingContainer.SEPARATOR_CHAR); 
String targetClientId = clientId.substring(0, n) 
     + NamingContainer.SEPARATOR_CHAR + _for; 
ResponseWriter writer = context.getResponseWriter(); 
// write markup 

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

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


EDIT:

Я думал об этом в минувшие выходные. Поскольку 50% запросов JSF, похоже, касаются того, как работать с идентификаторами, я написал сообщение, поэтому я могу просто сослаться на него - JSF: working with component IDs. В состав включен механизм кэширования идентификаторов (вид!) с некоторым примером кода.

+0

Спасибо, Макдауэлл. Мне нужны идентификаторы клиентов только для отправки сообщений для правильного компонента. Я не хочу привязывать каждый компонент к моему бэкбону: это правильный подход? –

+0

Посмотрите функции taglib (см. Ссылку на блог). Если вы сможете улучшить свои решения, мне было бы интересно услышать об этом. – McDowell

Смежные вопросы