Статически обслуживать JSF компонент фреймворка Javascript и CSS - PullRequest
2 голосов
/ 25 мая 2011

Я использую RichFaces 3.3.1 и пытаюсь выяснить, есть ли способ разместить RichFaces CSS и Javascript в качестве статических ресурсов от другого веб-сервера, такого как Apache или Nginx.

I 'мы попытались установить параметр инициализации org.ajax4jsf.RESOURCE_URI_PREFIX в web.xml для другого веб-сервера, но URI по-прежнему относился к веб-приложению.

Я также попытался извлечь два файла Javascript из RichFaces jar

  • framework.pack.js
  • ui.pack.js

добавил следующее в web.xml.

<context-param>
    <param-name>org.richfaces.LoadScriptStrategy</param-name>
    <param-value>NONE</param-value>
</context-param>

а затем в xhtml включены файлы Javascript с другого сервера.К сожалению, многие компоненты RichFaces не работали после того, как я это сделал.

Есть еще идеи, как это можно сделать?У кого-нибудь был какой-либо успех, делающий это с каркасами компонентов JSF?

1 Ответ

3 голосов
/ 26 мая 2011

Я понимаю, что это не ответ в версии 3.3, но если вы можете выполнить обновление до финальной версии Richfaces 4, то у них есть эта изящная маленькая функция, где вы можете добавить это в web.xml:

<context-param>
    <param-name>org.richfaces.staticResourceLocation</param-name>
    <param-value>#{resourceLocation}</param-value>
</context-param>

и затем в META-INF вы можете включить статический файл сопоставления ресурсов. Полный путь / имя файла:

META-INF / RichFaces / static-resource-mappings.properties

Содержимое которых:

jquery.js=https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js
richfaces.js=https://mystaticimageserver.com/img/richfaces.js

EDIT:

Еще одна вещь, которую я иногда делаю (в JSF 2), это просто подавление версии ресурса, который включает провайдер библиотеки. Затем я просто создаю статическую версию и сам включаю ее в свой шаблон Facelets или в любое другое место, где это имеет смысл в вашем проекте. Это менее элегантно, но хорошо работает, если вы объединяете ресурсы для повышения производительности или чего-то подобного.

Для этого я сначала определяю некоторые средства визуализации клиентов для скриптов и таблиц стилей, добавляя их в face-config.xml:

лица-config.xml

<render-kit>
    <renderer>
        <component-family>javax.faces.Output</component-family>
        <renderer-type>javax.faces.resource.Script</renderer-type>
        <renderer-class>com.davemaple.jsf.resource.ScriptRenderer</renderer-class>
    </renderer>
    <renderer>
        <component-family>javax.faces.Output</component-family>
        <renderer-type>javax.faces.resource.Stylesheet</renderer-type>
        <renderer-class>com.davemaple.jsf.resource.StylesheetRenderer</renderer-class>
    </renderer>
</render-kit>

Затем я добавляю некоторые файлы или классы, которые хочу подавить, в web.xml:

web.xml

<context-param>
    <param-name>com.davemaple.jsf.resource.suppressedScriptResourceClasses</param-name>
    <param-value></param-value>
</context-param>

<context-param>
    <param-name>com.davemaple.jsf.resource.suppressedScripts</param-name>
    <param-value>javax.faces:jsf.js :jquery.js :richfaces.js :richfaces-event.js :richfaces-base-component.js org.richfaces:message.js org.richfaces:richfaces-csv.js</param-value>
</context-param>

<context-param>
    <param-name>com.davemaple.jsf.resource.suppressedStylesheetResourceClasses</param-name>
    <param-value></param-value>
</context-param>

<context-param>
    <param-name>com.davemaple.jsf.resource.suppressedStylesheets</param-name>
    <param-value>org.richfaces:msg.ecss</param-value>
</context-param>

ScriptRenderer.java

/**
 * A Customer ScriptRenderer that allows specific resources to be  
 * suppressed and managed manually (CDN, Static Resource Server, Combining resources)
 *
 */
public class ScriptRenderer extends ScriptStyleBaseRenderer {

    private static final String DELIMITER = " ";
    private static final String LIBRARY_DELIMITER = ":";

