o: возможно кэширование графических изображений? - PullRequest
0 голосов
/ 23 апреля 2020

В моей верхней панели у меня есть <o:graphicImage> для показа изображения от моего пользователя.

<o:graphicImage dataURI="true" height="32" width="32" styleClass="img-circle"
    value="#{employeeProfileMenuPictureRequestController.getPicture_32_32(loginBean.currentEmployee)}" 
    lastModified="#{employeeProfileMenuPictureRequestController.lastUpdate}" />

Мой бэкэнд-компонент выглядит следующим образом:

@GraphicImageBean
public class EmployeeProfileMenuPictureRequestController implements Serializable {

    private Date lastUpdate = new Date();

    public byte[] getPicture_32_32(Employee employee) throws StorageAttachmentNotFoundException, IOException {
        try {

            String path = employeeProfilePictureService.findProfileImageByEmployee(employee, FileSizeType.SIZE_32_32.toString());

            if (employee == null || path == null || path.isEmpty()) {
                return Utils.toByteArray(Faces.getResourceAsStream("/resources/images/no-photo-icon.png"));
            }

            Path fileLocation = Paths.get(path);
            byte[] data = Files.readAllBytes(fileLocation);
            LOGGER.info("END getPicture_32_32");
            return data;
        catch (Exception e) {
            LOGGER.error(ExceptionUtils.getFullStackTrace(e));
        }

        return Utils.toByteArray(Faces.getResourceAsStream("/resources/images/no-photo-icon.png"));
    }

    public Date getLastUpdate() {
        return lastUpdate;
    }
}

К сожалению, getPicture_32_32(Employee) - это вызывается для каждого запроса страницы / навигации по странице. Это означает, что это также каждый раз запрос к базе данных, который занимает время.

Я уже пытался добавить lastModified к <o:graphicImage>, но функция вызывается также каждый раз для каждого запроса страницы .

Кто-нибудь может мне помочь решить эту проблему?

1 Ответ

2 голосов
/ 24 апреля 2020

Согласно документации <o:graphicImage>:

URI данных

[...]

Однако этот подход не рекомендуется для «постоянных» и / или «больших» изображений, так как не дает браузеру никакой возможности кэшировать изображения для повторного использования, ~ 10 КБ, как правило, будет максимум даже меньше, поэтому если на одной странице больше таких изображений.

Итак, он вообще не поддерживает кэширование. Техническая причина в том, что он в основном включает все содержимое изображения в вывод HTML. Он не вставляет URL-адрес изображения. lastModified в основном игнорируется. Наверное, мне лучше документировать это. По крайней мере, вы должны полностью удалить атрибут dataURI. Это полезно только для предварительного просмотра загруженного изображения.

И,

Потоковое изображение

[...]

В случае, если Свойство - это выражение метода, принимающее аргументы, каждый из которых будет преобразован в строковый параметр HTTP-запроса и обратно в фактические объекты с использованием преобразователей, зарегистрированных классом как доступные через Application.createConverter(Class). Таким образом, большинство стандартных типов, таких как Long, уже неявно поддерживаются. Если вам по какой-то причине необходимо предоставить пользовательский объект в качестве аргумента, вам нужно явно зарегистрировать конвертер для него самостоятельно с помощью @FacesConverter(forClass).

Итак, поскольку ваш метод Возьмите аргумент Employee, вам нужно иметь @FacesConverter(forClass=Employee.class), чтобы JSF мог автоматически конвертировать его в String. Как создать конвертеры можно найти здесь: Значение параметра Ошибка преобразования для 'нулевого конвертера' - Зачем мне нужен конвертер в JSF?

В итоге вы должны получить что-то вроде этого:

@FacesConverter(forClass=Employee.class)
public class EmployeeConverter implements Converter {

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
        // Write code here which converts Employee to its unique String representation.
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
        // Write code here which coverts the Employee unique String representation
        // as created in above method back to the original Employee object.
    }

}

В качестве альтернативы можно настроить метод getPicture_32_32() так, чтобы идентификатор сотрудника, например, Long вместо сотрудника. Тогда вам не нужен специальный конвертер. JSF уже имеет встроенный конвертер для Long.

public byte[] getPicture_32_32(Long employeeId) {
    // ...
}

<o:graphicImage
    value="#{employeeProfileMenuPictureRequestController.getPicture_32_32(loginBean.currentEmployee.id)}" />

Возвращаясь к кешированию, документация гласит:

Кэширование

[...]

Если не указано, то «максимальный возраст ресурса по умолчанию», заданный в параметре контекста Mojarra c com.sun.faces.defaultResourceMaxAge или в параметре MyFaces c будет использоваться параметр контекста org.apache.myfaces.RESOURCE_MAX_TIME_EXPIRES, иначе будет принято значение по умолчанию 1 неделя .

Так что, если у вас нет настроек возраста ресурса, он по умолчанию уже кэшируется для 1 неделя. Таким образом, lastModified является необязательным и полезен, только когда вы фактически отслеживаете метку времени в той же базе данных или файловой системе, когда изображение фактически изменяется. Затем вы должны действительно использовать это для наиболее оптимального кэширования. «Случайная» дата абсолютно не верна.

...