典型的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
(例如,包含两个字段:articleName
和articleId
,其中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中实现此功能?
答案 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;
}
}
}
WebFilter
或NavigationHandler
。最好的选择是什么,嗯,这取决于。所有这些都有其优点和缺点。