2012-04-27 3 views
11

У меня есть несколько страниц, которые нужны идент для работы, таким образом, следующий код:Обработка параметров вида в JSF после поста

userpage.xhtml

<!-- xmlns etc. omitted --> 
<html> 
<f:metadata> 
    <f:viewParam name="userId" value="#{userPageController.userId}"/> 
</f:metadata> 
<f:view contentType="text/html"> 
<h:head> 
</h:head> 
<h:body> 
    <h:form> 
     <h:commandButton action="#{userPageController.doAction}" value="post"/> 
    </h:form> 
</h:body> 
</f:view> 

userPageController.java

@Named 
@ViewScoped 
public class userPageControllerimplements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Inject protected SessionController sessionController; 
    @Inject private SecurityContext securityContext; 
    @Inject protected UserDAO userDAO; 

    protected User user; 
    protected Long userId; 

    public UserPage() { 
    } 

    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    public Long getUserId() { 
     return userId; 
    } 

    public void setUserId(Long userId) { 
     if(!FacesContext.getCurrentInstance().isPostback()){ 
      User u = userDAO.find(userId); 
      this.userId = userId; 
      this.user = u; 
     } 
    } 

    public void doAction(){ 

    } 

} 

Однако, после вызова doAction, параметр вида в URL-адресе исчезает. Боб все еще работает из-за своей видимой природы, но он разрушает мои попытки будущей навигации. Когда я ищу вокруг, у меня создается впечатление, что параметр просмотра должен оставаться после сообщения, таким образом, считывая userpage.jsf? UserId = 123, но это не так. Каково действительно предполагаемое поведение?

В связи с этим я попытался реализовать автоматическое добавление параметров вида при переходе на другую страницу, где я хочу сохранить userId. Кажется, что это работает для других, но для меня userId в ViewRoot всегда имеет значение null. Код ниже используется для получения viewparameter (я знаю, что я мог бы использовать мою временно сохраненную USERID в компоненте для навигации, но это решение было бы гораздо любителя):

String name = "userId"; 
    FacesContext ctx = FacesContext.getCurrentInstance(); 
    ViewDeclarationLanguage vdl = ctx.getApplication().getViewHandler().getViewDeclarationLanguage(ctx, viewId); 
    ViewMetadata viewMetadata = vdl.getViewMetadata(ctx, viewId); 
    UIViewRoot viewRoot = viewMetadata.createMetadataView(ctx); 
    UIComponent metadataFacet = viewRoot.getFacet(UIViewRoot.METADATA_FACET_NAME); 

    // Looking for a view parameter with the specified name 
    UIViewParameter viewParam = null; 
    for (UIComponent child : metadataFacet.getChildren()) { 
     if (child instanceof UIViewParameter) { 
      UIViewParameter tempViewParam = (UIViewParameter) child; 
      if (name.equals(tempViewParam.getName())) { 
       viewParam = tempViewParam; 
       break; 
      } 
     } 
    } 

    if (viewParam == null) { 
     throw new FacesException("Unknown parameter: '" + name + "' for view: " + viewId); 
    } 

    // Getting the value 
    String value = viewParam.getStringValue(ctx); // This seems to ALWAYS be null. 

Одна последней мысли о том, что методы сеттера до сих пор, кажется, work, setUserId вызывается с правильным значением в сообщении.

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

ответ

25

Когда я искать вокруг, я получаю впечатление, что параметр вид должен оставаться после того, как таким образом, после прочтения userpage.jsf? USERID = 123, но это не так. Каково действительно предполагаемое поведение?

Это поведение является правильным. <h:form> генерирует элемент HTML <form> с URL-адресом действия без любых параметров просмотра. Запрос POST просто отправляет именно этот URL. Если вы намерены сохранить параметры представления в URL-адресе, то есть в основном 3 способа:

  1. Принесите некоторую магию ajax.

    <h:commandButton action="#{userPageController.doAction}" value="post"> 
        <f:ajax execute="@form" render="@form" /> 
    </h:commandButton> 
    

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

  2. Если применимо (например, для навигации по страницам), сделайте запрос GET и используйте includeViewParams=true. Вы можете использовать <h:link> и <h:button> для этого:

    <h:button outcome="nextview?includeViewParams=true" value="post" /> 
    

    Однако это имеет безопасность EL использовать в версиях Mojarra старше 2.1.6. Убедитесь, что вы используете Mojarra 2.1.6 или новее. См. Также issue 2247.

  3. Управление генерации URL-адреса действия <h:form> самостоятельно.Предоставьте обычай ViewHandler (просто увеличьте ViewHandlerWrapper), в котором вы выполняете задание в getActionURL().

    public String getActionURL(FacesContext context, String viewId) { 
        String originalActionURL = super.getActionURL(context, viewId); 
        String newActionURL = includeViewParamsIfNecessary(context, originalActionURL); 
        return newActionURL; 
    } 
    

    Чтобы его запустить, зарегистрировать его в faces-config.xml следующим образом:

    <application> 
        <view-handler>com.example.YourCustomViewHandler</view-handler> 
    </application> 
    

    Это также то, что OmniFaces<o:form> делает. Он поддерживает дополнительный includeViewParams атрибут, который включает в себя все параметры просмотра в URL действий формы по:

    <o:form includeViewParams="true"> 
    

Update: получение параметров вида текущего вида программно (что в основном ваш второй вопрос) должно быть сделано следующим образом:

Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(FacesContext.getCurrentInstance().getViewRoot()); 

for (UIViewParameter viewParam : viewParams) { 
    String name = viewParam.getName(); 
    Object value = viewParam.getValue(); 
    // ... 
} 
+0

Я думаю, третий один хорошо известные варианты. – kosa

+0

Я, вероятно, использую 1. для обработки проблемы с строкой url. Примерно 2: это было бы чистое решение для просмотра обработки параметров, но оно работает только при использовании одного и того же управляемого компонента для 2-х страниц (что, по-моему, обычно является плохим выбором), что делает его бесполезным. Скорее всего, я просто определяю параметры вручную в каждой ссылке. Есть ли у вас какие-либо идеи, что код внизу не работает? Получить параметр вида программно, что есть. –

+0

Это потому, что вы создаете совершенно новый вид и вместо текущего представления. См. Обновленный ответ. – BalusC

0

Правильно ли я, что для решения 1 <f:ajax execute="@form" render="@form" /> к ш орк один также будет включать что-то вроде

<f:param name="userId" value="#{userPageController.userId}"/> 

внутри <h:commandButton>?

Как описано в https://stackoverflow.com/a/14026995/811046

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