Может ли фрагментарная часть URL-адреса отображать текущую страницу в JSF? [Дубликат]

Ссылка NullReferenceException или Object, не установленная на экземпляр объекта, возникает, когда объект класса, который вы пытаетесь использовать, не создается. Например:

Предположим, что у вас есть класс с именем Student.

public class Student
{
    private string FirstName;
    private string LastName;
    public string GetFullName()
    {
        return FirstName + LastName;
    }
}

Теперь рассмотрим другой класс, в котором вы пытаетесь получить полное имя учащегося.

public class StudentInfo
{      
    public string GetStudentName()
    {
        Student s;
        string fullname = s.GetFullName();
        return fullname;
    }        
}

Как видно из вышеприведенного кода, оператор Student s - объявляет только переменную типа Student, обратите внимание, что класс Student не создается в этой точке. Следовательно, когда выполняется выполнение инструкции s.GetFullName (), она выкинет исключение NullReferenceException.

16
задан BalusC 13 August 2010 в 14:37
поделиться

5 ответов

Вы можете сделать это с помощью window.onhashchange , который заполняет поле ввода скрытой формы, которое представляет собой асинхронно, когда поле ввода изменилось.

Вот начало Пример страницы Facelets:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>SO question 3475076</title>
        <script>
            window.onload = window.onhashchange = function() {
                var fragment = document.getElementById("processFragment:fragment");
                fragment.value = window.location.hash;
                fragment.onchange();
            }
        </script>
        <style>.hide { display: none; }</style>
    </h:head>
    <h:body>
        <h:form id="processFragment" class="hide">
            <h:inputText id="fragment" value="#{bean.fragment}">
                <f:ajax event="change" execute="@form" listener="#{bean.processFragment}" render=":showFragment" />
            </h:inputText>
        </h:form>
        <p>Change the fragment in the URL. Either manually or by those links:
            <a href="#foo">foo</a>, <a href="#bar">bar</a>, <a href="#baz">baz</a>
        </p>
        <p>Fragment is currently: <h:outputText id="showFragment" value="#{bean.fragment}" /></p>
    </h:body>
</html>

Вот как выглядит соответствующий компонент:

package com.stackoverflow.q3475076;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.event.AjaxBehaviorEvent;

@ManagedBean
@RequestScoped
public class Bean {

    private String fragment;

    public void processFragment(AjaxBehaviorEvent event) {
        // Do your thing here. This example is just printing to stdout.
        System.out.println("Process fragment: " + fragment);
    }

    public String getFragment() {
        return fragment;
    }

    public void setFragment(String fragment) {
        this.fragment = fragment;
    }

}

Вот и все.

Обратите внимание, что onhashchange событие является относительно новым и не поддерживается старыми браузерами. В случае отсутствия поддержки браузера (undefinied и т. Д.) Вы хотите проверить window.location.hash с интервалами, используя setInterval() . Приведенный выше пример кода должен, по крайней мере, дать хорошее начало. Он работает, по крайней мере, с FF3.6 и IE8.

8
ответ дан BalusC 28 August 2018 в 02:29
поделиться

Посмотрите этот вопрос и особенно ответы: JSP Сервлет-якорь

  • Фрагмент не отображается на сервере.
  • Вы можете извлечь фрагмент на стороне клиента, преобразовать его и отправить на сервер через Ajax.
1
ответ дан Community 28 August 2018 в 02:29
поделиться

Вот самый надежный способ извлечь фрагмент из синтаксически допустимого URL / URI.

 URI uri = new URI(someString);
 String fragment = uri.getFragment();

Как вы вставляете это в bean-компонент, будет зависеть от того, какую серверную структуру вы используете, и независимо от того, выполняете ли вы инъекцию, используя XML или аннотации, или делаете это программно.

