Is it possible to include all javascripts files from one folder in JSF?

佐手、 提交于 2020-08-21 19:46:24

问题


I am using JSF 2.0, and am looking for a means to include all the javascripts from a given folder on a page, i.e. do something like

<h:outputScript library="javascript" name="*.js" target="head" />

Is this kind of thing even possible? Should I write a custom component using java code to achieve this?

Thanks for your help,
Sébastien Tromp


回答1:


Nice idea. This is not supported by the JSF API, but it's in theory possible with a custom script renderer. I played somewhat around it and it's indeed possible. Just create a MultiScriptRenderer which extends ScriptRenderer and override encodeEnd() to check if the name attribute contains the * wildcard and then handle accordingly by scanning for files matching this pattern in the resources folder.

Here's a kickoff example:

package com.example;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import com.sun.faces.renderkit.html_basic.ScriptRenderer;

public class MultiScriptRenderer extends ScriptRenderer {

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        Map<String, Object> attributes = component.getAttributes();
        String name = (String) attributes.get("name");
        if (name.contains("*")) {
            String pattern = name.replace(".", "\\.").replace("*", ".*");
            String library = (String) attributes.get("library");
            File root = new File(context.getExternalContext().getRealPath("/resources/" + (library != null ? library : "")));
            for (File file : root.listFiles()) {
                if (file.getName().matches(pattern)) {
                    attributes.put("name", file.getName());
                    super.encodeEnd(context, component);
                }
            }
            attributes.put("name", name); // Put original name back. You never know.
        } else {
            super.encodeEnd(context, component);
        }
    }
}

Register it in faces-config.xml as follows (Sorry, @FacesRenderer annotation isn't going to work until it's fixed in JSF 2.2 for this specific corner case, see also JSF issue 1748):

<render-kit>
    <renderer>
        <component-family>javax.faces.Output</component-family>
        <renderer-type>javax.faces.resource.Script</renderer-type>
        <renderer-class>com.example.MultiScriptRenderer</renderer-class>
    </renderer>
</render-kit>

Works fine on Mojarra 2.0.3 here. You can use patterns like *.js and prefix*.js. The particular code example is only tight coupled to a specific JSF implementation to save code boilerplate. It also requires that the WAR is expanded on deploy, otherwise browsing the directory by File#listFiles() won't be possible (which thus excludes certain (older) servletcontainer versions/configurations). For other JSF implementations you'll have to extend its ScriptRenderer instead, or write a whole new one if you want to be implementation independent (which should be pretty simple though, just look at standard ScriptRenderer source if you stucks).




回答2:


I didn't test this, but if wildcards are not accepted, you could fetch the filelist via java code in a backing bean, and insert them into head using c:forEach or ui:repeat like:

<ui:repeat value="#{bean.files}" var="file">
    <h:outputScript library="javascript" name="#{file}" target="head" />
</ui:repeat>

Note that you cannot give absolute paths to h:outputScript but you must extract the prefix from them (the part the preceeds the JSF resources path).



来源:https://stackoverflow.com/questions/4482443/is-it-possible-to-include-all-javascripts-files-from-one-folder-in-jsf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!