如何在构建时创建变量?

时间:2015-09-17 20:07:19

标签: jsf jsf-2 primefaces

我有这个页面:

<c:forEach begin="0" end="#{tareaController.tipoFuncion.filas}" step="1" var="x">
    <p:row>
        <c:forEach begin="0" end="#{tareaController.tipoFuncion.columnas}" step="1" var="y">
            <c:choose>
                <c:when test="#{tareaController.configuracionEnPosicion(x,y) ne null}">
                    <p:column style="width: 80px" 
                              colspan="#{tareaController.configuracionEnPosicion(x,y).colSpan}"
                              rowspan="#{tareaController.configuracionEnPosicion(x,y).rowSpan}">
                        <p:outputLabel value="#{tareaController.atributoEnPosicion(x,y).labelAtributo}:" 
                                       rendered="#{!tareaController.validar.isBoton(tareaController.atributoEnPosicion(x, y).tipoAtributosOpcionales)}">
                            <c:if test="#{tareaController.configuracionEnPosicion(x,y).esObligatorio}">
                                *
                            </c:if>
                        </p:outputLabel>
                    </p:column>
                    <p:column colspan="#{tareaController.configuracionEnPosicion(x,y).colSpan}"
                              rowspan="#{tareaController.configuracionEnPosicion(x,y).rowSpan}"> 
                        <c:choose>
                            <c:when test="#{tareaController.validar.isSeparador(tareaController.atributoEnPosicion(x, y).tipoAtributosOpcionales)}">
                                <p:separator/>
                            </c:when>
                            <c:when test="#{tareaController.validar.isNumerico(tareaController.atributoEnPosicion(x,y).tipoAtributosOpcionales)}">
                                <pe:inputNumber decimalSeparator="#{tareaController.configuracionEnPosicion(x,y).separadorDecimal}" 
                                                thousandSeparator="#{tareaController.configuracionEnPosicion(x,y).separadorMiles}" 
                                                decimalPlaces="#{tareaController.configuracionEnPosicion(x,y).cantidadDecimales}" 
                                                disabled="#{mFuncion.soloLectura || !tareaController.tareaAceptada || tareaController.tomadaPorOtroUsuario || tareaController.configuracionEnPosicion(x,y).soloLectura}"
                                                maxValue="#{tareaController.configuracionEnPosicion(x,y).valorMaximo}"
                                                rendered="#{!tareaController.configuracionEnPosicion(x,y).ocultarAtributo}"
                                                value="#{tareaController.atributoEnPosicion(x,y).valorAtributoNumerico}" 
                                                style="width: #{tareaController.configuracionEnPosicion(x,y).ancho}px; height: #{tareaController.configuracionEnPosicion(x,y).alto}px;">
                                    <p:ajax global="false" update=":f_tarea:tabView:tab_#{tareaController.indiceTramite}:nombreRepetido, :f_tarea:b_completarT" listener="#{tareaController.validarTarea()}"/>
                                </pe:inputNumber>
                            </c:when>
                            <c:when test="#{tareaController.validar.isBoton(tareaController.atributoEnPosicion(x, y).tipoAtributosOpcionales)}">
                                <p:commandButton value="#{tareaController.atributoEnPosicion(x,y).labelAtributo}" 
                                                 actionListener="#{tareaController.ejecutarWs(tareaController.configuracionEnPosicion(x,y))}"
                                                 update=":f_tarea:tabView:tab_#{tareaController.indiceTramite}:pg_funcion_#{tareaController.indiceTramite}"/>
                            </c:when>
                            <c:when test="#{tareaController.validar.isFecha(tareaController.atributoEnPosicion(x,y).tipoAtributosOpcionales)}">
                                <p:calendar value="#{tareaController.atributoEnPosicion(x,y).valorAtributoFecha}" 
                                            maxdate="#{tareaController.configuracionEnPosicion(x,y).fechaMaxima}" 
                                            mindate="#{tareaController.configuracionEnPosicion(x,y).fechaMinima}"
                                            rendered="#{!tareaController.configuracionEnPosicion(x,y).ocultarAtributo}"
                                            disabled="#{mFuncion.soloLectura || !tareaController.tareaAceptada || tareaController.tomadaPorOtroUsuario || tareaController.configuracionEnPosicion(x,y).soloLectura || tareaController.atributoEnPosicion(x,y).bloquear}"
                                            size="20"
                                            pattern="#{tareaController.configuracionEnPosicion(x,y).formatoFecha}">
                                    <p:ajax global="false" update=":f_tarea:tabView:tab_#{tareaController.indiceTramite}:nombreRepetido, :f_tarea:b_completarT" listener="#{tareaController.validarTarea()}"/>
                                    <p:ajax event="dateSelect" global="false" update=":f_tarea:tabView:tab_#{tareaController.indiceTramite}:nombreRepetido, :f_tarea:b_completarT" listener="#{tareaController.validarTarea()}"/>
                                </p:calendar>
                            </c:when>
                            <c:otherwise test="#{tareaController.validar.isAlfanumerico(tareaController.atributoEnPosicion(x,y).tipoAtributosOpcionales)}">
                                <p:inputTextarea value="#{tareaController.atributoEnPosicion(x,y).valorAtributoAlfanumerico}" 
                                                 disabled="#{mFuncion.soloLectura || !tareaController.tareaAceptada || tareaController.tomadaPorOtroUsuario || tareaController.configuracionEnPosicion(x,y).soloLectura}"
                                                 rendered="#{!tareaController.configuracionEnPosicion(x,y).ocultarAtributo}"
                                                 style="width: #{tareaController.configuracionEnPosicion(x,y).ancho}px; 
                                                 height:  #{tareaController.configuracionEnPosicion(x,y).alto}px; 
                                                 word-break: normal;">
                                    <p:ajax global="false" update=":f_tarea:tabView:tab_#{tareaController.indiceTramite}:nombreRepetido, :f_tarea:b_completarT" listener="#{tareaController.validarTarea()}"/>
                                    <p:ajax event="select" global="false" update=":f_tarea:tabView:tab_#{tareaController.indiceTramite}:nombreRepetido, :f_tarea:b_completarT" listener="#{tareaController.validarTarea()}"/>
                                </p:inputTextarea>
                            </c:otherwise>
                        </c:choose>
                    </p:column>
                </c:when>
                <c:otherwise>
                    <p:column>
                        <h:panelGroup/>
                    </p:column>
                    <p:column>
                        <h:panelGroup/>
                    </p:column>
                </c:otherwise>
            </c:choose>
        </c:forEach>

