静态服务JSF组件框架Javascript和CSS

静态服务JSF组件框架Javascript和CSS,jsf,richfaces,webserver,Jsf,Richfaces,Webserver,我使用的是RichFaces 3.3.1,我试图找出是否有一种方法可以将RichFaces CSS和Javascript作为静态资源从另一个web服务器(如Apache或Nginx)托管 我尝试将web.xml中的org.ajax4jsf.RESOURCE\u URI\u PREFIX初始化参数设置为另一个web服务器,但URI仍然是相对于web应用程序的 我还尝试从RichFaces jar中提取两个Javascript文件 framework.pack.js ui.pack.js 将以下

我使用的是RichFaces 3.3.1,我试图找出是否有一种方法可以将RichFaces CSS和Javascript作为静态资源从另一个web服务器(如Apache或Nginx)托管

我尝试将web.xml中的
org.ajax4jsf.RESOURCE\u URI\u PREFIX
初始化参数设置为另一个web服务器,但URI仍然是相对于web应用程序的

我还尝试从RichFaces jar中提取两个Javascript文件

  • framework.pack.js
  • ui.pack.js
将以下内容添加到web.xml中

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

org.richfaces.LoadScriptStrategy
没有一个
然后在xhtml中包含来自另一台服务器的Javascript文件。不幸的是,在我这么做之后,许多RichFaces组件都无法工作

还有其他的想法吗?
有人用JSF组件框架成功地做到了这一点吗?

我意识到这不是版本3.3中的答案,但如果您可以升级到Richfaces 4 final,那么他们有一个漂亮的小功能,您可以将其添加到web.xml:

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

编辑:

我有时做的另一件事(在JSF2中)就是抑制库提供者包含的资源的版本。然后我只是创建一个静态版本,并将其包含在我的facelets模板中,或者在项目中有意义的任何地方。它不那么优雅,但如果您将资源组合在一起以获得性能或类似性能,它会工作得很好

为此,我首先通过将以下内容添加到faces-config.xml中,为脚本和样式表定义一些客户呈现器:

faces 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>
<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>

javax.faces.Output
javax.faces.resource.Script
com.davemple.jsf.resource.ScriptRenderer
javax.faces.Output
javax.faces.resource.Stylesheet
com.davemple.jsf.resource.StylesheetRenderer
然后,我向web.xml添加了一些要抑制的文件或类:

<context-param>
    <param-name>org.richfaces.staticResourceLocation</param-name>
    <param-value>#{resourceLocation}</param-value>
</context-param>
web.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>
<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>

com.davemple.jsf.resource.suppressedScriptResourceClasses
com.davemple.jsf.resource.suppressedScripts
javax.faces:jsf.js:jquery.js:richfaces.js:richfaces-event.js:richfaces-base-component.js org.richfaces:message.js org.richfaces:richfaces-csv.js
com.davemple.jsf.resource.suppressedStylesheetResourceClasses
com.davemple.jsf.resource.suppressedStylesheets
org.richfaces:msg.ecss
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);

        }
    }

}
/**
 * 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);
        }
    }

}
/**
*一种客户脚本呈现程序,允许特定资源
*手动抑制和管理(CDN、静态资源服务器、合并资源)
*
*/
公共类ScriptRenderer扩展了ScriptStyleBaseRenderer{
私有静态最终字符串分隔符=”;
私有静态最终字符串库_DELIMITER=“:”;
私有静态最终字符串suppressed_CLASSES_INIT_PARAM=“com.davemple.jsf.resource.suppressedScriptResourceClasses”;
私人最终名单>();
私有静态最终字符串suppressed_SCRIPTS_INIT_PARAM=“com.davemple.jsf.resource.suppressedScripts”;
private final List suppressedScriptNames=new ArrayList();
/**
*建造师
*/
公共脚本渲染器(){
超级();
字符串抑制类=
FacesContext.getCurrentInstance().getExternalContext().getInitParameter(suppressed_CLASSES_INIT_PARAM);
if(suppressedClasses!=null
&&!suppressedClasses.isEmpty()){
for(字符串suppressedClassString:suppressedClasses.split(分隔符)){
试一试{
add(Class.forName(suppressedClassString));
}捕获(ClassNotFoundException ex){
}
}
}
字符串抑制脚本=
FacesContext.getCurrentInstance().getExternalContext().getInitParameter(suppressed_SCRIPTS_INIT_PARAM);
if(suppressedScripts!=null
&&!suppressedScripts.isEmpty()){
for(字符串suppressedScript:suppressedScripts.split(分隔符)){
this.suppressedScriptNames.add(suppressedScript);
}
}        
}
/**
*返回一个布尔值,指示组件是否应
*被编码并如此呈现
* 
*@param组件
*@return-isSuppressed
*/
受保护的布尔值isSuppressed(UIComponent组件){
if(this.supersedClasses.contains(component.getClass())){
返回true;
}
if(component.getAttributes().containsKey(“名称”)
&&component.getAttributes().containsKey(“库”)){
字符串键=component.getAttributes().get(“库”)+库分隔符+component.getAttributes().get(“名称”);
if(this.suppressedScriptNames.contains(key)){
返回true;
}
}
if(component.getAttributes().containsKey(“名称”)
&&!component.getAttributes().containsKey(“库”)){
String key=LIBRARY_DELIMITER+component.getAttributes().get(“name”);
if(this.suppressedScriptNames.contains(key)){
返回true;
}
}
返回false;
}
@凌驾
受保护的void startElement(ResponseWriter编写器、UIComponent组件)引发IOException{
startElement(“脚本”,组件);
writeAttribute(“type”、“text/javascript”、“type”);
}
@凌驾
受保护的void endElement(ResponseWriter写入程序)引发IOException{
作者:恩德莱恩(“剧本”);
}
@凌驾
public void encodeBegin(FacesContext上下文,UIComponent)引发IOException{
如果(!this.isSuppressed(组件)){
super.encodeBegin(上下文、组件);
}
}
@凌驾
public void encodeEnd(FacesContext上下文,UIComponent)引发IOException{
如果(!t