只是看了一下GraphicImageRenderer,想弄清楚它们是如何生成动态 URL 的。他们在DynamicContentSrcBuilder上使用静态方法:
protected String getImageSrc(FacesContext context, GraphicImage image) throws Exception {
String name = image.getName();
if (name != null) {
// ...
} else {
return DynamicContentSrcBuilder.build(context, image.getValue(), image, image.isCache(), DynamicContentType.STREAMED_CONTENT, image.isStream());
}
}
那么为什么不在p:graphicImage
组件上重现这个调用呢?我将首先bind
将其设置为RequestScoped
bean 的属性,然后从该 bean 中获取 URI,该 URI 再现了上面显示的渲染器的行为:
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://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">
<h:head/>
<body>
<p:graphicImage binding="#{myBean.imgComponent}"
value="#{myBean.img}" />
<h:outputText id="imageData" pt:data-image="#{myBean.getImgUri()}" />
</body>
</html>
我的豆又名myBean
:
package test;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.enterprise.context.RequestScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import org.primefaces.application.resource.DynamicContentType;
import org.primefaces.component.graphicimage.GraphicImage;
import org.primefaces.model.StreamedContent;
import org.primefaces.util.DynamicContentSrcBuilder;
@Named
@RequestScoped
public class MyBean {
private GraphicImage imgComponent;
private String imgUri;
public StreamedContent getImg() throws IOException {
// ...
}
public GraphicImage getImgComponent() {
return imgComponent;
}
public void setImgComponent(GraphicImage imgComponent) {
this.imgComponent = imgComponent;
}
public String getImgUri() throws UnsupportedEncodingException {
assert null != imgComponent;
if (null == imgUri) {
// here we reproduce the GraphicImageRenderer behavior:
imgUri = DynamicContentSrcBuilder.build(FacesContext.getCurrentInstance(), imgComponent.getValue(),
imgComponent, imgComponent.isCache(), DynamicContentType.STREAMED_CONTENT, imgComponent.isStream());
}
return imgUri;
}
}
或者,我们可以使用andGraphicImageRenderer
发布protected
方法getImageSrc
:
public class MyBean {
// ...
public String getImgUri() throws Exception {
assert null != imgComponent;
if (null == imgUri) {
imgUri = new GraphicImageRendererXtension().getPublicImageSrc(FacesContext.getCurrentInstance(),
imgComponent);
}
return imgUri;
}
}
public class GraphicImageRendererXtension extends GraphicImageRenderer {
// publish the protected GraphicImageRenderer#getImageSrc method:
public String getPublicImageSrc(FacesContext context, GraphicImage image) throws Exception {
return getImageSrc(context, image);
}
}
但是为什么我写#{myBean.getImgUri()}
而不是#{myBean.imgUri}
?我仍然不确定,但使用后者会产生PropertyNotFoundException
:
javax.el.PropertyNotFoundException: /myView.xhtml @20,46 value="#{myBean.imgUri}": ELResolver did not handle type: [null] with property of [imgUri]
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:117)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:200)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:187)
at javax.faces.component.UIOutput.getValue(UIOutput.java:179)
at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:360)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:171)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:949)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1912)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:918)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:309)
at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:114)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:918)
at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:86)
at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:73)
at org.primefaces.component.layout.LayoutUnitRenderer.encodeEnd(LayoutUnitRenderer.java:49)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:949)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1912)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1908)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1908)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1908)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:491)
at javax.faces.view.ViewDeclarationLanguageWrapper.renderView(ViewDeclarationLanguageWrapper.java:126)
...
Caused by: javax.el.PropertyNotFoundException: ELResolver did not handle type: [null] with property of [imgUri]
at org.apache.el.parser.AstValue.getValue(AstValue.java:174)
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:190)
at org.apache.webbeans.el22.WrappedValueExpression.getValue(WrappedValueExpression.java:68)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:115)
... 122 more
可能DynamicContentSrcBuilder.build()
以某种方式调用该方法会扰乱值表达式的持续解析#{myBean.imgUri}
,而#{myBean.getImgUri()}
不会受到影响。
回到你的问题:不,没有消息。生成动态 URI 并在渲染时直接发送到浏览器。该GraphicImage
组件没有为此提供任何吸气剂。我在这里介绍的是一种解决方法的服务器端变体,无需创建新的 servlet。
编辑:
当然,您也可以参数化该getImageUri
方法并将您的 Image 组件绑定到一些任意变量,这将使您更接近您的演示var="..."
示例:
public class MyBean {
// ...
public String getImgUri(GraphicImage imgComponent) throws Exception {
assert null != imgComponent;
String imgUri = new GraphicImageRendererXtension().getPublicImageSrc(FacesContext.getCurrentInstance(),
imgComponent);
return imgUri;
}
}
然后通过以下方式使用此方法:
<p:graphicImage binding="#{myImage}" value="#{myBean.img}" />
<h:outputText id="imageData" pt:data-image="#{myBean.getImgUri(myImage)}" />
这样就不需要为每个图像创建一个 bean 或方法。