我有将图像存储在blob列中的MySQL数据库。我想在PrimeFaces中展示它们<p:dataTable>。我该如何实现?
blob
<p:dataTable>
您可以使用<p:graphicImage>来显示存储在中的图像byte[],而不管其byte[]来源(数据库,磁盘文件系统,网络等)如何。最简单的例子是:
<p:graphicImage>
byte[]
<p:graphicImage value="#{bean.streamedContent}" />
指的是StreamedContent财产。
StreamedContent
但是,这有一个陷阱,尤其是在用于数据表之类的迭代组件中时:getter方法将被调用两次;第一次由JSF本身生成URL,<img src>第二次由webbrowser生成,它需要基于中的URL下载图像内容<img src>。为了提高效率,您不应在第一个getter调用中访问数据库。另外,要对getter方法调用进行参数化,以便可以使用传递特定图像ID的通用方法,则应使用<f:param>(请注意,传递方法参数的EL 2.2功能根本无法使用,因为这样做不行。不能以URL开头<img src>!)。
<img src>
<f:param>
总结起来,这应该做到:
<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看起来是这样的:
#{item.imageId}
#{imageStreamer}
@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进行交互)。
Image
@Entity
@Lob
bytes
@Entity public class Image { @Id @GeneratedValue(strategy = IDENTITY) // Depending on your DB, of course. private Long id; @Lob private byte[] bytes; // ... }
该ImageService仅仅是一个标准的@StatelessEJB,没有什么特别在这里看到:
ImageService
@Stateless
@Stateless public class ImageService { @PersistenceContext private EntityManager em; public Image find(Long id) { return em.find(Image.class, id); } }