本文介绍了是否可以在JSF中包含一个文件夹中的所有javascripts文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用JSF 2.0,并且正在寻找一种方法来包含页面上给定文件夹中的所有javascript,即做类似的事情

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" />

这种事情甚至可能吗?我是否应该使用Java代码编写自定义组件来实现此目的?

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

感谢您的帮助,
塞巴斯蒂安·特朗普(SébastienTromp)

Thanks for your help,
Sébastien Tromp

推荐答案

好主意. JSF API不支持此功能,但是从理论上讲,使用自定义脚本渲染器是可能的.我在它周围玩了一些,这确实是可能的.只需创建一个MultiScriptRenderer其中extends ScriptRenderer并覆盖 encodeEnd() 来检查name属性是否包含*通配符,然后通过扫描匹配的文件来进行相应处理资源文件夹中的这种模式.

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.

这是一个开球示例:

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

按以下说明在faces-config.xml中进行注册(抱歉, @FacesRenderer 注释在JSF 2.2中针对此特殊情况进行修复之前无法使用,另请参见 JSF问题1748 ):

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>

此处在Mojarra 2.0.3上运行良好.您可以使用*.jsprefix*.js之类的模式.特定的代码示例仅与特定的JSF实现紧密结合,以节省代码样板.它还要求在部署时扩展WAR,否则将无法通过File#listFiles()浏览目录(因此不包括某些(较旧的)servlet容器版本/配置).对于其他JSF实现,您必须扩展其ScriptRenderer,或者如果您想要独立于实现,则编写一个全新的代码(尽管这应该非常简单,如果遇到困难,只需看一下标准ScriptRenderer源代码).

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).

这篇关于是否可以在JSF中包含一个文件夹中的所有javascripts文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 23:44