首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在“命名空间模式”中使用jsf

如何在“命名空间模式”中使用jsf
EN

Stack Overflow用户
提问于 2020-05-15 09:12:25
回答 1查看 123关注 0票数 3

在一个网站中,我们希望集成jsf应用程序提供的一些片段,比如仪表板应用程序或“门户灯”。在分析需求时,我们看到了Arjan Tjims在JSF2.3新特性上发表的一篇博文,他在文章中提到了一种新的“命名空间模式”:

在命名空间模式(它是专为Portlet设计的,但也可以在其他环境中使用)中,部分响应被赋予一个被视为“命名容器id”的id。所有预定义的回发参数名称(如"javax.faces.ViewState“、"javax.faces.ClientWindow”、"javax.faces.RenderKitId“等)都以此和命名分隔符(默认值":")作为前缀。例如,javax.faces.ViewState“变成"myname:javax.faces.ViewState”。当UIViewRoot实例实现NamingContainer接口时,名称空间模式被激活。

我们的应用程序可能是那种“命名空间模式”的实用程序,因此我们想尝试一下。

我们构建了一个MyUIViewRoot,实现了NamingContainer并封装了原始的UIViewRoot-instance。我们在faces-config.xml中注册了一个faces-config.xml,它处理ViewRoot的包装。在测试中,我们使用了一个简单的反应用程序和两个<h:form>-elements (似乎很重要)。

我们发现“命名空间模式”似乎被激活了,比如javax.faces.ViewState确实被某些名称空间所占据,并变成了j_id1:javax.faces.ViewState:0。但是这两种操作都不再起作用--回发请求不再恢复View,而是创建了一个新的。因此,通过我们的简单方法,我们缺少了一些东西(顺便说一句,只从implements NamingContainer中删除MyUIViewRoot -反应用程序再次正常工作)。

  • 是否有一些我们忽略的文档、方法或工作示例?
  • 如何正确激活“命名空间模式”?我们错过了什么让回发又起作用了?
  • 如何使MyUIViewRoot在ViewState中加上myNamespace

应用程序运行在payara-5应用服务器中。

我们的index.xhtml

代码语言:javascript
复制
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head/>
<h:body>
  <h:form id="counterForm">
    <h:panelGrid columns="2">
      <h:outputLabel value="Counter" />
      <h:outputText value="#{counterUiController.counter}" />
    </h:panelGrid>
    <h:commandButton value="inc" action="#{counterUiController.incAction}">
      <f:ajax execute="@form" render="@form" />
    </h:commandButton>
  </h:form>
  <h:form id="resetForm">
    <h:commandButton value="reset" action="#{counterUiController.resetAction}">
      <f:ajax execute="@form" render=":counterForm" />
    </h:commandButton>
  </h:form>
</h:body>
</html>

CounterUiController:

代码语言:javascript
复制
@Named
@ViewScoped
public class CounterUiController implements Serializable {

    private int counter;

    public int getCounter() {
        return counter;
    }

    public void incAction() {
        counter++;
    }

    public void resetAction() {
        counter=0;
    }
}

我们的UIViewRoot-Implementation:

代码语言:javascript
复制
public class MyUIViewRoot extends UIViewRoot implements NamingContainer, FacesWrapper<UIViewRoot> {

    private static final Logger LOG = Logger.getLogger(MyUIViewRoot.class.getName());

    private UIViewRoot wrapped;

    public MyUIViewRoot(UIViewRoot wrapped) {
        this.wrapped = wrapped;
        LOG.log(Level.INFO, "new instance created: {0}", this);
    }

    @Override
    public UIViewRoot getWrapped() {
        return wrapped;
    }

    @Override
    public String createUniqueId() {
        return wrapped==null ? null : wrapped.createUniqueId();
    }

    @Override
    public void setId(String id) {
        if( wrapped!=null ) {
            wrapped.setId(id);
        }
    }
    // all other methodes delegated to `wrapped` directly
}

我们的ViewHandler

代码语言:javascript
复制
public class MyViewHandler extends ViewHandlerWrapper {

    private static final Logger LOG = Logger.getLogger(MyViewHandler.class.getName());

    public MyViewHandler(ViewHandler wrapped) {
        super(wrapped);
    }

    @Override
    public UIViewRoot createView(FacesContext context, String viewId) {
        UIViewRoot retval = super.createView(context, viewId);
        retval = wrapIfNeeded(retval);
        LOG.log(Level.INFO, "view created: {0}", retval);
        return retval;
    }

    @Override
    public UIViewRoot restoreView(FacesContext context, String viewId) {
        UIViewRoot retval =  super.restoreView(context, viewId);
        retval = wrapIfNeeded(retval);
        LOG.log(Level.INFO, "view restored: {0}", retval);
        return retval;
    }

    private UIViewRoot wrapIfNeeded(UIViewRoot root) {
        if (root != null && !(root instanceof MyUIViewRoot)) {
            LOG.log(Level.INFO, "view wrapped: {0}, {1}", new Object[] { root, root.getId() });
            return new MyUIViewRoot(root);
        } else {
            return root;
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-15 09:35:45

您需要替换UIViewRoot,而不是包装它。

代码语言:javascript
复制
public class NamespacedView extends UIViewRoot implements NamingContainer {
    //
}

然后在faces-config.xml

代码语言:javascript
复制
<component>
    <component-type>javax.faces.ViewRoot</component-type>
    <component-class>com.example.NamespacedView</component-class>
</component>

基本上仅此而已。另见这上面的莫贾拉

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61815731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档