问题描述
我有一个MySQL数据库存储图像在一个 blob
列。我想在PrimeFaces < p:dataTable>
中显示它们。如何实现?您可以使用显示存储在字节[ ]
,而不管 byte []
source(DB,磁盘文件系统,网络等)。最简单的例子是:
< p:graphicImage value =#{bean.streamedContent} />
它引用了一个 StreamedContent
属性。 p>
然而,这是一个陷阱,特别是在诸如数据表的迭代组件中使用时:getter方法将被调用两次;第一次由JSF自己生成< img src>
的URL,第二次由webbrowser在需要根据< img src>
。为了有效率,您不应该在第一个getter调用中击中DB。另外,要参数化getter方法调用,以便您可以使用通用特定图像ID的通用方法,您应该使用< f:param>
(请请注意,传递方法参数的EL 2.2功能将无法正常工作,因为这不会导致< img src>
!的URL)。
总结说,这应该是:
p:dataTable value =#{bean.items}var =item>
< p:column>
< p:graphicImage value =#{imageStreamer.image}>
< f:param name =idvalue =#{item.imageId}/>
< / p:graphicImage>
< / p:column>
< / p:dataTable>
#{item.imageId}
返回数据库(主键)中图像的唯一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){
//所以,我们渲染HTML。返回一个存根StreamedContent,以便它将生成正确的URL。
返回新的DefaultStreamedContent();
} else {
//所以浏览器正在请求图像。用图像字节返回一个真正的StreamedContent。
String imageId = context.getExternalContext()。getRequestParameterMap()。get(imageId);
Image image = imageService.find(Long.valueOf(imageId));
返回新的DefaultStreamedContent(新的ByteArrayInputStream(image.getBytes()));
}
}
}
code> Image class在这个特殊的例子中只有一个 @Entity
与 @Lob
在字节
属性(因为你使用JSF,我的cource假定你正在使用JPA与数据库进行交互)。
@Entity
public class Image {
@Id
@ GeneratedValue(strategy = IDENTITY)//根据您的DB,当然。
private Long id;
@Lob
private byte [] bytes;
// ...
}
ImageService
只是一个标准的 @Stateless
EJB,没有什么特别的看法:
@Stateless
public class ImageService {
@PersistenceContext
private EntityManager em;
public Image find(Long id){
return em.find(Image.class,id);
}
}
另请参见:
I have MySQL database which stores images in a blob
column. I would like to show them in a PrimeFaces <p:dataTable>
. How can I achieve this?
You can use <p:graphicImage>
to display images stored in a byte[]
, regardless of the byte[]
source (DB, disk file system, network, etc). Simplest example is:
<p:graphicImage value="#{bean.streamedContent}" />
which refers a StreamedContent
property.
This has however a pitfall, particularly when used in an iterating component such as a data table: the getter method will be invoked twice; the first time by JSF itself to generate the URL for <img src>
and the second time by webbrowser when it needs to download the image content based on the URL in <img src>
. To be efficient, you should not be hitting the DB in the first getter call. Also, to parameterize the getter method call so that you can use a generic method wherein you pass a specific image ID, you should be using a <f:param>
(please note that EL 2.2 feature of passing method arguments won't work at all as this doesn't end up in URL of <img src>
!).
Summarized, this should do:
<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>
The #{item.imageId}
obviously returns the unique idenfitier of the image in the DB (the primary key) and thus not the byte[]
content. The #{imageStreamer}
is an application scoped bean which look like this:
@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()));
}
}
}
The Image
class is in this particular example just an @Entity
with a @Lob
on bytes
property (as you're using JSF, I of cource assume that you're using JPA to interact with the DB).
@Entity
public class Image {
@Id
@GeneratedValue(strategy = IDENTITY) // Depending on your DB, of course.
private Long id;
@Lob
private byte[] bytes;
// ...
}
The ImageService
is just a standard @Stateless
EJB, nothing special to see here:
@Stateless
public class ImageService {
@PersistenceContext
private EntityManager em;
public Image find(Long id) {
return em.find(Image.class, id);
}
}
See also:
这篇关于从JSF datatable中的MySQL数据库显示图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!