0

com.I 有用户上传图像的 SWF 应用程序,并且该图像必须在下一个流状态下显示。该流程使用存储所有用户输入数据的对话范围 bean(实际上是一个 JPA 实体)。我可以上传图像,将其存储在 bean 中,但 PrimeFaces graphicsImage facelet 不会渲染它。我做了一些研究,似乎在渲染 PF GI 组件期间存储要使用会话评估的 EL 表达式,随后对 ResourceHandler 的调用(由渲染 HTML 中的 IMG 标记进行)获取相同的 EL 表达式并实际评估它。问题是 ResourceHandler 无法访问我存储所有数据的流变量,因此无法渲染图像。

我扩展了 PF GI 组件以使用会话而不是 EL 表达式存储实际图像,但这具有明显的性能影响:在 Session 中存储二进制数据不是一个好主意。此外,出于安全原因,我宁愿将所有数据保留在流/对话范围内,而不是会话中。

有什么干净的方法可以让 PF GI 组件访问我的流变量吗?

我的代码片段如下

流程:

<on-start>
    <evaluate expression="new my.models.Customers()" result="conversationScope.customer"></evaluate>
</on-start>

<view-state id="scanImage" view="s1-scan.xhtml" model="customer" >
    <secured attributes="ROLE_WEB" />
    <transition on="submit" to="verifyImage"></transition>
    <transition on="cancel" to="canceled"></transition>
</view-state>

<view-state id="verifyImage" view="s2-verifyscan.xhtml" model="customer">
    <secured attributes="ROLE_WEB" />
    <transition on="submit" to="enterDetails"></transition>
    <transition on="back" to="scanImage"></transition>
    <transition on="cancel" to="canceled"></transition>
</view-state>

图像渲染:

<p:graphicImage value="#{customer.getImageSC()}"></p:graphicImage>

已修补的 GraphicImageRenderer.getImageSrc()

protected String getImageSrc(FacesContext context, GraphicImage image) {
    String src = null;
String name = image.getName();

if(name != null) {
    String libName = image.getLibrary();
    ResourceHandler handler = context.getApplication().getResourceHandler();
    Resource res = handler.createResource(name, libName);

    if(res == null) {
        return "RES_NOT_FOUND";
    } 
    else {
        String requestPath = res.getRequestPath();

        return context.getExternalContext().encodeResourceURL(requestPath);
    }
}
else {
    Object value = image.getValue();

    if(value == null) {
        return "";
    }
    else  if(value instanceof String) {
        src = getResourceURL(context, (String) value);
    }
    else if(value instanceof StreamedContent) {
        StreamedContent streamedContent = (StreamedContent) value;
        Resource resource = context.getApplication().getResourceHandler().createResource("dynamiccontent", "primefaces", streamedContent.getContentType());
        String resourcePath = resource.getRequestPath();
        String rid = createUniqueContentId(context);
        StringBuilder builder = new StringBuilder(resourcePath);

        builder.append("&").append(Constants.DYNAMIC_CONTENT_PARAM).append("=").append(rid);

        for(UIComponent kid : image.getChildren()) {
            if(kid instanceof UIParameter) {
                UIParameter param = (UIParameter) kid;

                builder.append("&").append(param.getName()).append("=").append(param.getValue());
            }
        }

        src = builder.toString();

        context.getExternalContext().getSessionMap().put(rid, value);
        // context.getExternalContext().getSessionMap().put(rid, image.getValueExpression("value").getExpressionString());
    }

    if(!image.isCache()) {
        src += src.contains("?") ? "&" : "?";
        src += "primefaces_image=" + UUID.randomUUID().toString();
    }

    src = context.getExternalContext().encodeResourceURL(src);
}

    return src;
}

处理程序:

public void handleResourceRequest(FacesContext context) throws IOException {
Map<String,String> params = context.getExternalContext().getRequestParameterMap();
String library = params.get("ln");
String dynamicContentId = params.get(Constants.DYNAMIC_CONTENT_PARAM);

if(dynamicContentId != null && library != null && library.equals("primefaces")) {
    Map<String,Object> session = context.getExternalContext().getSessionMap();
    StreamedContent streamedContent = null;

    try {

        Object dynamicContentEL = (Object) session.get(dynamicContentId);

        //String dynamicContentEL = (String) session.get(dynamicContentId);
        //ELContext eLContext = context.getELContext();
        //ValueExpression ve = context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(), dynamicContentEL, StreamedContent.class);
        //streamedContent = (StreamedContent) ve.getValue(eLContext);

        streamedContent = (StreamedContent) dynamicContentEL;

        ExternalContext externalContext = context.getExternalContext();
        externalContext.setResponseStatus(200);
        externalContext.setResponseContentType(streamedContent.getContentType());

        byte[] buffer = new byte[2048];

        int length;
        InputStream inputStream = streamedContent.getStream();
        while ((length = (inputStream.read(buffer))) >= 0) {
            externalContext.getResponseOutputStream().write(buffer, 0, length);
        }

        externalContext.responseFlushBuffer();
        context.responseComplete();

    } catch(Exception e) {
        logger.log(Level.SEVERE, "Error in streaming dynamic resource. {0}", new Object[]{e.getMessage()});
    }
    finally {
        //cleanup
        session.remove(dynamicContentId);

        if(streamedContent != null) {
            streamedContent.getStream().close();
        }
    }
}
else {
   super.handleResourceRequest(context); 
}

}

面孔配置:

   <application>
        <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
        <resource-handler>com.my.PrimeResourceHandler</resource-handler>
    </application>

<render-kit>    
    <renderer>
         <component-family>org.primefaces.component</component-family>
         <renderer-type>org.primefaces.component.graphicimage.GraphicImageRenderer</renderer-type>
         <renderer-class>com.my.GraphicImageRenderer</renderer-class>
    </renderer>
</render-kit>

我怀疑有可能将 webflow 上下文与 EL 一起存储在 Session 对象中,并让资源处理程序在评估 EL 时使用该上下文......

4

1 回答 1

0

您是否修改了 primefaces 代码(即 GraphicImageRenderer 和 PrimeResourceHandler 类)或扩展了它们?如果您扩展它们,代码是如何知道使用/调用扩展类的?

我正在使用请求范围并将所有图像存储在 WEB-INF 文件夹中并使用以下方法检索它们:

<p:graphicImage value="/images/{springBean.imageFileName}"> 

我没有对 primefaces 代码进行任何更改,因为它们可能会在以后的版本中解决此问题。我喜欢使用流范围,也想使用如下 bean 来检索它们:

<p:graphicImage value="#{springBean.imageFile}">

我还尝试将图像保存到不在 webapproot 中的硬盘驱动器位置,并且无法显示图形图像。希望我可以将所有请求映射到 /images/* 到某个本地文件夹,而无需在 websphere 中使用如下的控制器/托管 bean?

如何在 java webapp 中的服务器上保存和检索图像

于 2012-11-15T19:24:09.457 回答