我将以以下方式在<p:graphicImage>
上显示以BLOB形式存储在MySQL中的图像。
<p:dataTable var="row" value="#{testManagedBean}" lazy="true" editable="true" rows="10">
<p:column headerText="id">
<h:outputText value="#{row.brandId}"/>
</p:column>
<p:column headerText="Image">
<p:cellEditor>
<f:facet name="output">
<p:graphicImage value="#{brandBean.image}" height="100" width="100">
<f:param name="id" value="#{row.brandId}"/>
</p:graphicImage>
</f:facet>
<f:facet name="input">
<p:graphicImage id="image" value="#{brandBean.image}" height="100" width="100">
<f:param name="id" value="#{row.brandId}"/>
</p:graphicImage>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Edit" width="50">
<p:rowEditor/>
</p:column>
</p:dataTable>
在编辑行时,<p:overlayPanel>
上显示了一个<p:fileUpload>
。为了简单起见,本例中省略了许多其他内容,因为它们与具体问题无关。
相关的JSF托管bean:
@ManagedBean
@ViewScoped
public final class TestManagedBean extends LazyDataModel<Brand> implements Serializable
{
@EJB
private final TestBeanLocal service=null;
private static final long serialVersionUID = 1L;
@Override
public List<Brand> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
setRowCount(3);
return service.getList();
}
}
BrandBean
是一个从数据库中根据唯一行标识符检索图像的bean。
@ManagedBean
@ApplicationScoped
public final class BrandBean
{
@EJB
private final BrandBeanLocal service=null;
public BrandBean() {}
public StreamedContent getImage() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
}
else {
String id = context.getExternalContext().getRequestParameterMap().get("id");
System.out.println("id = "+id);
byte[] bytes = service.findImageById(Long.parseLong(id));
return bytes==null? new DefaultStreamedContent(new ByteArrayInputStream(new byte[0])):new DefaultStreamedContent(new ByteArrayInputStream(bytes));
}
}
}
当在数据表中点击最后一列位置上的打勾按钮(由
<p:rowEditor>
指示),编辑完成的行被更新后,应该会调用BrandBean
中的getImage()
方法。在运行GlassFish server 4.0、PrimeFaces 5.0和JSF 2.2.6的应用程序中,这样做是正确的。在数据表中更新行(因此也更新了数据库)后,数据表中将立即显示新图像。
在Tomcat server 8.0.5中使用Spring 4.0.0 GA的另一个应用程序中,更新数据表中的行后
getImage()
方法未被调用,导致数据表中继续显示旧图像(而非新更新的图像)(尽管更改已正确传播到数据库)。只有当按下大多数浏览器上的F5刷新页面时,才会显示新更新的图像。它甚至不会在页面加载时(输入URL到地址栏,然后按下Enter键)显示。
换句话说,当通过
<p:rowEditor>
点击数据表中的行时进行更新时,getImage()
方法不会被调用(因此无法从数据库获取新图像以显示在<p:graphicImage>
上)。只有按下F5快捷键刷新/重新加载页面时,该方法才会被调用。
为什么会这样?如何在行更新后立即显示新更新的图像?
表面上看,这既与Spring也与JPA无关(点击打勾后更新操作已正确传播到数据库)。而是与Tomcat服务器有关。