3
ответ дан Stephen C 28 August 2018 в 02:29
поделиться
  • 1
    Спасибо за вашу идею. Я ищу способ поймать URL-адрес, когда есть перезагрузка страницы (GET), а не getFragment (), правильно разобрать его, чтобы получить значения и установить соответствующие переменные. – Choesang 13 August 2010 в 10:47
  • 2
    Все в порядке, что метод существует, но браузеры не отправляют информацию об фрагменте на сервер. Это можно увидеть, зарегистрировав HTTP-трафик. – pcjuzer 13 August 2010 в 11:41
  • 3
    Хотя это технически правильно, этот ответ практически и принципиально ошибочен. Фрагмент, установленный веб-браузером [, не будет ] ( ru.wikipedia.org/wiki/Fragment_identifier#Processing ) прибывает на веб-сервер. – BalusC 13 August 2010 в 12:19
  • 4
    Хорошая точка зрения. Однако вы можете отправлять URL-адрес с фрагментом ... если вы его кодируете и отправляете в качестве параметра запроса на другой URL-адрес. Вот как работают много инструментов для аннотаций и закладок. – Stephen C 13 August 2010 в 13:16

Фрагмент не может быть замечен с серверной стороны, к нему могут быть доступны только клиентские скрипты. Обычно это делается так, что серверная сторона генерирует непараметрированную страницу, которая затем модифицируется скриптами в соответствии с параметрами фрагмента. Сценарии могут делать запросы AJAX с параметрами запроса, где ответы AJAX генерируются JSF с использованием beans, контролируемых параметрами.

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

EDIT: для перезагрузки страницы вы можете использовать этот код:

if (window.location.hash != '') {
  var newsearch = window.location.search;
  if(newsearch != '') {
    newsearch += '&';
  }
  newsearch += window.location.hash.match(/#?(.*)/)[1];
  window.location.hash = '';
  window.location.search = newsearch;
}
1
ответ дан BalusC 28 August 2018 в 02:29
поделиться
  • 1
    Я видел эту технику, используемую facebook, где параметры фрагмента преобразуются в параметры запроса, когда страница перезагружается. Я хотел бы попробовать эту идею. Как преобразовать URL-адрес, содержащий фрагмент, в URL-адрес с параметрами запроса при перезагрузке страницы? т. е. url.com/#a=1&b=2 - & gt; url.com/?a=1&b=2 – Choesang 13 August 2010 в 10:38
  • 2
    Добавлен пример кода. Однако я бы предложил вместо этого написать код для анализа параметров и сделать соответствующий запрос AJAX для восстановления состояния закладки. Кроме того, мой пример кода слишком прост для ваших нужд, он не проверяет, например. дублируются параметры и, следовательно, сталкиваются с проблемами, когда пользователь начинает нажимать, и вы снова добавляете вещи в фрагмент. – clacke 13 August 2010 в 12:48
  • 3
    Пример кода неуклюжий. Только window.location.hash дает вам уже фрагмент и window.location.search строку запроса. Прочитайте документы window.location . – BalusC 13 August 2010 в 13:12
  • 4
    Вы читаете старую версию примера. Я уже исправил это, прежде чем вы прокомментировали. – clacke 13 August 2010 в 13:24
  • 5
    Правильно, это, должно быть, слишком давно открытая вкладка браузера :) – BalusC 13 August 2010 в 14:37

Большое спасибо за ваши идеи и amp; специально BalusC (много для вас). Моим окончательным решением была небольшая мутация, и я хотел бы поделиться с вами всеми.

Поскольку я использую richfaces 3.3.3, это похоже на использование jsf1.2, следовательно, нет <f:ajax>

. В обычной ситуации вы должны нажать на ссылку с href, указывающий на внутреннюю ссылку <a id='internalLink'href='#internalLink'>. Я использую много предварительно упакованных компонентов, где не каждый кликабельный элемент является ссылкой <a>. Это может быть любой элемент html. Было очень полезно использовать плагин jAQuery для закладок Ben Alman ( http://benalman.com/projects/jquery-bbq-plugin/ )

Обратите внимание, что onclick I может программно установить значение фрагмента как ключа / значения, а в следующем коде я заменю старое значение новым значением jQuery.bbq.pushState(state,2) (или я мог бы просто добавить за прежнее значение jQuery.bbq.pushState(state)).

В моем случае ws->md->nd - это иерархические данные, в которых достаточно, чтобы один из них и его родители вычислялись на сервере, поэтому я заменяю родительское значение дочерним значением.

<ui:repeat value="#{workspaceController.modulesForWorkspace}" var="item">  
 <a4j:commandLink onclick="var state = {}; state['md'] = '#{item.uuid}';
  jQuery.bbq.pushState( state, 2 );"    
  action="#{workspaceController.setSelectedModule}"
  reRender="localesList" 
  oncomplete="selectNavigationElement(this.parentNode>
    <f:param name="selectedModule" value="#{item.uuid}"/>
  </a4j:commandLink>
</ui:repeat>

В богатых интерфейсах это классный способ вызова методов setter из браузера с параметром. Обратите внимание, что sendURLFragment рассматривается как метод JS с 5 параметрами и значения передаются на сервер (что очень круто).

<h:form id="processFragment" prependId="false" style="display: none">
  <h:inputText id="fragment" value="#{workspaceController.selectedWorkspace}">                                  
   <a4j:support event="onchange"/>
  </h:inputText>    
<a4j:jsFunction name="sendURLFragment" reRender="workspaces">
 <a4j:actionparam name="ws" assignTo="#{workspaceController.selectedWorkspace}"/>
 <a4j:actionparam name="md" assignTo="#{workspaceController.selectedModule}"/>
 <a4j:actionparam name="nd" assignTo="#{workspaceController.selectedContentNode}"/>
 <a4j:actionparam name="ld" assignTo="#{workspaceController.selectedLOD}"/>
 <a4j:actionparam name="ln" assignTo="#{workspaceController.contentNodeTreeLocale}"  
 converter="localeConverter"/>                              
</a4j:jsFunction>
</h:form>

Сделайте это, когда вы скопируете новый URL-адрес и загрузите страницу.

window.onload = function(){
if(window.location.hash != ""){  
    //Parse the fragment (hash) from a URL, deserializing it into an object            
    var deparamObj = jQuery.deparam.fragment();
    var ws= '', md= '', nd= '', ld= '', ln = '';            
    jQuery.each(deparamObj, function(key, value) {              
        switch(key){
            case 'ws':
                ws = value;
                break;
            case 'md':
                md = value;
                break;
            case 'nd':
                nd = value;
                break;
            case 'ld':
                ld = value;
                break;
            case 'ln':
                ln = value;
                break;
            default:
                break;          
        }

    });
    sendURLFragment(ws,md,nd,ld,ln);
}   };  
0
ответ дан Choesang 28 August 2018 в 02:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: