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

查看:81
本文介绍了发布后在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始终为null.下面的代码用于检索viewparameter(我知道我可以使用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.

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,但事实并非如此.真正的预期行为是什么?

此行为是正确的. <h:form>生成一个HTML <form>元素,该元素具有操作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.您可以为此使用<h:link><h:button>

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或更高版本.另请参见问题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.

您可以自己控制<h:form>的操作URL的生成.提供自定义 ViewHandler (只是扩展 ViewHandlerWrapper )在

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 <o:form> 正在执行.它支持附加的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天全站免登陆