简体   繁体   English

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

[英]How to make Primefaces graphicImage work with Spring Web Flow

com.I have SWF app where user uploads image, and that image has to be displayed in the next flow state. com。我有SWF应用程序,用户可以在其中上传图片,并且该图片必须在下一个流程状态下显示。 The flow uses conversation-scoped bean (actually a JPA entity) that stores all user-entered data. 该流使用对话范围的Bean(实际上是JPA实体)来存储所有用户输入的数据。 I can upload the image, store it in the bean, but PrimeFaces graphicImage facelet will not render it. 我可以上传图像,将其存储在bean中,但是PrimeFaces graphicImage facelet不会呈现它。 I did some research, and it appears that during rendering PF GI component stores the EL expression to be evaluated with the session, and subsequent call to ResourceHandler (made by IMG tag in rendered HTML) fetches the same EL expression and actually evaluates it. 我做了一些研究,似乎在渲染PF GI组件期间存储了要与会话进行评估的EL表达式,随后对ResourceHandler(由呈现的HTML中的IMG标签制作)的调用将获取相同的EL表达式并对其进行实际评估。 Problem is that ResourceHandler has no access to the flow variable where I store all my data and therefore cant render the image. 问题是ResourceHandler无法访问流变量,因为我将所有数据存储在该流变量中,因此无法渲染图像。

I extended PF GI component to store actual image with the session instead of EL expression, but that has obvious performance implications: storing binary data in Session is not a good idea. 我扩展了PF GI组件,以使用会话而不是EL表达式存储实际图像,但这具有明显的性能含义:在Session中存储二进制数据不是一个好主意。 Also, I would rather keep all data in flow/conversation scope instead of session for security reasons. 另外,出于安全考虑,我宁愿将所有数据都保留在流/会话范围内,而不是会话中。

Is there any clean way to make PF GI component access my flow variables? 有什么干净的方法可以使PF GI组件访问我的流量变量?

Snippets of my code below 我的代码片段如下

The Flow: 流程:

<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>

Image rendering: 图像渲染:

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

Patched GraphicImageRenderer.getImageSrc() 修补的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;
}

Handler: 处理程序:

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); 
}

} }

faces-config: faces-config:

   <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>

I suspect it may be possible to store webflow context together with the EL in Session object, and make resource handler to use that context when evaluating the EL... 我怀疑可能将Webflow上下文与EL一起存储在Session对象中,并使资源处理程序在评估EL时使用该上下文...

Did you modify the primefaces code(ie GraphicImageRenderer and PrimeResourceHandler classes) or extend them? 您是否修改了primefaces代码(即GraphicImageRenderer和PrimeResourceHandler类)或对其进行了扩展? If you extended them how did the code know to use/call the extended classes? 如果扩展了它们,代码如何知道使用/调用扩展类?

I am using a request scope and storing all images in the WEB-INF folder and retrieving them using below: 我正在使用请求范围并将所有图像存储在WEB-INF文件夹中,并使用以下方法检索它们:

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

I did not make any changes to primefaces code as they may be a fix for this in later versions. 我没有对primefaces代码进行任何更改,因为它们可能是以后版本中的解决方案。 I like to use flow scope though and also would like to retrieve them using the bean like below: 我喜欢使用流作用域,也想使用如下所示的bean检索它们:

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

I also tried saving the images to hard-drive location not in webapproot and cannot show the graphicImage. 我还尝试将图像保存到不在webapproot中的硬盘驱动器位置,并且无法显示graphicImage。 wish I can map all requests to /images/* to some local folder without using controller/managed bean like below in websphere? 希望我可以将对/ images / *的所有请求映射到某个本地文件夹,而无需像在Websphere中那样使用控制器/托管bean?

How I save and retrieve an image on my server in a java webapp 如何在Java WebApp中的服务器上保存和检索图像

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM