方法链如何在表达式语言的#{flash.keep.message}中工作?

时间:2016-06-25 06:36:23

标签: jsf jsf-2 el flash-scope

我有这个示例代码:

<h:form>
    <h:commandButton action="#{fooBar.foo()}" value="Submit"/>
</h:form>

并在bean中:

@ManagedBean
@ApplicationScoped
public class FooBar {
    public String foo() {
        final Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
        flash.put("message", "Hello World");
        return "hello?faces-redirect=true";
    }
}

最后在hello.xhtml

<h:body>
    #{flash.keep.message}
</h:body>

所以我转到index.xhtml,点击提交,我按预期重定向到hello.xhtml。当我刷新页面时,我仍然看到消息,因为flash.keep行为非常好。

现在我想了解发生了什么,所以我打开了documentation

此类中有一个keep()方法,但其返回类型为void,并且它需要一个String参数。那么#{flash.keep.message}是否使用message参数调用keep()方法?我真的不这么认为,据我所知它应该是#{flash.keep(message)},不是吗?

那么这里发生了什么?

1 个答案:

答案 0 :(得分:1)

可以使用ELResolver实现自定义EL解析。有两个EL解析器参与评估#{flash.keep.message}。第一个,JSF内置FlashELResolver#{flash}上执行。正如您在其源代码中所看到的(行号与Mojarra 2.2.12匹配),

216        // and the property argument is "keep"...
217        if (property.toString().equals(FLASH_KEEP_VARIABLE_NAME))
218        {
219            elContext.setPropertyResolved(true);
220          
221            // then this is a request to promote the value
222            // "property", which is assumed to have been previously
223            // stored in request scope via the "flash.now"
224            // expression, to flash scope.
225            result = base;
226            // Set a flag so the flash itself can look in the request
227            // and promote the value to the next request
228            FlashFactory ff = (FlashFactory) 
229                    FactoryFinder.getFactory(FactoryFinder.FLASH_FACTORY);
230            ff.getFlash(true);
231            ELFlash.setKeepFlag(facesContext);
232        }

FlashELResolver将在评估ELFlash.setKeepFlag(facesContext)表达式时调用#{flash.keep}(第231行)。它还将属性设置为已解析(第219行),以便EL上下文可以使用下一个属性前进,并将base#{flash})设置为评估结果(第225行),因此有效#{flash.keep}返回完全相同的#{flash}对象。

然后,当message属性要对#{flash.keep}的结果进行评估时,#{flash}基本上仍为#{flash},但使用&#34;保持&#34;标志集,EL-builtin MapELResolver被执行。这是因为Map基本上是Map#get(),另见javadoc(强调我的)。

  

公共抽象类Flash
  扩展对象
  实现Map&lt; String,Object&gt;

这会调用Flash方法,384 public Object get(Object key) { 385 Object result = null; 386 387 FacesContext context = FacesContext.getCurrentInstance(); 388 if (null != key) { 389 if (key.equals("keepMessages")) { 390 result = this.isKeepMessages(); 391 } else if (key.equals("redirect")) { 392 result = this.isRedirect(); 393 } else { 394 if (isKeepFlagSet(context)) { 395 result = getPhaseMapForReading().get(key); 396 keep(key.toString()); 397 clearKeepFlag(context); 398 return result; 399 } 400 401 } 402 403 } customized如下(行号与Mojarra 2.2.12匹配):

keep(key)

正如您在第396行所见,它会在设置标志时调用FlashELResolver,如from sklearn.feature_extraction.text import CountVectorizer train_vectorizer = CountVectorizer() train = [ 'this is the first', 'set of documents' ] train_matrix = train_vectorizer.fit_transform(train) train_vocab = train_vectorizer.vocabulary_ test = [ 'this is the second', 'set of documents' ] test_vectorizer = CountVectorizer(vocabulary=train_vocab) test_matrix = test_vectorizer.fit_transform(test) print(train_vocab) print(train_matrix.toarray()) print('\n') print(test_vectorizer.vocabulary_) print(test_matrix.toarray()) 所示。