我正在阅读,尝试和搜索,我不知道我做错了什么。我曾经在JSF之前的时代用JSP和Seam编程,并且我已经习惯了技术本身(好吧,有点),我是JSF 2.x的新手,我仍然需要掌握一些概念。我现在最大的问题是将参数从一个视图发送到另一个视图,以便对传递的值执行实际的业务逻辑。我的用例:
主页initiateQuery.xhtml
带有多个选项搜索小部件(目前PrimeFaces自动完成带multiple="true"
,因为它在我的用例中提供了最好的用户体验,我相信)
用户可以输入/选择一些值并点击启动业务流程的按钮。输入的值应传递到另一个视图,refineQuery.xhtml
应显示它们,并且可以使用其他参数优化业务查询
我不知道如何存储在initiateQuery
中选择的值,将它们传递给refineQuery
并在那里检索它们以获取实际业务逻辑以及一些其他字段。我不得不承认,我有点失去了GETting,POSTing,Post-Redirect-Get flow的所有可能性,隐含的所有内容,viewParam
s,FacesContext
&#39}的成员, bean范围,按钮与commandButtons,以及如何连接所有这些部分。我尝试了很多东西,但没有运气,从一个错误转到另一个错误,从没有传递到" bean范围大于参数的范围" to"无法使用null转换器设置值[]"。
我认为我的支持bean必须是视图作用域,因为会话范围不适用(用户可能在启动业务查询时未登录),并且请求范围太小 - 两个视图上都有一些组件(即p:gmap
s)用ajax修改支持bean属性。我想我可以处理应用程序的其他方面,比如自动完成列表中的POJO,持久性,L10n,但是将表单值传递给另一个视图对我来说太过分了;)尽管我在途中遇到的一些错误可能是由于自动完成控件或一些PrimeFaces相关的东西,这对我来说是更普遍的问题,因为我甚至无法将输入的简单字符串传递到p:inputText
:(
您可以找到一个简化的示例,说明哪些不适合我,以及我希望在下面实现的目标。请记住,我是JSF的新手,代码从一次尝试演变为另一种,我不太了解某些方面,因此有些事情可能会丢失或多余。
initQuery.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
lang="#{localeBean.language}"
>
<f:view locale="#{localeBean.language}">
<h:head>
<title>#{msg.homeTitle}</title>
</h:head>
<f:metadata>
<f:viewParam name="search" value="#{initQueryView.searchedServices}"/>
</f:metadata>
<body>
<h:form>
<p:autoComplete id="search"
multiple="true"
required="true"
value="#{initQueryView.searchedServices}"
completeMethod="#{initQueryView.completeService}"
var="serviceKey"
itemLabel="#{serviceKey}"
itemValue="#{serviceKey}"
forceSelection="true"
minQueryLength="1"
>
<p:ajax event="itemSelect" listener="#{initQueryView.onItemSelect}" />
<p:ajax event="itemUnselect" listener="#{initQueryView.onItemUnselect}" />
<p:column>
<h:outputText value="#{serviceKey}" />
</p:column>
</p:autoComplete>
<p:commandButton ajax="false" title="#{msg.search}" value="#{msg.search}" action="refineQuery?faces-redirect=true&includeViewParams=true" >
<f:param name="search" value="#{initQueryView.searchedServices}"/>
</p:commandButton>
</h:form>
</body>
</f:view>
</html>
initQuery backing bean:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@ManagedBean
@ViewScoped
public class InitQueryView {
private List<String> searchedServices = new ArrayList<>();
private Set<String> availableServices = new HashSet<>();
@PostConstruct
public void init() {
availableServices = Sets.newHashSet("ServiceA", "ServiceB", "ServiceC");
searchedServices = new ArrayList<>();
}
public Set<String> getAvailableServices() {
return availableServices;
}
public List<String> getSearchedServices() {
return searchedServices;
}
public void setSearchedServices(List<String> searchedServices) {
this.searchedServices = searchedServices;
}
public String searchSubmit() {
return "refineQuery?faces-redirect=true&includeViewParams=true";
}
public List<String> completeService(String query) {
query = query.toLowerCase();
List<String> filteredServices = new ArrayList<String>();
for(String candidateService : availableServices) {
if(candidateService.toLowerCase().startsWith(query)) {
filteredServices.add(candidateService);
}
}
return Lists.newArrayList(filteredServices);
}
public void onItemSelect(SelectEvent event) {
String selected = (String)event.getObject();
availableServices.remove(selected);
}
public void onItemUnselect(UnselectEvent event) {
String selected = (String)event.getObject();
availableServices.add(selected);
}
}
refineQuery.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui" lang="#{localeBean.language}">
<f:view locale="#{localeBean.language}">
<h:head>
<title>#{msg.homeTitle}</title>
</h:head>
<f:metadata>
<f:viewParam name="search" value="#{searchResultView.searched}"/>
</f:metadata>
<h:body>
Services to search for: #{refineQueryView.searched}<br/>
</h:body>
</f:view>
</html>
refineQuery支持bean:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean
@ViewScoped
public class RefineQueryView {
private List<String> searched = new ArrayList<>();
@PostConstruct
public void init() {
searched = Arrays.asList("No idea how to retrieve searched services from previous view...");
}
public List<String> getSearched() {
return searched;
}
public void setSearched(List<String> searched) {
this.searched = searched;
}
}