如何在构建时创建变量?
How to create a variable in build time?
我有这个页面:
<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 个方法一样调用并执行 foreach 以在 x、y 中找到实际配置。令人惊讶的是,它的运行速度并不慢,但我觉得这是我可以避免的大量开销。
在我尝试将 configuracionEnPosicion(x,y) 和 atributoEnPosicion(x,y) 的结果及其各自的 getter 和 setter 保存在客户端的变量中之前,但是自从JSTL Core 标记 运行s 在构建时,在渲染时该变量未更新,导致该变量保持其最后一个值并给出不希望的行为。我的 "solution" 是实际的,但我的最后一个问题是:有没有一种方法可以存储该变量的值,以便我只能在构建时间或类似的时间保持它的活动?我想在每个 x 和 y 位置只调用一次这些方法,但我对 JSF 和 Primefaces 的了解不足以实现这一点。
附加信息:
- 阿帕奇 Tomcat 7.0.41.
- JSF 2.2
- Primefaces 4.0
- Mojarra 2.7.2
- jstl-1.2
你可以使用 c:set.
<c:set var="salary" scope="request" value="#{calculatePosition(x,y)}"/>
或者您可以使用 varstatus,具体取决于您的 fct 中发生的情况。 (这是 jsf 标签的文档,不是 jstl 标签,但它们是同一回事)。
我在@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}"
看起来像是 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);
}
}
当然,您应该 select jcache 提供程序(ecache、infinispan 等)并向项目添加必要的依赖项。
我有这个页面:
<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 个方法一样调用并执行 foreach 以在 x、y 中找到实际配置。令人惊讶的是,它的运行速度并不慢,但我觉得这是我可以避免的大量开销。
在我尝试将 configuracionEnPosicion(x,y) 和 atributoEnPosicion(x,y) 的结果及其各自的 getter 和 setter 保存在客户端的变量中之前,但是自从JSTL Core 标记 运行s 在构建时,在渲染时该变量未更新,导致该变量保持其最后一个值并给出不希望的行为。我的 "solution" 是实际的,但我的最后一个问题是:有没有一种方法可以存储该变量的值,以便我只能在构建时间或类似的时间保持它的活动?我想在每个 x 和 y 位置只调用一次这些方法,但我对 JSF 和 Primefaces 的了解不足以实现这一点。
附加信息:
- 阿帕奇 Tomcat 7.0.41.
- JSF 2.2
- Primefaces 4.0
- Mojarra 2.7.2
- jstl-1.2
你可以使用 c:set.
<c:set var="salary" scope="request" value="#{calculatePosition(x,y)}"/>
或者您可以使用 varstatus,具体取决于您的 fct 中发生的情况。 (这是 jsf 标签的文档,不是 jstl 标签,但它们是同一回事)。
我在@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}"
看起来像是 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);
}
}
当然,您应该 select jcache 提供程序(ecache、infinispan 等)并向项目添加必要的依赖项。