Ссылка 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.
Вы можете сделать это с помощью 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.
Посмотрите этот вопрос и особенно ответы: JSP Сервлет-якорь
Вот самый надежный способ извлечь фрагмент из синтаксически допустимого URL / URI.
URI uri = new URI(someString);
String fragment = uri.getFragment();
Как вы вставляете это в bean-компонент, будет зависеть от того, какую серверную структуру вы используете, и независимо от того, выполняете ли вы инъекцию, используя XML или аннотации, или делаете это программно.
Фрагмент не может быть замечен с серверной стороны, к нему могут быть доступны только клиентские скрипты. Обычно это делается так, что серверная сторона генерирует непараметрированную страницу, которая затем модифицируется скриптами в соответствии с параметрами фрагмента. Сценарии могут делать запросы 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;
}
window.location.hash
дает вам уже фрагмент и window.location.search
строку запроса. Прочитайте документы window.location
.
– BalusC
13 August 2010 в 13:12
Большое спасибо за ваши идеи и 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);
} };