gpt4 book ai didi

jsf - includeViewParams=true 将空模型值转换为查询字符串中的空字符串

转载 作者:行者123 更新时间:2023-12-04 07:53:43 25 4
gpt4 key购买 nike

给定一个 <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"/>

相应的托管 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";
}
}
<f:viewParam>表示的参数是可选的。例如,使用 URL 访问页面,如下所示。
https://localhost:8181/Project-war/private_resources/Test.jsf
id是一个可选参数,一个空参数附加到 URL(当语言从 <p:selectOneMenu> 更改时),以防它没有提供如下。
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() : "";
}
}

现在需要使用 <f:viewParam> 明确指定此转换器如下。
<f:viewParam name="id" 
value="#{testManagedBean.id}"
converter="#{zoneConverter}"
rendered="#{not empty param.id}"/>

并且关联的托管 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";
}
}

最佳答案

这可能是 Mojarra's default implementation 中的疏忽的 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 }
每个 UIViewParameter 都会调用此方法( <f:viewParam> 后面的 UI 组件)在为 includeViewParams=true 构建查询字符串期间.我们在源码中看到,不管 currentValue 是否调用转换器,是 null或不。换句话说,即使模型值为 null ,它仍然用它调用转换器。
根据 javadoc of Converter#getAsString() 如果值为 null,转换器按规范要求返回零长度字符串:

getAsString

...

Returns: a zero-length String if value is null, otherwise the result of the conversion


因此,转换器实际上应该永远不会返回 nullgetAsString() .然后他们返回一个空字符串。对于查询字符串中的 View 参数,这是非常不可取的。空字符串值和查询字符串中完全缺失之间的区别非常重要。
我已将其报告给 Mojarra 人员 issue 3288 .然后他们应该按如下方式解决这个问题:
391        Object currentValue = ve.getValue(context.getELContext());
392
393 if (currentValue == null) {
394 return null;
395 }
与此同时,我 committed OmniFaces 的解决方案。 <o:viewParam> 已扩展此修复程序。根据今天的 1.8 snapshot 可用.
<f:metadata>
<o:viewParam name="id" value="#{testManagedBean.id}" converter="javax.faces.Long"/>
</f:metadata>

更新 : 他们决定不修复它。在任何情况下,都有 OmniFaces。

关于jsf - includeViewParams=true 将空模型值转换为查询字符串中的空字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23725629/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com