    private static final String SUPRESSED_CLASSES_INIT_PARAM = "com.davemaple.jsf.resource.suppressedScriptResourceClasses";
    private final List<Class<?>> supressedClasses = new ArrayList<Class<?>>();

    private static final String SUPRESSED_SCRIPTS_INIT_PARAM = "com.davemaple.jsf.resource.suppressedScripts";
    private final List<String> suppressedScriptNames = new ArrayList<String>();

    /**
     * Constructor
     */
    public ScriptRenderer() {
        super();

        String suppressedClasses = 
            FacesContext.getCurrentInstance().getExternalContext().getInitParameter(SUPRESSED_CLASSES_INIT_PARAM);

        if (suppressedClasses != null
                && !suppressedClasses.isEmpty()) {
            for (String suppressedClassString : suppressedClasses.split(DELIMITER)) {
                try {
                    this.supressedClasses.add(Class.forName(suppressedClassString));
                } catch (ClassNotFoundException ex) {
                }
            }
        }

        String suppressedScripts = 
            FacesContext.getCurrentInstance().getExternalContext().getInitParameter(SUPRESSED_SCRIPTS_INIT_PARAM);

        if (suppressedScripts != null
                && !suppressedScripts.isEmpty()) {
            for (String suppressedScript : suppressedScripts.split(DELIMITER)) {
                this.suppressedScriptNames.add(suppressedScript);
            }
        }        
    }

    /**
     * Returns a boolean indicating if the component should
     * be encoded and thus rendered
     * 
     * @param component
     * @return isSuppressed
     */
    protected boolean isSuppressed(UIComponent component) {

        if (this.supressedClasses.contains(component.getClass())) {
            return true;
        }

        if (component.getAttributes().containsKey("name")
                && component.getAttributes().containsKey("library")) {

            String key = component.getAttributes().get("library") + LIBRARY_DELIMITER + component.getAttributes().get("name");

            if (this.suppressedScriptNames.contains(key)) {
                return true;
            }
        }

        if (component.getAttributes().containsKey("name")
                && !component.getAttributes().containsKey("library")) {

            String key = LIBRARY_DELIMITER + component.getAttributes().get("name");

            if (this.suppressedScriptNames.contains(key)) {
                return true;
            }
        }

        return false;
    }

    @Override
    protected void startElement(ResponseWriter writer, UIComponent component) throws IOException {
        writer.startElement("script", component);
        writer.writeAttribute("type", "text/javascript", "type");
    }

    @Override
    protected void endElement(ResponseWriter writer) throws IOException {
        writer.endElement("script");
    }

    @Override
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {

        if (!this.isSuppressed(component)) {
            super.encodeBegin(context, component);
        }
    }


    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {

        if (!this.isSuppressed(component)) {

            Map<String, Object> attributes = component.getAttributes();
            Map<Object, Object> contextMap = context.getAttributes();

            String name = (String) attributes.get("name");
            String library = (String) attributes.get("library");

            String key = name + library;

            if (null == name) {
                return;
            }

            // Ensure this script is not rendered more than once per request
            if (contextMap.containsKey(key)) {
                return;
            }
            contextMap.put(key, Boolean.TRUE);

            // Special case of scripts that have query strings
            // These scripts actually use their query strings internally, not
            // externally
            // so we don't need the resource to know about them
            int queryPos = name.indexOf("?");
            String query = null;
            if (queryPos > -1 && name.length() > queryPos) {
                query = name.substring(queryPos + 1);
                name = name.substring(0, queryPos);
            }

            Resource resource = context.getApplication().getResourceHandler()
                    .createResource(name, library);

            ResponseWriter writer = context.getResponseWriter();
            this.startElement(writer, component);

            String resourceSrc;
            if (resource == null) {
                resourceSrc = "RES_NOT_FOUND";
            } else {
                resourceSrc = resource.getRequestPath();
                if (query != null) {
                    resourceSrc = resourceSrc
                            + ((resourceSrc.indexOf("?") > -1) ? "+" : "?") + query;
                }
            }

            writer.writeURIAttribute("src", resourceSrc, "src");
            this.endElement(writer);
            super.encodeEnd(context, component);

        }
    }

}

ScriptRenderer.java

