gpt4 book ai didi

jsf - BLOB 图像仅在通过 p :dataTable is made in PrimeFaces 更新后刷新页面时显示

转载 作者:行者123 更新时间:2023-11-28 21:46:46 25 4
gpt4 key购买 nike

我在 <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:fileUpload>显示在 <p:overlayPanel> 上.为了简单起见,本示例中省略了这一点和许多其他内容,因为它们与具体问题无关。

关联的 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();
}
}

根据唯一行标识符从数据库中检索图像的 bean - BrandBean .

@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> 表示)的勾号更新(编辑后)行时,getImage() BrandBean 中的方法应该被调用。

这在使用 PrimeFaces 5.0 和 JSF 2.2.6 的 GlassFish server 4.0 上运行的应用程序中正确发生。

在数据表(以及数据库)中更新一行后,数据表中将立即显示一个新图像。


还有另一个应用程序在使用 Spring 4.0.0 GA 的 Tomcat 服务器 8.0.5 上运行,其中 getImage()更新数据表保存的行后未调用方法,导致数据表中仍显示旧图像(不是新更新的图像)(即使更改正确传播到数据库)。

仅当按 F5(在大多数浏览器上)刷新页面时,才会显示新更新的图像。它甚至不会在页面加载时显示(在地址栏中输入 URL,然后按 enter 键)。

换句话说,当数据表中的一行通过点击 <p:rowEditor> 指示的勾号更新时, getImage()方法未被调用(因此,新图像未从数据库中获取以显示在 <p:graphicImage> 上)。仅当通过按 F5 快捷键刷新/重新加载页面时才会调用此方法。


为什么会这样?如何在更新一行后立即显示新更新的图像?

从表面上看,这应该既不与 Spring 也不与 JPA 相关(更新操作在单击勾号后正确传播到数据库)。这应该与 Tomcat 服务器有关。

最佳答案

The newly updated image is displayed only when the page refreshed by pressing F5 (on most browsers). It is even not displayed on page load (entering a URL into the address bar and then pressing the enter key).

图像正在被网络浏览器缓存。资源通过响应 header 中设置的与缓存相关的指令在每个 URL 的基础上进行缓存。您的具体问题是因为资源 URL 仍然相同并且网络浏览器不知道服务器端的资源已更改。 OmniFaces CacheControlFilter showcase page详细解释了缓存(注意:过滤器不是解决这个问题的方法)。

您基本上需要通过更改 URL 强制浏览器重新请求资源。在这种情况下,可缓存资源突然更改并且其更改需要立即反射(reflect)到所有客户端,最常见的方法之一是将图像的“最后修改”时间戳附加到 URL 的查询字符串。鉴于您使用的是 JPA,所以应该这样做:

  • lastModified 列添加到 brand 表:

    ALTER TABLE brand ADD COLUMN lastModified TIMESTAMP DEFAULT now();
  • 使用适当的属性和 @PreUpdate 扩展 Brand 实体设置它:

    @Column @Temporal(TemporalType.TIMESTAMP)
    private Date lastModified;

    @PreUpdate
    public void onUpdate() {
    lastModified = new Date();
    }

    // +getter+setter

    (JPA 在每个 UPDATE 查询之前调用一个 @PreUpdate 注释方法)

  • 将其附加到图像 URL(参数名称 v 是对“version”的提示):

    <p:graphicImage value="#{brandBean.image}" ...>
    <f:param name="id" value="#{row.brandId}" />
    <f:param name="v" value="#{row.lastModified.time}" />
    </p:graphicImage>

    (为了清晰起见,我在这里将 row 重命名为 brand 并将 brandId 重命名为 id 以进行重复数据删除)

  • 最后,如果您使用的是 PrimeFaces 5.0 或更新版本,那么您还需要禁用服务器端缓存:

    <p:graphicImage value="#{brandBean.image}" cache="false" ...>

设计注意事项:如果图像不一定在 Brand 的每次更新时更新,则将其拆分到另一个表 Image 并让 BrandImage 有 FK(@ManyToOne@OneToOne)。这也使得属性“图像”可在 web 应用程序的各种实体之间重复使用。

关于jsf - BLOB 图像仅在通过 p :dataTable is made in PrimeFaces 更新后刷新页面时显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23946803/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com