我有一个定义明确的界面的应用程序。它使用CDI解析模块(具体地说,它使用API接口上的Instance <>注入点来解析模块),并通过接口将各种数据传回第四个,而不会出现问题。我故意将API和实现分开,并且模块仅从API继承以避免紧密耦合,并且应用程序仅通过运行时相关性以及通过API完成的数据传递来了解模块。应用程序在没有模块的情况下运行良好,只需将jar放到WEB- INF / lib文件夹中,然后重新启动应用程序服务器即可添加。
我遇到问题的地方是我希望模块创建视图的一部分,因此我想以可移植的方式调用JSF组件,或者从模块中进行包含以使其具有视图呈现其视图。我已经解决了我要调用的模块,并且已经准备好对该模块接口的引用。我最初的想法是做一个ui:include,要求模块提供视图模板的位置,但是我不知道如何以有意义的方式回答该查询,因为视图解析是由应用程序完成的根目录,而不是库根目录。
执行摘要是,我不知道如何使用JSF for .xhtml(模板/组件)文件从Application跳到Library。
使用CC会很好,但是如何指定在运行时需要特定的CC实例,而不是将其硬编码到页面中?
我当然可以直接调用应用程序代码并要求它做标记,但是这看起来确实是蛮力的,一旦有了标记,就不确定如何告诉JSF对其进行评估。就是说,我可以想象一个组件将采用资源路径,获取标记并对其进行评估,并返回完成的标记,我只是不知道如何实现。
我宁愿避免强迫模块开发人员尽可能采用繁重的UIComponent方法,这意味着采用动态方式执行ui:include(或某些等效方式)或采用动态方式调用CC。(如果这样做会使模块开发人员的工作变得更轻松,那么我不介意在应用程序中编码UIComponent方法ONCE)
关于我应该在哪里解决的任何建议?(如果我先找到答案,则会在此处发布答案)
我了解您的问题基本上可以归结为 如何在JAR中包含Facelets视图?
您可以通过ResourceResolver在JAR中放置一个自定义来实现。
ResourceResolver
public class FaceletsResourceResolver extends ResourceResolver { private ResourceResolver parent; private String basePath; public FaceletsResourceResolver(ResourceResolver parent) { this.parent = parent; this.basePath = "/META-INF/resources"; // TODO: Make configureable? } @Override public URL resolveUrl(String path) { URL url = parent.resolveUrl(path); // Resolves from WAR. if (url == null) { url = getClass().getResource(basePath + path); // Resolves from JAR. } return url; } }
在webapp web.xml中进行如下配置:
web.xml
<context-param> <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name> <param-value>com.example.FaceletsResourceResolver</param-value> </context-param>
想象一下,你已经一/META-INF/resources/foo/bar.xhtml中random.jar,那么你可以只包括它的常规方式
/META-INF/resources/foo/bar.xhtml
random.jar
<ui:include src="/foo/bar.xhtml" />
甚至是动态的
<ui:include src="#{bean.path}" />
注意:由于Servlet 3.0和更高版本的JBoss / JSF 2.0版本,ResourceResolver如果将文件保存在文件/META- INF/resources夹中,则不需要整个方法。上面ResourceResolver的仅在Servlet 2.5或更早的JBoss / JSF版本中是强制性的,因为它们在META-INF资源解析中存在错误。
/META- INF/resources
META-INF