如何创建模块化 JSF 2.0 应用程序? [英] How to create a modular JSF 2.0 application?

查看:21
本文介绍了如何创建模块化 JSF 2.0 应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有明确定义界面的应用程序.它使用 CDI 来解析模块(具体来说,它使用 API 接口上的 Instance<> 注入点来解析模块)并通过接口来回传递各种数据,而不会出现问题.我有意将 API 和实现分开,并且模块仅从 API 继承以避免紧密耦合,并且应用程序仅通过运行时依赖关系了解模块,并通过 API 完成数据传递.应用程序在没有模块的情况下运行良好,只需将 jar 放入 WEB-INF/lib 文件夹并重新启动应用服务器即可添加模块.

I have an application with a well defined interface. It uses CDI for resolution of the modules, (Specifically it uses Instance<> injection points on API interfaces to resolve modules) and passes various data back and fourth via the interfaces without issue. I've intentionally kept the API and implementation separate, and the modules only inherit from the API to avoid tight coupling, and the application only knows of the modules through runtime dependancies, and data passing accomplished via the APIs. The application runs fine without the modules, which can be added simply by dropping the jar into the WEB-INF/lib folder and restarting the app server.

我遇到的问题是我希望模块创建视图的一部分,因此我想以可移植的方式调用 JSF 组件,或者按顺序从模块中执行包含让它呈现它的视图.我已经解决了我想要调用的模块,并且已经准备好对模块接口的引用.我最初想这样做的方法是做一个 ui:include 要求模块提供它的视图模板在哪里,但我不知道如何以有意义的方式回答该查询,因为视图解析是从应用程序完成的根,而不是库根.

Where I'm running into issues is that I want the modules to create a portion of the view, and I therefor want to invoke, in a portable way, either a JSF component, or do an include from the module in order to have it render its view. I already have resolved what module I want to invoke, and have references to the module's interface ready. The way I initially thought to do this was to do a ui:include that asks the module to supply where it's view template is, but I have no idea how to answer that query in a meaningful way, as view resolution is done from the application root, not the library root.

执行摘要是,我不知道如何使用 JSF 为 .xhtml(模板/组件)文件跳过从应用程序到库的差距.

The executive summary is that I have no idea how to jump the gap from Application to Library using JSF for .xhtml (template/component) files.

使用 CC 会很好,但是我如何在运行时指定我想要一个特定的 CC 实例,而不是将其硬编码到页面中?

Using a CC would be nice, but how do I specify that I want a particular CC instance at runtime, instead of having that hard coded into the page?

我当然可以直接调用应用程序代码并要求它进行标记,但这似乎是蛮力,一旦我有了标记,我不确定如何告诉 JSF 对其进行评估.也就是说,我可以想象一个组件会获取资源路径,获取标记并对其进行评估,返回完成的标记,我只是不知道如何实现.

I can of course invoke the application code directly and ask it for markup, but this seems really brute force, and once I have the markup, I'm not sure exactly how to tell JSF to evaluate it. That said, I can imagine a component that would take the resource path, grab the markup and evaluate it, returning the completed markup, I just don't know how to implement that.

如果可能的话,我宁愿避免强迫模块开发人员采用繁重的 UIComponent 方法,这意味着要么以动态方式执行 ui:include(或某种等效方式),要么以动态方式调用 CC.(我不介意在应用程序中一次性编写 UIComponent 方法,如果这能让模块开发人员的生活更轻松)

I'd rather avoid forcing module developers to go the heavy duty UIComponent approach if possible, which means either a dynamic way of doing ui:include (or some equivalent) or a dynamic way of invoking CCs. (I don't mind coding the UIComponent approach ONCE in the application if that's what it takes to make module developers' lives easier)

关于我应该在哪里解决这个问题的任何建议?(如果我先找到答案,我会在这里发布)

Any suggestions on where I should look to figure this out? (I'll post the answer here if I find it first)

推荐答案

我知道您的问题基本上归结为如何在 JAR 中包含 Facelets 视图?

I understand that your question basically boils down to How can I include Facelets views in a JAR?

您可以通过放置自定义ResourceResolver 在 JAR 中.

You can do this by placing a custom ResourceResolver in the JAR.

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中配置如下:

Configure this in webapp's web.xml as follows:

<context-param>
    <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
    <param-value>com.example.FaceletsResourceResolver</param-value>
</context-param>

假设您在 random.jar 中有一个 /META-INF/resources/foo/bar.xhtml,那么您可以按照通常的方式包含它

Imagine that you've a /META-INF/resources/foo/bar.xhtml in random.jar, then you can just include it the usual way

<ui:include src="/foo/bar.xhtml" />

甚至动态

<ui:include src="#{bean.path}" />

注意:由于 Servlet 3.0 和更新的 JBoss/JSF 2.0 版本,如果您将文件保存在 /META-INF/resources 文件夹中,则不需要整个 ResourceResolver 方法.上述 ResourceResolver 仅在 Servlet 2.5 或更旧的 JBoss/JSF 版本中是必需的,因为它们在 META-INF 资源解析中存在错误.

Note: since Servlet 3.0 and newer JBoss/JSF 2.0 versions, the whole ResourceResolver approach is not necessary if you keep the files in /META-INF/resources folder. The above ResourceResolver is only mandatory in Servlet 2.5 or older JBoss/JSF versions because they've bugs in META-INF resource resolving.

这篇关于如何创建模块化 JSF 2.0 应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