一尘不染

在JSF数据表中显示来自MySQL数据库的图像[关闭]

mysql

我有将图像存储在blob列中的MySQL数据库。我想在PrimeFaces中展示它们<p:dataTable>。我该如何实现?


阅读 255

收藏
2020-05-17

共1个答案

一尘不染

您可以使用<p:graphicImage>来显示存储在中的图像byte[],而不管其byte[]来源(数据库,磁盘文件系统,网络等)如何。最简单的例子是:

<p:graphicImage value="#{bean.streamedContent}" />

指的是StreamedContent财产。

但是,这有一个陷阱,尤其是在用于数据表之类的迭代组件中时:getter方法将被调用两次;第一次由JSF本身生成URL,<img src>第二次由webbrowser生成,它需要基于中的URL下载图像内容<img src>。为了提高效率,您不应在第一个getter调用中访问数据库。另外,要对getter方法调用进行参数化,以便可以使用传递特定图像ID的通用方法,则应使用<f:param>(请注意,传递方法参数的EL
2.2功能根本无法使用,因为这样做不行。不能以URL开头<img src>!)。

总结起来,这应该做到:

<p:dataTable value="#{bean.items}" var="item">
    <p:column>
        <p:graphicImage value="#{imageStreamer.image}">
            <f:param name="id" value="#{item.imageId}" />
        </p:graphicImage>
    </p:column>
</p:dataTable>

#{item.imageId}明显返回在DB的图像的独特idenfitier(主键),从而
byte[]内容。该#{imageStreamer}是一个应用范围的bean看起来是这样的:

@ManagedBean
@ApplicationScoped
public class ImageStreamer {

    @EJB
    private ImageService service;

    public StreamedContent getImage() throws IOException {
        FacesContext context = FacesContext.getCurrentInstance();

        if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
            // So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
            return new DefaultStreamedContent();
        } else {
            // So, browser is requesting the image. Return a real StreamedContent with the image bytes.
            String imageId = context.getExternalContext().getRequestParameterMap().get("imageId");
            Image image = imageService.find(Long.valueOf(imageId));
            return new DefaultStreamedContent(new ByteArrayInputStream(image.getBytes()));
        }
    }

}

Image在这个特定示例中,该类只是一个@Entity具有@Lobon
bytes属性的类(当您使用JSF时,我当然假定您正在使用JPA与DB进行交互)。

@Entity
public class Image {

    @Id
    @GeneratedValue(strategy = IDENTITY) // Depending on your DB, of course.
    private Long id;

    @Lob
    private byte[] bytes;

    // ...
}

ImageService仅仅是一个标准的@StatelessEJB,没有什么特别在这里看到:

@Stateless
public class ImageService {

    @PersistenceContext
    private EntityManager em;

    public Image find(Long id) {
        return em.find(Image.class, id);
    }

}
2020-05-17