如何使Primefaces graphicImage与Spring Web Flow一起使用

时间:2012-11-15 16:10:37

标签: java spring primefaces facelets spring-webflow

com。我有一个用户上传图像的SWF应用程序,该图像必须在下一个流状态下显示。该流使用会话范围的bean(实际上是JPA实体)来存储所有用户输入的数据。我可以上传图像,将其存储在bean中,但PrimeFaces的graphicImage 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>

Patched 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时使用该上下文...

1 个答案:

答案 0 :(得分:0)

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

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

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

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

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

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

How I save and retrieve an image on my server in a java webapp