发布后处理 JSF 中的视图参数 [英] Handling view parameters in JSF after post

查看:11
本文介绍了发布后处理 JSF 中的视图参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个页面需要一个 userId 才能工作,因此代码如下:

I have a few pages that needs a userId to work, thus the following code:

userpage.xhtml

userpage.xhtml

<!-- xmlns etc. omitted -->
<html>
<f:metadata>
    <f:viewParam name="userId" value="#{userPageController.userId}"/>
</f:metadata>
<f:view contentType="text/html">
<h:head>
</h:head>
<h:body>
    <h:form>
        <h:commandButton action="#{userPageController.doAction}" value="post"/>
    </h:form>
</h:body>
</f:view>

userPageController.java

userPageController.java

@Named
@ViewScoped
public class userPageControllerimplements Serializable {
    private static final long serialVersionUID = 1L;

    @Inject protected SessionController sessionController;
    @Inject private SecurityContext securityContext;
    @Inject protected UserDAO userDAO;

    protected User user;
    protected Long userId;

    public UserPage() {
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        if(!FacesContext.getCurrentInstance().isPostback()){
            User u = userDAO.find(userId);
            this.userId = userId;
            this.user = u;
        }
    }

    public void doAction(){

    }

}

但是调用doAction后,url中的view参数就消失了.由于其视图范围的性质,该 bean 仍然有效,但它破坏了我未来导航的尝试.当我四处搜索时,我的印象是视图参数应该在发布后保留,因此阅读 userpage.jsf?userId=123,但事实并非如此.真正的预期行为是什么?

However, after doAction is called, the view parameter in the url disappears. The bean still works due to its viewscoped nature, but it ruins my attempts of future navigation. When i search around, I get the impression that the view parameter should remain after a post thus reading userpage.jsf?userId=123, but this is not the case. What is really the intended behaviour?

与此相关,我尝试在导航到另一个要保留 userId 的页面时实现视图参数的自动添加.它似乎对其他人有效,但对我而言,ViewRoot 中的 userId 始终为空.下面的代码用于检索视图参数(我知道我可以使用我在 bean 中临时存储的 userId 进行导航,但这个解决方案会更漂亮):

Related to this, I've tried to implement automatic adding of view parameters when navigating to another page where I want to keep the userId. It seems to work for others, but for me, the userId in the ViewRoot is always null. Code below used to retrieve the viewparameter (i know i could use my temporarily stored userId in the bean for navigation, but this solution would be much fancier):

    String name = "userId";
    FacesContext ctx = FacesContext.getCurrentInstance();
    ViewDeclarationLanguage vdl = ctx.getApplication().getViewHandler().getViewDeclarationLanguage(ctx, viewId);
    ViewMetadata viewMetadata = vdl.getViewMetadata(ctx, viewId);
    UIViewRoot viewRoot = viewMetadata.createMetadataView(ctx);
    UIComponent metadataFacet = viewRoot.getFacet(UIViewRoot.METADATA_FACET_NAME);

    // Looking for a view parameter with the specified name
    UIViewParameter viewParam = null;
    for (UIComponent child : metadataFacet.getChildren()) {
        if (child instanceof UIViewParameter) {
            UIViewParameter tempViewParam = (UIViewParameter) child;
            if (name.equals(tempViewParam.getName())) {
                viewParam = tempViewParam;
                break;
            }
        }
    }

    if (viewParam == null) {
        throw new FacesException("Unknown parameter: '" + name + "' for view: " + viewId);
    }

    // Getting the value
    String value = viewParam.getStringValue(ctx);  // This seems to ALWAYS be null.

最后一个想法是 setter 方法似乎仍然有效,setUserId 在 post 时使用正确的值调用.

One last thought is that the setter methods still seem to work, setUserId is called with the correct value on post.

我是否完全误解了视图参数的工作原理,或者这里是否存在某种错误?我认为我的用例应该非常常见,并且在框架中得到基本支持.

Have I completly missunderstood how view parameters work, or is there some kind of bug here? I think my use case should be extremly common and have basic support in the framework.

推荐答案

当我四处搜索时,我的印象是视图参数应该在发布后保留,因此读取 userpage.jsf?userId=123,但事实并非如此.真正的预期行为是什么?

这种行为是正确的. 生成一个 HTML

元素,其中包含一个操作 URL 没有任何视图参数.POST 请求只是提交到该 URL.如果你打算在URL中保留视图参数,那么基本上有3种方式:

This behaviour is correct. The <h:form> generates a HTML <form> element with an action URL without any view parameters. The POST request just submits to exactly that URL. If you intend to keep the view parameters in the URL, then there are basically 3 ways:

  1. 引入一些 ajax 魔法.

  1. Bring in some ajax magic.

<h:commandButton action="#{userPageController.doAction}" value="post">
    <f:ajax execute="@form" render="@form" />
</h:commandButton>

这样一来,最初请求的页面以及浏览器地址栏中的请求 URL 始终保持不变.

This way the initially requested page and thus also the request URL in browser's address bar remains the same all the time.

如果适用(例如用于页面到页面导航),请将其设为 GET 请求并使用 includeViewParams=true.你可以使用 :

If applicable (e.g. for page-to-page navigation), make it a GET request and use includeViewParams=true. You can use <h:link> and <h:button> for this:

<h:button outcome="nextview?includeViewParams=true" value="post" />

然而,这在早于 2.1.6 的 Mojarra 版本中存在 EL 安全漏洞.确保您使用的是 Mojarra 2.1.6 或更新版本.另请参阅 issue 2247.

However, this has an EL security exploit in Mojarra versions older than 2.1.6. Make sure that you're using Mojarra 2.1.6 or newer. See also issue 2247.

自己控制的action URL的生成.提供自定义ViewHandler(只需扩展 ViewHandlerWrapper) 其中您在 getActionURL().

Control the generation of action URL of <h:form> yourself. Provide a custom ViewHandler (just extend ViewHandlerWrapper) wherein you do the job in getActionURL().

public String getActionURL(FacesContext context, String viewId) {
    String originalActionURL = super.getActionURL(context, viewId);
    String newActionURL = includeViewParamsIfNecessary(context, originalActionURL);
    return newActionURL;
}

要让它运行,请在 faces-config.xml 中注册它,如下所示:

To get it to run, register it in faces-config.xml as follows:

<application>
    <view-handler>com.example.YourCustomViewHandler</view-handler>
</application>

这也是 OmniFaces 正在做.它支持额外的 includeViewParams 属性,该属性包括表单操作 URL 中的所有视图参数:

This is also what OmniFaces <o:form> is doing. It supports an additional includeViewParams attribute which includes all view parameters in the form's action URL:

<o:form includeViewParams="true">

<小时>

更新:以编程方式获取当前视图的视图参数(这基本上是你的第二个问题)应该如下完成:


Update: obtaining the view parameters of the current view programmatically (which is basically your 2nd question) should be done as follows:

Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(FacesContext.getCurrentInstance().getViewRoot());

for (UIViewParameter viewParam : viewParams) {
    String name = viewParam.getName();
    Object value = viewParam.getValue();
    // ...
}

这篇关于发布后处理 JSF 中的视图参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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