2

典型 JSF 应用程序中的许多页面都是动态的,这意味着有一个模板视图可用于呈现给定类型的每个对象。对于这些页面,PrettyFaces 重写解决方案非常有效且轻松。一个示例是基于其 id 或其他唯一字段显示产品的 Web 应用程序。通常有一个与这样的显示相关的视图,比如product.xhtml,和一个视图参数,保存产品的唯一字段,比如name

通过一个简单的设置,我们得到所有请求/product.xhtml?name=exact-product-name,例如重写为/products/exact-product-name

网址映射:

<url-mapping id="viewProduct">
    <pattern value="/products/#{ name : productBean.name }" />
    <view-id value="/store/product.xhtml" />
    <action> #{ productBean.loadData } </action>
</url-mapping>

风景:

<f:metadata>
    <f:viewParam id="name" name="name" required="true" />
</f:metadata>

该模型:

public class ProductBean implements Serializable {

    private ProductService productService;

    private String name;

    private Product product;

    public String loadData() {
        if(!((name == null) || (name.equals(""))) {
            Product product = productService.findByName(name);
            this.product = product;
            return null;
        }
        return "error";
    }

}

但是,也有许多具有静态数据的页面,它们没有以上述方式使用视图参数进行模板化。这些页面仅显示放入其中的内容。例如,可能有许多文章被创建为单独的视图(如/pages/articles/article1.xhtml等)。使用 PrettyFaces,我们需要创建与此类页面数量一样多的 URL 映射。但是,实际上这种行为也可以在一个 URL 映射中进行模板化。不幸的是,当前 PrettyFaces 版本不支持此功能。

PrettyFaces 框架的建议增强功能如下:

<url-mapping id="viewArticle">
    <pattern value="/articles/#{ articleName }" />
    <view-id value="/store/#{ articleName }.xhtml" />
</url-mapping>

或者,使用ArticleBean(例如,包含两个字段:articleNamearticleId,其中 name 在 id 字段的设置器中定义为唯一值):

<url-mapping id="viewArticle">
    <pattern value="/articles/#{ articleId : articleBean.articleId }" />
    <view-id value="/store/#{ articleBean.articleName }.xhtml" />
</url-mapping>

或者使用基于 EL 表达式的其他预定义依赖关系,该 EL 表达式又基于唯一对应关系。

我想强调这不会是 a因为 view-id 中没有不确定性: a和 aDynaView之间存在一对一的对应关系。<pattern><view-id>

您如何看待在 PrettyFaces 中实现此功能?

4

2 回答 2

1

我认为 Stackoverflow 不是讨论 PrettyFaces 提案的合适场所。你应该看看PrettyFaces 支持论坛

您可以选择一些选项来实现这样的事情。恕我直言,您可以尝试执行此视图 DynaView。即使像您所写的那样,模式和视图 ID 之间存在一对一的关系。然而 dynaview 有一些问题,特别是在出站重写方面。

但是你应该看看Rewrite,它是 PrettyFaces 的继承者。使用 Rewrite 实现这样的要求非常简单:

.addRule(Join.path("/articles/{articleName}").to("/store/{articleName}.xhtml"))

看看 Rewrite 的配置示例

于 2013-02-22T15:34:06.007 回答
0

至于pretty-config.xml当前不支持此功能的设置,有一些解决方法可以实现此功能。我将在下面描述它们。

一个虚拟视图,<f:event>它根据虚拟 bean 中的视图参数处理到最终页面的导航。

网址映射:

<url-mapping id="viewArticle">
    <pattern value="/articles/#{ articleName : articleBean.articleName }" />
    <view-id value="/handle-article-redirection.xhtml" />
</url-mapping>

查看handle-article-redirection.xhtml

<f:metadata>
    <f:viewParam id="articleName" name="articleName" required="true" />
    <f:event type="preRenderView" listener="#{articleBean.handleRedirect}" />
</f:metadata>

模型:

public class ArticleBean {

    private ArticleService articleService;

    private String articleName;

    private String articleUrl;

    public void handleRedirect() {
        if(!((articleName == null) || (articleName.equals(""))) {
            String url = articleName;
            //String url = articleService.getUrlForArticleName(articleName);
            //articleUrl = url;
            FacesContext.getCurrentInstance().getExternalContext().redirect("/" + url + ".xhtml");
            return null;
        }
        FacesContext.getCurrentInstance().getExternalContext().redirect("/home.xhtml");
    }

}

一个有意义的动态视图,<ui:include>它基于 bean 值/视图参数将必要的页面内容作为片段导入。

网址映射:

<url-mapping id="viewArticle">
    <pattern value="/articles/#{ articleName : articleBean.articleName }" />
    <view-id value="/article.xhtml" />
</url-mapping>

查看article.xhtml

<f:metadata>
    <f:viewParam id="articleName" name="articleName" required="true" />
</f:metadata>
<h:head></h:head>
<h:body>
    <ui:include src="/#{articleBean.articleUrl}.xhtml" />
</h:body>

模型:

public class ArticleBean {

    private ArticleService articleService;

    private String articleName;

    private String articleUrl;

    public void setArticleName(String articleName) {
        this.articleName = articleName;
        if((!(articleName == null)) || (articleName.equals("")) {
            articleUrl = articleName;
            //articleUrl = articleService.getUrlForArticleName(articleName);
        } else {
             articleUrl = null;
        }
    }

}

DynaView带有返回正确结果的方法的URL 映射。

网址映射:

<url-mapping id="viewArticle">
    <pattern value="/articles/#{ articleName : articleBean.articleName }" />
    <view-id value="#{articleBean.getViewPath}" />
</url-mapping>

不需要额外的视图。

模型:

public class ArticleBean {

    private ArticleService articleService;

    private String articleName;

    private String articleUrl;

    public String getViewPath() {
        this.articleName = articleName;
        if(!((articleName == null) || (articleName.equals(""))) {
            articleUrl = articleName;
            //articleUrl = articleService.getUrlForArticleName(articleName);
            return articleUrl;
        }
        return "error";
    }

}

从数据库加载页面数据的模板视图,因此这些页面不会有单独的视图。

网址映射:

<url-mapping id="viewArticle">
    <pattern value="/articles/#{ articleName : articleBean.articleName }" />
    <view-id value="/article.xhtml" />
    <action> #{ articleBean.loadData } </action>
</url-mapping>

查看article.xhtml

<f:metadata>
    <f:viewParam id="articleName" name="articleName" required="true" />
</f:metadata>
<h:head></h:head>
<h:body>
    <h:panelGroup>
        #{articleBean.content}
    <h:panelGroup>
</h:body>

模型:

public class ArticleBean {

    private ArticleService articleService;

    private String articleName;

    private String articleUrl;

    private String content;

    public void loadData() {
        if(!((articleName == null) || (articleName.equals(""))) {
            articleUrl = articleName;
            //articleUrl = articleService.getUrlForArticleName(articleName);
            content = articleService.getContentForArticleName(articleName);
        } else {
             articleUrl = null;
             content = null;
        }
    }

}

编写自定义WebFilterNavigationHandler.

什么是最好的选择,好吧,这取决于。他们都有自己的优点和缺点。

于 2013-02-22T12:55:38.793 回答