Tin*_*iny 8 jsf viewparams jsf-2.2
给出<p:selectOneMenu>如下.
<f:metadata>
<f:viewParam name="id" value="#{testManagedBean.id}" converter="javax.faces.Long"/>
</f:metadata>
<p:selectOneMenu value="#{localeBean.language}" onchange="changeLanguage();">
<f:selectItem itemValue="en" itemLabel="English" />
<f:selectItem itemValue="hi" itemLabel="Hindi" />
</p:selectOneMenu>
<p:remoteCommand action="#{testManagedBean.submitAction}"
name="changeLanguage"
process="@this"
update="@none"/>
Run Code Online (Sandbox Code Playgroud)
相应的托管bean:
@ManagedBean
@RequestScoped
public final class TestManagedBean {
private Long id; //Getter and setter.
public TestManagedBean() {}
public String submitAction() {
return FacesContext.getCurrentInstance().getViewRoot().getViewId() + "?faces-redirect=true&includeViewParams=true";
}
}
Run Code Online (Sandbox Code Playgroud)
指示的参数<f:viewParam>是可选的.例如,使用URL访问页面,如下所示.
https://localhost:8181/Project-war/private_resources/Test.jsf
由于id是可选参数,<p:selectOneMenu>因此如果未按如下方式提供,则将空参数附加到URL(更改语言时).
https://localhost:8181/Project-war/private_resources/Test.jsf?id=
这不应该发生.如果未提供空参数,则不应附加空参数,并且URL应与第一个类似.
有没有办法防止空参数被传递到URL时没有传递?
这仅与<f:viewParam>- 指定的转换器相关联javax.faces.Long.
如果删除此转换器,则在未提供参数的情况下,参数不会附加到URL.
虽然完全没有必要指定转换器,但我有如下所示的转换器将id通过URL作为查询字符串参数传递给JPA实体.
@ManagedBean
@RequestScoped
public final class ZoneConverter implements Converter {
@EJB
private final SharableBeanLocal sharableService = null;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
try {
long parsedValue = Long.parseLong(value);
if (parsedValue <= 0) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Message Summary", "Message"));
}
ZoneTable entity = sharableService.findZoneById(parsedValue);
if (entity == null) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_WARN, "Message Summary", "Message"));
}
return entity;
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Message Summary", "Message"), e);
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return value instanceof ZoneTable ? ((ZoneTable) value).getZoneId().toString() : "";
}
}
Run Code Online (Sandbox Code Playgroud)
现在需要明确指定此转换器<f:viewParam>,如下所示.
<f:viewParam name="id"
value="#{testManagedBean.id}"
converter="#{zoneConverter}"
rendered="#{not empty param.id}"/>
Run Code Online (Sandbox Code Playgroud)
并且需要按如下方式更改关联的托管bean.
@ManagedBean
@RequestScoped
public final class TestManagedBean {
private ZoneTable id; //Getter and setter.
public TestManagedBean() {}
public String submitAction() {
return FacesContext.getCurrentInstance().getViewRoot().getViewId() + "?faces-redirect=true&includeViewParams=true";
}
}
Run Code Online (Sandbox Code Playgroud)
这可能是对Mojarra默认实现的疏忽,UIViewParameter#getStringValueFromModel()其源代码可供参考,如下所示:
384 public String getStringValueFromModel(FacesContext context)
385 throws ConverterException {
386 ValueExpression ve = getValueExpression("value");
387 if (ve == null) {
388 return null;
389 }
390
391 Object currentValue = ve.getValue(context.getELContext());
392
393 // If there is a converter attribute, use it to to ask application
394 // instance for a converter with this identifer.
395 Converter c = getConverter();
396
397 if (c == null) {
398 // if value is null and no converter attribute is specified, then
399 // return null (null has meaning for a view parameters; it means remove it).
400 if (currentValue == null) {
401 return null;
402 }
403 // Do not look for "by-type" converters for Strings
404 if (currentValue instanceof String) {
405 return (String) currentValue;
406 }
407
408 // if converter attribute set, try to acquire a converter
409 // using its class type.
410
411 Class converterType = currentValue.getClass();
412 c = context.getApplication().createConverter(converterType);
413
414 // if there is no default converter available for this identifier,
415 // assume the model type to be String.
416 if (c == null) {
417 return currentValue.toString();
418 }
419 }
420
421 return c.getAsString(context, this, currentValue);
422 }
Run Code Online (Sandbox Code Playgroud)
在为查询字符串构建期间,为每个UIViewParameter(后面的UI组件<f:viewParam>)调用此方法includeViewParams=true.我们看到无论它调用转换器的源currentValue是null或不是.换句话说,即使模型值是null,它仍然用它来调用转换器.
根据转换器的javadoc,Converter#getAsString()如果值为null:返回零长度字符串所需的规范:
符getAsString
...
返回:值为零的长度字符串
null,否则为转换的结果
因此,转换器实际上应该不会再回来null的getAsString().然后他们返回一个空字符串.在查询字符串中的视图参数的情况下,这是非常不期望的.空字符串值与查询字符串中完全缺失之间的差异非常重要.
我已经向Mojarra家伙报告了问题3288.然后他们应该解决这个问题如下:
391 Object currentValue = ve.getValue(context.getELContext());
392
393 if (currentValue == null) {
394 return null;
395 }
Run Code Online (Sandbox Code Playgroud)
在此期间,我致力于解决OmniFaces.在<o:viewParam>已扩展与此修复程序.它可以按照今天的1.8快照获得.
<f:metadata>
<o:viewParam name="id" value="#{testManagedBean.id}" converter="javax.faces.Long"/>
</f:metadata>
Run Code Online (Sandbox Code Playgroud)
更新:他们决定不解决它.无论如何,有OmniFaces.
| 归档时间: |
|
| 查看次数: |
1714 次 |
| 最近记录: |