【问题标题】:Is there news on getting the URL of <p:graphicImage>?有没有关于获取 <p:graphicImage> 的 URL 的消息?
【发布时间】:2019-07-25 17:28:49
【问题描述】:

基本上我的问题与五年前回答的this one 相同:我想从&lt;p:graphicImage&gt; 输出服务器提供的图像的URL,但只是URL 而不是&lt;img&gt; 标记。我正在寻找的是这样的解决方案:

(这是不工作代码,只是为了说明:)

<p:graphicImage var="url" value="#{MyForm.image}"/>
<span id="imageData" data-image="#{url}/>

应该像这样输出到 HTML:

<span id="imageData" data-image="http://localhost:8080/contextPath/javax.faces.resource/dy...

我目前为此使用JavaScript work-around,但这个要求对我来说似乎很常见,我希望新的开发已经针对它并且有一个内置的解决方案。自过去五年以来是否有关于该主题的新闻?

【问题讨论】:

    标签: jsf primefaces graphicimage


    【解决方案1】:

    刚刚查看了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;
        }
    
    }
    

    或者,我们可以使用GraphicImageRenderer并发布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 或方法。

    【讨论】:

    • 在 stackoverflow 上有 99.5% 的确定性。
    • @Kukeltje 是 OP 问题的副本?他把它联系起来。我应该在此处而不是此处发布我建议的答案吗?
    • 不,没关系,但在接下来的几天里,我只是在手机上,我不能轻易检查真正的好东西,但我几乎可以肯定是一个。但它也可能是 OmniFaces 的“修复”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-15
    • 1970-01-01
    • 2013-02-24
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多