在<view-id>中使用PrettyFaces </view-id>中的路径参数

时间:2013-02-22 12:54:05

标签: prettyfaces pretty-urls

典型的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字段的setter中定义为唯一值):

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

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

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

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

2 个答案:

答案 0 :(得分:1)

我认为Stackoverflow不适合讨论PrettyFaces的提案。你应该看一下PrettyFaces Support Forum

您可以选择实施类似的选项。恕我直言,你可以尝试这个视图DynaView。即使模式和视图之间存在一对一的关系,就像你写的一样。但是dynaview存在一些问题,尤其是出站重写问题。

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

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

查看重写的configuration examples

答案 1 :(得分: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

最好的选择是什么,嗯,这取决于。所有这些都有其优点和缺点。