我的想法是,我可以配置该页面并将组件放置在我想要的位置,具有许多不同的配置。它工作得很好,人们对此很满意,但我不是。如果你检查页面,我会在循环的每次运行中调用方法configuracionEnPosicion(x,y)和atributoEnPosicion(x,y)300次。并且这些方法像其他3种方法一样调用,并在x,y中查找实际配置。令人惊讶的是它不会缓慢但我觉得这是我可以避免的大量开销。

在我尝试使用各自的getter和setter将configuracionEnPosicion(x,y)和atributoEnPosicion(x,y)的结果保存在客户端的变量中之前,但由于JSTL Core标记在构建时运行,渲染时间变量未更新,导致该变量保持其最后一个值并给出不希望的行为。我的“解决方案”是实际的,但我的最后一个问题是:有没有办法存储该变量的值,所以我只能在构建时或类似的东西中保持它?我想在每个x和y位置调用这些方法只是ONCE,但是我对JSF和Primefaces的了解并不足以实现这一点。

有条件的信息:

  • Apache Tomcat 7.0.41。
  • JSF 2.2
  • Primefaces 4.0
  • Mojarra 2.7.2
  • JS​​TL-1.2

3 个答案:

答案 0 :(得分:3)

它似乎是JSR 107: JCACHE - Java Temporary Caching API的任务。但是你应该使用CDI bean而不是JSF托管bean。这允许您编写如下代码:

 @CacheResult(cacheName = "configuracionEnPosicion")
 public String configuracionEnPosicion(int x, int y){
    .....
 }

还需要创建META-INF / beans.xml:

 <beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
    <interceptors>
         <class>org.jsr107.ri.annotations.cdi.CacheResultInterceptor</class>
         <class>org.jsr107.ri.annotations.cdi.CachePutInterceptor</class>
         <class>org.jsr107.ri.annotations.cdi.CacheRemoveEntryInterceptor</class>
         <class>org.jsr107.ri.annotations.cdi.CacheRemoveAllInterceptor</class>
    </interceptors>
</beans>

还需要在某处创建缓存:

@PostConstruct
public void init() {
    try {
        // Retrieve the system wide cache manager
        CacheManager cacheManager = Caching.getCachingProvider().getCacheManager();
        // Define a named cache with default JCache configuration
        MutableConfiguration<String, String> configuration = new MutableConfiguration<>();
        //specify expiry policy
        configuration.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE));
        cache = cacheManager.createCache("configuracionEnPosicion", configuration);
    } catch (Exception e) {
        L.error("Can't init cache!", e);
    }
}

当然,您应该选择jcache provider(ecache,infinispan,...)并为项目添加必要的依赖项。

答案 1 :(得分:1)

我在@BalusC评论之后编辑了我的答案

您可以预先计算支持bean PostConstruct方法中的所有值。

  • 在支持bean级别声明一个二维数组:

    private ReturnedObjectClass[][] precalculatedArray;
    
  • 添加getter方法。

  • 在PostConstruct方法中初始化它:

    precalculatedArray = new ReturnedObjectClass[x][y];
    
  • 使用PostConstruct方法中函数返回的对象填充它:

    precalculatedArray[i][j] = myBigFunction(i,j);
    

然后,您可以使用以下方式从您的页面访问计算值:

    value="#{tareaController.precalculatedArray[x][y].propertyOfReturnedObjectClass}"

答案 2 :(得分:-1)

您可以使用c:set

<c:set var="salary" scope="request" value="#{calculatePosition(x,y)}"/>

或者你可以使用varstatus取决于你的fct中发生的事情。 (这是jsf标签的文档,而不是jstl标签,但它是一样的。)