Получение шаблонов / файлов Facelets из внешней файловой системы или базы данных

Я могу успешно заставить это работать с шаблоном в моем приложении:

<ui:decorate template="/WEB-INF/templates/mytemplate.xhtml">

Я также могу переместить шаблон в /META-INF/templates/mytemplate.xhtml банку и заставить это работать:

<ui:decorate template="/templates/mytemplate.xhtml">

Я действительно хотел бы поместить этот файл в файловую систему (или базу данных в этом отношении). Как мне этого добиться? Я нашел много вещей, связанных с com.sun.facelets.impl.DefaultResourceResolver, но я не думаю, что это на самом деле связано с переопределением подачи шаблона. Он не пытается разрешить URL, он просто пытается каким-то образом получить файл в пути к классам.

1 ответ

Решение

Если вы уже используете JSF 2.2, вы можете сделать это, предоставив ResourceHandler где вы возвращаете нужный ресурс просмотра в createViewResource(),

public class FaceletsResourceHandler extends ResourceHandlerWrapper {

    private ResourceHandler wrapped;

    public FaceletsResourceHandler(ResourceHandler wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public ViewResource createViewResource(FacesContext context, final String name) {
        ViewResource resource = super.createViewResource(context, name);

        if (resource == null) {
            resource = new ViewResource() {
                @Override
                public URL getURL() {
                    try {
                        return new File("/some/base/path", name).toURI().toURL();
                    } catch (MalformedURLException e) {
                        throw new FacesException(e);
                    }
                }
            };
        }

        return resource;
    }

    @Override
    public ResourceHandler getWrapped() {
        return wrapped;
    }

}

Который зарегистрирован в faces-config.xml как показано ниже:

<application>
    <resource-handler>com.example.FaceletsResourceHandler</resource-handler>
</application>

Или, если вы еще не используете JSF 2.2, используйте ResourceResolver вместо.

public class FaceletsResourceResolver extends ResourceResolver {

    private ResourceResolver parent;

    public FaceletsResourceResolver(ResourceResolver parent) {
        this.parent = parent;
    }

    @Override
    public URL resolveUrl(String path) {
        URL url = parent.resolveUrl(path); // Resolves from WAR.

        if (url == null) {
            try {
                url = new File("/some/base/path", path).toURI().toURL();
            } catch (MalformedURLException e) {
                throw new FacesException(e);
            }

        }

        return url;
    }

}

Который зарегистрирован в web.xml как показано ниже:

<context-param>
    <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
    <param-value>com.example.FaceletsResourceResolver</param-value>
</context-param>

Независимо от способа, для предоставления ресурса из базы данных, вы должны либо сохранить / кэшировать их в (временную) дисковую файловую систему, чтобы вы могли предоставить URL только через File или придумать собственный протокол, такой как db:// и предоставить обычай URLStreamHandlerFactory а также URLStreamHandlerреализация для выполнения фактической работы потоковой передачи из БД. Вы можете найти пример запуска здесь Регистрация и использование собственного протокола java.net.URL.

Другие вопросы по тегам