PrimeFaces 6.0 не кэширует изображения на стороне клиента
Учитывая <p:dataTable>
рендеринг изображений в одном из столбцов.
<p:dataTable id="dataTable" var="row" value="#{bean}"
lazy="true"
skipChildren="true">
<p:column headerText="Image">
<p:cellEditor>
<f:facet name="output">
<p:graphicImage value="#{imageBean.image}" stream="true" cache="true">
<f:param name="id" value="#{row.id}"/>
<f:param name="width" value="100"/>
<f:param name="height" value="100"/>
</p:graphicImage>
</f:facet>
<f:facet name="input">
<p:graphicImage value="#{imageBean.image}" stream="true" cache="true">
<f:param name="id" value="#{row.id}"/>
<f:param name="width" value="100"/>
<f:param name="height" value="100"/>
</p:graphicImage>
<!-- <p:overlayPanel> here for file upload -->
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Edit">
<p:rowEditor/>
</p:column>
</p:dataTable>
Таблица данных может содержать другие важные часто используемые атрибуты и столбцы по мере необходимости.
Когда эта таблица (Ajaxically) обновляется, все изображения выбираются из базы данных (или файловой системы диска, если используется), как будто они вообще не кэшируются браузером, даже если cache
явно установлен на true
(который является значением по умолчанию). Это хорошо работало до финала PrimeFaces 5.3.
Руководство по миграции ничего не говорит об этом, но, видимо, что-то изменилось в кэшировании <p:graphicImage>
,
Любое предложение, чтобы решить проблему?
Например, в приведенном выше примере, если таблица содержит 5 изображений в 5 строках, база данных будет запрашиваться 10 раз при каждом обновлении <p:dataTable>
(кроме встроенного редактирования строки, по умолчанию текущей строки), что не должно происходить, поскольку получение изображений, особенно из базы данных, очень дорого.
Заголовки запроса / ответа, использующие PrimeFaces 6.0 final (работает на WildFly 10.0.0 final), когда на сервер делается первоначальный запрос на обслуживание изображения (не работает - изображения не кэшируются).
General
Request URL:https://localhost:8443/ContextRoot/javax.faces.resource/dynamiccontent.properties.xhtml?ln=primefaces&v=6.0&pfdrid=aed903cc-daba-4822-a62b-888b9a0ef2ac&pfdrt=sc&id=14&width=100&height=100&pfdrid_c=true
Request Method:GET
Status Code:200 OK
Remote Address:127.0.0.1:8443
Response Headers
Cache-Control:max-age=29030400
Connection:keep-alive
Date:Sat, 23 Jul 2016 06:59:54 GMT
Expires:Sun, 23 Jul 2017 06:59:54 GMT
Server:WildFly/10
Transfer-Encoding:chunked
X-Powered-By:Undertow/1
Request Headers
Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:JSESSIONID=4AoRGa1IAPTB4KssnikbO9uUetcQpMupli8BkGga.om-f6b0ea3ad206; __utma=111872281.616526714.1454485589.1468749319.1468751735.4; __utmz=111872281.1454485589.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Host:localhost:8443
Referer:https://localhost:8443/ContextRoot/admin/Brand
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
Query String Parameters
ln:primefaces
v:6.0
pfdrid:aed903cc-daba-4822-a62b-888b9a0ef2ac
pfdrt:sc
id:14
width:100
height:100
pfdrid_c:true
Заголовки запроса / ответа, использующие PrimeFaces 5.3 final (работают на GlassFish 4.1), когда на сервер делается первоначальный запрос на обслуживание изображения (работает как задумано - изображения кэшируются).
General
Request URL:https://localhost:8181/ContextRoot/javax.faces.resource/dynamiccontent.properties.xhtml?ln=primefaces&v=5.3&pfdrid=aAPHlxcQ2lcqfvzacYoCC6iUxLU1VVFp&pfdrt=sc&id=11&width=100&height=100&pfdrid_c=true
Request Method:GET
Status Code:200 OK
Remote Address:127.0.0.1:8181
Response Headers
Cache-Control:max-age=29030400
Date:Sat, 23 Jul 2016 07:15:03 GMT
Expires:Sun, 23 Jul 2017 07:15:04 GMT
Pragma:No-cache
Server:GlassFish Server Open Source Edition 4.1
Transfer-Encoding:chunked
X-Powered-By:Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1 Java/Oracle Corporation/1.8)
Request Headers
Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:JSESSIONID=69b5070218cfe0fc6eaac2141c13; __utma=111872281.616526714.1454485589.1468749319.1468751735.4; __utmz=111872281.1454485589.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Host:localhost:8181
Referer:https://localhost:8181/ContextRoot/admin/Brand
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
Query String Parameters
ln:primefaces
v:5.3
pfdrid:aAPHlxcQ2lcqfvzacYoCC6iUxLU1VVFp
pfdrt:sc
id:11
width:100
height:100
pfdrid_c:true
1 ответ
Заголовки выглядят хорошо. Это говорит о том, что что-то в параметрах строки запроса изменяется от запроса к запросу. Это также будет интерпретироваться как совершенно новый ресурс и, таким образом, разрушит кэширование, даже если базовый URI (часть перед разделителем строки запроса URL) ?
) точно так же.
И действительно, PrimeFaces 6.0 изменил способ pfdrid
Параметр строки запроса генерируется. Это стало совершенно случайным UUID
который меняется каждый раз, когда HTML <img src>
оказано. Смотрите также строку 59 исходного кода PF 6.0. В PrimeFaces 5.3 он был зашифрован на основе строки выражения EL и, таким образом, гарантированно будет одинаковым в запросах, если строка выражения EL одинакова. См. Также строку 53 исходного кода PF 5.3.
Изменение было введено Cagatay без ссылки на тикет. Так что остается неясным, почему именно это изменение было сделано. Но, в конце концов, это больше не дает клиенту возможности кэшировать динамический контент и, таким образом, фактически снижает производительность в обоих концах. На PrimeFaces это определенно стоит билет для выпуска, поэтому я его создал: выпуск 1765.
Я не вижу чистого способа решить эту проблему, кроме как взломать исходный код PrimeFaces. Ваш лучший выбор - заменить <p:graphicImage>
по <h:graphicImage>
с "простым ванильным сервлетом", или если вы используете библиотеку утилит JSF OmniFaces, то <o:graphicImage>
с простым бобом. Эти подходы уже подробно описаны в соответствующих вопросах и ответах: Показать изображение в виде байта [] из базы данных в виде графического изображения на странице JSF.
Обновление: согласно проблеме 1765, это было исправлено для PrimeFaces 6.1.
У меня была такая же проблема с этим компонентом простых шрифтов для изображений, потому что он добавляет параметр ?pfdrid_c=true
используется для контроля Cache-Control
Я использовал это так (элемент Primefaces):
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"...>
<p:graphicImage value="/url/images" />
и я решил использовать этот другой элемент jsf, который отлично работает для меня, поскольку он не вводит параметр:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"...>
<h:graphicImage value="/url/images" />
Как очень хорошо разъяснено @BalusC, это работает, только если значение представляет собой строку, представляющую URL-адрес.