/**
 * A Customer StylesheetRenderer that allows specific resources to be  
 * suppressed and managed manually (CDN, Static Resource Server, Combining resources)
 *
 */
public class StylesheetRenderer extends ScriptStyleBaseRenderer {

    private static final String DELIMITER = " ";
    private static final String LIBRARY_DELIMITER = ":";

    private static final String SUPRESSED_CLASSES_INIT_PARAM = "com.davemaple.jsf.resource.suppressedStylesheetResourceClasses";
    private final List<Class<?>> supressedClasses = new ArrayList<Class<?>>();

    private static final String SUPPRESSED_STYLESHEETS_INIT_PARAM = "com.davemaple.jsf.resource.suppressedStylesheets";
    private final List<String> suppressedStylesheets = new ArrayList<String>();

    /**
     * Constructor
     */
    public StylesheetRenderer() {
        super();

        String suppressedClasses = 
            FacesContext.getCurrentInstance().getExternalContext().getInitParameter(SUPRESSED_CLASSES_INIT_PARAM);

        if (suppressedClasses != null
                && !suppressedClasses.isEmpty()) {
            for (String suppressedClassString : suppressedClasses.split(DELIMITER)) {
                try {
                    this.supressedClasses.add(Class.forName(suppressedClassString));
                } catch (ClassNotFoundException ex) {
                }
            }
        }

        String suppressedStylesheets = 
            FacesContext.getCurrentInstance().getExternalContext().getInitParameter(SUPPRESSED_STYLESHEETS_INIT_PARAM);

        if (suppressedStylesheets != null
                && !suppressedStylesheets.isEmpty()) {
            for (String suppressedStylesheet : suppressedStylesheets.split(DELIMITER)) {
                this.suppressedStylesheets.add(suppressedStylesheet);
            }
        }        
    }

    /**
     * Returns a boolean indicating if the component should
     * be encoded and thus rendered
     * 
     * @param component
     * @return isSuppressed
     */
    protected boolean isSuppressed(UIComponent component) {

        if (this.supressedClasses.contains(component.getClass())) {
            return true;
        }

        if (component.getAttributes().containsKey("name")
                && component.getAttributes().containsKey("library")) {

            String key = component.getAttributes().get("library") + LIBRARY_DELIMITER + component.getAttributes().get("name");

            if (this.suppressedStylesheets.contains(key)) {
                return true;
            }
        }

        if (component.getAttributes().containsKey("name")
                && !component.getAttributes().containsKey("library")) {

            String key = LIBRARY_DELIMITER + component.getAttributes().get("name");

            if (this.suppressedStylesheets.contains(key)) {
                return true;
            }
        }

        return false;
    }

    @Override
    protected void startElement(ResponseWriter writer, UIComponent component)
            throws IOException {
        writer.startElement("style", component);
        writer.writeAttribute("type", "text/css", "type");
    }

    @Override
    protected void endElement(ResponseWriter writer) throws IOException {
        writer.endElement("style");
    }

    @Override
    protected String verifyTarget(String toVerify) {
        return "head";
    }

    @Override
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {

        if (!this.isSuppressed(component)) {
            super.encodeBegin(context, component);
        }
    }


    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {

        if (!this.isSuppressed(component)) {
            Map<String, Object> attributes = component.getAttributes();
            Map<Object, Object> contextMap = context.getAttributes();

            String name = (String) attributes.get("name");
            String library = (String) attributes.get("library");
            String key = name + library;

            if (null == name) {
                return;
            }

            // Ensure this stylesheet is not rendered more than once per request
            if (contextMap.containsKey(key)) {
                return;
            }
            contextMap.put(key, Boolean.TRUE);

            Resource resource = context.getApplication().getResourceHandler()
                    .createResource(name, library);

            ResponseWriter writer = context.getResponseWriter();
            writer.startElement("link", component);
            writer.writeAttribute("type", "text/css", "type");
            writer.writeAttribute("rel", "stylesheet", "rel");
            writer.writeURIAttribute("href",
                    ((resource != null) ? resource.getRequestPath()
                            : "RES_NOT_FOUND"), "href");
            writer.endElement("link");
            super.encodeEnd(context, component);
        }
    }

}
...