2012-09-10 95 views
1

我正在开发一个使用JSF2和Primefaces作为WebFrameworks的Java Web应用程序。我的应用程序旨在管理相机。所有关于相机的数据都存储在PostgreSQL数据库中。
我有一个JSF视图,其中使用Leaflet的JavaScript API显示动态地图。 您可以通过以下链接查看此类地图的示例:Leaflet example。总结一下,我的地图旨在显示摄像机的标记。标记的位置是使用相机的属性生成的。
我已经创建了一个复合组件和它的Backing Bean来处理地图。下面是这个视图的源代码:
JSF 2.0:复合组件属性从Backing Bean初始化问题

<h:body> 
    <!-- INTERFACE --> 
    <composite:interface componentType="mapComponent"> 
    </composite:interface> 

    <!-- IMPLEMENTATION --> 
    <composite:implementation> 
     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 
     <link rel="stylesheet" href="#{resource['css:leaflet.css']}" /> 
     <!--[if lte IE 8]><link rel="stylesheet" href="#{resource['css:leaflet.ie.css']}" /><![endif]--> 
     <script 
      src="#{resource['js:leaflet/Leaflet-v0.4.4-0/dist/leaflet-src.js']}"></script> 
     <script 
      src="#{resource['js:leaflet/Leaflet-v0.4.4-0/src/leafclusterer.js']}"></script> 

     <div id="#{cc.mapId}" style="width: 520px; height: 580px" /> 

     <script type="text/javascript"> 
     //<![CDATA[ 
      var clusterPopup; 

      function onClustererClick(cluster, coordinates) { 
       var markers = cluster.getMarkers; 
       var popupContent = "<p>"; 
       for (var i = 0; i < cluster.getCluster().getMarkers().length; i++) { 
        var currentMarker = cluster.getCluster().getMarkers()[i]; 
        popupContent += currentMarker.marker._popup._content 
        popupContent += "<br/>"; 
       } 
       popupContent += "</p>"; 
       clusterPopup = new L.Popup(); 
       clusterPopup.setLatLng(coordinates); 
       clusterPopup.setContent(popupContent); 
       map.openPopup(clusterPopup); 
      }; 

      var cameraIcon = L.icon({ 
       iconUrl : "#{resource['img:leaflet/camera.png']}", 

       iconSize : [ 48, 48 ], 
       shadowSize : [ 48, 48 ], 
       iconAnchor : [ 30, 30 ], 
       popupAnchor : [ 0, -20 ] 
      }); 

      var marker; 
      function onMapClick(e) { 
       marker = new L.marker(e.latlng, { 
        draggable : true, 
        icon : cameraIcon 
       }); 
       map.addLayer(marker); 
       marker.bindPopup("<b>Hello world!</b><br />I am a popup."); 
       map.off('click'); 
      }; 

      var osmUrl = '#{cc.osmUrl}'; 
      var osmAttrib = '#{cc.osmAttrib}'; 

      var basic = new L.tileLayer(osmUrl, { 
       minZoom : #{cc.minZoom}, 
       maxZoom : #{cc.maxZoom}, 
       attribution : osmAttrib 
      }); 

      var map = new L.Map('#{cc.mapId}', { 
       center : new L.LatLng(#{cc.mapX}, #{cc.mapY}), 
       zoom : #{cc.mapDefaultZoom}, 
       layers : [ basic ] 
      }); 

      var baseMaps = { 
       "#{cc.mapBasicLayerName}" : basic 
      }; 

      if(#{cc.mapEnableOnClick}) { 
       map.on('click', onMapClick); 
      } 

      var clusterer = new LeafClusterer(map); 
     //]]> 
     </script> 
     <composite:insertChildren /> 
    </composite:implementation> 
</h:body> 
</html> 

这里是我支持bean的代码:

@FacesComponent(value = "mapComponent") 
public class MapComponent extends UINamingContainer { 

private static final String MAP_ID_PROP = "map_id"; 
private static final String OSM_URL_PROP = "osm_url"; 
private static final String OSM_ATTRIB_PROP = "osm_attrib"; 
private static final String MIN_ZOOM_PROP = "min_zoom"; 
private static final String MAX_ZOOM_PROP = "max_zoom"; 
private static final String MAP_X_PROP = "map_x"; 
private static final String MAP_Y_PROP = "map_y"; 
private static final String MAP_DEFAULT_ZOOM_PROP = "map_default_zoom"; 
private static final String MAP_BASIC_LAYER_NAME_PROP = "map_basic_layer_name"; 
private static final String MAP_ENABLE_ON_CLICK_PROP = "map_enable_on_click"; 

private String mapId; 
private String osmUrl; 
private String osmAttrib; 
private Integer minZoom; 
private Integer maxZoom; 
private Double mapX; 
private Double mapY; 
private Integer mapDefaultZoom; 
private String mapBasicLayerName; 
private Boolean mapEnableOnClick; 

/** 
* Instanties un nouveau map component. 
*/ 
public MapComponent() { 
    super(); 
    mapId = (String) AppUtil.getProperty(MAP_ID_PROP); 
    osmUrl = (String) AppUtil.getProperty(OSM_URL_PROP); 
    osmAttrib = (String) AppUtil.getProperty(OSM_ATTRIB_PROP); 
    minZoom = Integer.parseInt((String) AppUtil.getProperty(MIN_ZOOM_PROP)); 
    maxZoom = Integer.parseInt((String) AppUtil.getProperty(MAX_ZOOM_PROP)); 
    mapX = Double.parseDouble((String) AppUtil.getProperty(MAP_X_PROP)); 
    mapY = Double.parseDouble((String) AppUtil.getProperty(MAP_Y_PROP)); 
    mapDefaultZoom = Integer.parseInt((String) AppUtil.getProperty(MAP_DEFAULT_ZOOM_PROP)); 
    mapBasicLayerName = (String) AppUtil.getProperty(MAP_BASIC_LAYER_NAME_PROP); 
    setMapEnableOnClick(Boolean.parseBoolean((String) AppUtil.getProperty(MAP_ENABLE_ON_CLICK_PROP))); 
} 

/** 
* Getter : retourne le map id. 
* 
* @return le map id 
*/ 
public String getMapId() { 
    return mapId; 
} 

/** 
* Getter : retourne le osm url. 
* 
* @return le osm url 
*/ 
public String getOsmUrl() { 
    return osmUrl; 
} 

/** 
* Getter : retourne le osm attrib. 
* 
* @return le osm attrib 
*/ 
public String getOsmAttrib() { 
    return osmAttrib; 
} 

/** 
* Getter : retourne le min zoom. 
* 
* @return le min zoom 
*/ 
public Integer getMinZoom() { 
    return minZoom; 
} 

/** 
* Getter : retourne le max zoom. 
* 
* @return le max zoom 
*/ 
public Integer getMaxZoom() { 
    return maxZoom; 
} 

/** 
* Getter : retourne le map x. 
* 
* @return le map x 
*/ 
public Double getMapX() { 
    return mapX; 
} 

/** 
* Getter : retourne le map y. 
* 
* @return le map y 
*/ 
public Double getMapY() { 
    return mapY; 
} 

/** 
* Getter : retourne le map default zoom. 
* 
* @return le map default zoom 
*/ 
public Integer getMapDefaultZoom() { 
    return mapDefaultZoom; 
} 

/** 
* Getter : retourne le map basic layer name. 
* 
* @return le map basic layer name 
*/ 
public String getMapBasicLayerName() { 
    return mapBasicLayerName; 
} 

/** 
* Setter : affecte le map id. 
* 
* @param mapId le map id 
*/ 
public void setMapId(String mapId) { 
    this.mapId = mapId; 
} 

/** 
* Setter : affecte le osm url. 
* 
* @param osmUrl le osm url 
*/ 
public void setOsmUrl(String osmUrl) { 
    this.osmUrl = osmUrl; 
} 

/** 
* Setter : affecte le osm attrib. 
* 
* @param osmAttrib le osm attrib 
*/ 
public void setOsmAttrib(String osmAttrib) { 
    this.osmAttrib = osmAttrib; 
} 

/** 
* Setter : affecte le min zoom. 
* 
* @param minZoom le min zoom 
*/ 
public void setMinZoom(Integer minZoom) { 
    this.minZoom = minZoom; 
} 

/** 
* Setter : affecte le max zoom. 
* 
* @param maxZoom le max zoom 
*/ 
public void setMaxZoom(Integer maxZoom) { 
    this.maxZoom = maxZoom; 
} 

/** 
* Setter : affecte le map x. 
* 
* @param mapX le map x 
*/ 
public void setMapX(Double mapX) { 
    this.mapX = mapX; 
} 

/** 
* Setter : affecte le map y. 
* 
* @param mapY le map y 
*/ 
public void setMapY(Double mapY) { 
    this.mapY = mapY; 
} 

/** 
* Setter : affecte le map default zoom. 
* 
* @param mapDefaultZoom le map default zoom 
*/ 
public void setMapDefaultZoom(Integer mapDefaultZoom) { 
    this.mapDefaultZoom = mapDefaultZoom; 
} 

/** 
* Setter : affecte le map basic layer name. 
* 
* @param mapBasicLayerName le map basic layer name 
*/ 
public void setMapBasicLayerName(String mapBasicLayerName) { 
    this.mapBasicLayerName = mapBasicLayerName; 
} 

/** 
* Getter : retourne le map enable on click. 
* 
* @return le map enable on click 
*/ 
public Boolean getMapEnableOnClick() { 
    return mapEnableOnClick; 
} 

/** 
* Setter : affecte le map enable on click. 
* 
* @param mapEnableOnClick le map enable on click 
*/ 
public void setMapEnableOnClick(Boolean mapEnableOnClick) { 
    this.mapEnableOnClick = mapEnableOnClick; 
} 

}

来管理我的成分,我也创建了一个支持bean 。这里是XHTML来源:

<h:body> 
    <!-- INTERFACE --> 
    <composite:interface componentType="mapMarker"> 
     <composite:attribute name="longitude" type="java.lang.Float" /> 
     <composite:attribute name="latitude" type="java.lang.Float" /> 
     <composite:attribute name="padding" type="java.lang.Integer" /> 
     <composite:attribute name="popUpContent" type="java.lang.String" /> 
     <composite:attribute name="maxZoom" type="java.lang.Integer" /> 
    </composite:interface> 

    <!-- IMPLEMENTATION --> 
    <composite:implementation> 

     <script type="text/javascript"> 
      //   
      function onPopupClick(padding, lat, lng) { 
       map.closePopup(clusterPopup); 

       if(map.getZoom() &lt; #{cc.maxZoom}) { 
        var pos = map.latLngToLayerPoint(new L.LatLng(#{cc.latitude}, #{cc.longitude})); 
        var sw = new L.point(pos.x - padding, pos.y + padding); 
        sw = map.layerPointToLatLng(sw); 
        var ne = new L.point(pos.x + padding, pos.y - padding); 
        ne = map.layerPointToLatLng(ne); 
        map.setView(new L.LatLng(lat, lng), #{cc.maxZoom}); 
       } 
      }; 

      marker = new L.marker([#{cc.latitude}, #{cc.longitude}], { 
        draggable : true, 
        icon : cameraIcon 
      }); 
      var popUpContent = '<span style="cursor:pointer;" id="#{cc.id}Link" onclick="onPopupClick(#{cc.padding},' + #{cc.latitude} + ',' + #{cc.longitude} + ')">#{cc.popUpContent}</span>'; 
      marker.bindPopup(popUpContent); 

      clusterer.addMarker(marker); 
     </script> 

    </composite:implementation> 
</h:body> 

这里是我支持bean的源代码:按文件包含默认值读取性能

@FacesComponent(value = "mapMarker") 
public class MapMarker extends UINamingContainer { 

    private static final String PADDING_PROP = "padding"; 
    private static final String MAX_ZOOM_MARKER_PROP = "max_zoom_marker"; 

    private Float longitude; 
    private Float latitude; 
    private String popUpContent; 
    private Integer padding; 
    private Integer maxZoom; 

    public MapMarker() { 
     padding = Integer.parseInt((String) AppUtil.getProperty(PADDING_PROP)); 
     maxZoom = Integer.parseInt((String) AppUtil.getProperty(MAX_ZOOM_MARKER_PROP)); 
    } 

    public Float getLongitude() { 
     return longitude; 
    } 

    public void setLongitude(Float longitude) { 
     this.longitude = longitude; 
    } 

    public Float getLatitude() { 
     return latitude; 
    } 

    public void setLatitude(Float latitude) { 
     this.latitude = latitude; 
    } 

    public String getPopUpContent() { 
     return popUpContent; 
    } 

    public void setPopUpContent(String popUpContent) { 
     this.popUpContent = popUpContent; 
    } 

    public Integer getPadding() { 
     return padding; 
    } 

    public void setPadding(Integer padding) { 
     this.padding = padding; 
    } 

    public Integer getMaxZoom() { 
     return maxZoom; 
    } 

    public void setMaxZoom(Integer maxZoom) { 
     this.maxZoom = maxZoom; 
    } 

} 

组件设置其属性。 下面是该文件的内容:

# Cartographie OpenStreetMap 
map_id=map 
osm_attrib=test 
min_zoom=1 
max_zoom=13 
map_x=48.227 
map_y=6.611 
map_default_zoom=8 
map_basic_layer_name=Basique 
map_enable_on_click=true 
# Cartographie OpenStreetMap 

# Marqueur de caméra 
padding=20 
max_zoom_marker=11 
# Marqueur de caméra 

我有一颗豆“ConsultationBean”是处理包含地图的视图。这个bean使用一个服务来存储一个ArrayList,包含在数据库中的所有相机。在视图中,我通过prerenderView evet调用init方法,该方法使用摄像机列表创建所有MapMarker。这里是XHTML代码:

<ui:composition template="/xhtml/common/layout.xhtml"> 
    <ui:define name="headTitle"> 
     <h:outputText value="#Cartographie#" /> 
    </ui:define> 

    <ui:define name="header"> 
     <ui:include src="/xhtml/common/header.xhtml"> 
      <ui:param name="headerClass" value="banner-thin" /> 
     </ui:include> 
    </ui:define> 

    <ui:define name="content"> 
     <f:metadata> 
      <f:event type="preRenderView" listener="#{consultationBean.init}" 
       update="content,mapPanelGroup"></f:event> 
     </f:metadata> 
     <div id="content" class="content-home ui-corner-bottom"> 

      <h2 class="main-title content-title light-bg light-bordered-top"> 
       <h:outputText value="#Cartographie#" /> 
      </h2> 
      <h:panelGroup id="mapPanelGroup"> 
       <util:map id="mapContainer"> 
        <ui:repeat var="marker" value="#{consultationBean.markers}"> 
         <util:mapMarker/> 
        </ui:repeat> 
       </util:map> 
      </h:panelGroup> 
     </div> 
    </ui:define> 
</ui:composition> 
</html> 

这里是支持bean的源代码:

/** 
* Le Class ConsultationBean. 
*/ 
@Controller 
@Scope("view") 
@SuppressWarnings("serial") 
public class ConsultationBean implements Serializable { 

/** La constante LOGGER. */ 
private static final Logger LOGGER = Logger.getLogger(ConsultationBean.class); 

/** Le cameras. */ 
private List<Camera> cameras; 

/** Le map. */ 
private UINamingContainer map; 

/** Le markers. */ 
private List<MapMarker> markers; 

/** Le camera service. */ 
@Autowired 
private CameraService cameraService; 

/** 
* Initialise le. 
*/ 
public void init() { 
    cameras = cameraService.findAll(); 
    map = (UINamingContainer) FacesUtils.findComponentById(FacesContext.getCurrentInstance(), "mapContainer"); 
    initMarkers(); 
} 

/** 
* Initialise le markers. 
*/ 
public void initMarkers() { 
    markers = new ArrayList<MapMarker>(); 

    for (Camera camera : cameras) { 
     MapMarker mapMarker = new MapMarker(); 
     mapMarker.setLatitude(camera.getY()); 
     mapMarker.setLongitude(camera.getX()); 
     mapMarker.setPopUpContent(camera.toString()); 
     markers.add(mapMarker); 
     map.getChildren().add(mapMarker); 
     map.getChildren().add(new HtmlInputText()); 
    } 
} 

/** 
* Getter : retourne le markers. 
* 
* @return le markers 
*/ 
public List<MapMarker> getMarkers() { 
    return markers; 
} 

/** 
* Setter : affecte le markers. 
* 
* @param markers le markers 
*/ 
public void setMarkers(List<MapMarker> markers) { 
    this.markers = markers; 
} 

}

我的问题是,我需要为我设置属性到MapMarker的默认构造函数。例如,通过使用follogwing默认的构造函数,我的标记会在完全相同的点在地图上显示:

public MapMarker() { 
     padding = Integer.parseInt((String) AppUtil.getProperty(PADDING_PROP)); 
     maxZoom = Integer.parseInt((String) AppUtil.getProperty(MAX_ZOOM_MARKER_PROP)); 
     latitude = (float) 47.67876; 
     longitude = (float) 6.97061; 
    } 

我想要做的就是让我的“初始化”方法从“ConsultationBean”高效的感觉它像默认构造函数一样初始化标记的属性。我必须使用“init”方法,因为它是我使用我的相机列表的地方。
也许我应该重新渲染视图,这就是为什么我使用preRender事件的更新属性的原因,但它不起作用。

如果有人有一个想法来解决这个问题...

在此先感谢。

更新1:

的 “初始化” 由 “ConsultationBean” 的方法是效率不高。事实上,我创建了“MapMarker”并将它们添加到地图中,但它们从未出现在视图中。然而,这些由视图生成包含在视图中的标志和VI的“UI:重复”标签:

   <ui:repeat var="marker" value="#{consultationBean.markers}"> 
        <util:mapMarker/> 
       </ui:repeat> 

我发现我的MapMarkers是在“ConsultationBean”之前建造的。因此,我的相机列表和标记列表是空的,但生成的标记数量与存储在数据库中的相机数量相同。

我试图把一个ID标记以“#{camera.code}#作为一个值,用下面的代码:

   <ui:repeat var="camera" value="#{consultationBean.cameras}"> 
        <util:mapMarker id="#{camera.code}"/> 
       </ui:repeat> 

不幸的是它失败了,因为列表是空的。我真的坚持我的生成标记的方式

+2

请不要发布完整的课程和完整的代码页。 Ommit getter/setters,包声明,导入等。这会影响可读性,并且完全不相关。请发布代码**的简短**示例,以说明您的问题,这也在常见问题解答中说明。 – siebz0r

回答

0

试试这个:

@Override 
public void encodeBegin(FacesContext context) throws IOException{ 
    padding = Integer.parseInt((String) AppUtil.getProperty(PADDING_PROP)); 
    maxZoom = Integer.parseInt((String) AppUtil.getProperty(MAX_ZOOM_MARKER_PROP)); 
    latitude = (float) 47.67876; 
    longitude = (float) 6.97061; 
    super.encodeBegin(context); 
} 
+0

作为示例,在构造函数中设置了纬度和经度值。我已经通过将“padding”属性设置为“55”来尝试你的方法,当我用Firebug查看视图的源代码时,它的值是55。因此,“encodeBegin”方法适用于更新已经构建的组件,但我想要做的是使用我在init方法中传递给组件的值执行相同的操作。 从“ConsultationBean”我的“init”方法也是错误的,因为我创建了视图从不显示的其他“MarkerComponent”。 – user1194442

1

我终于找到了解决办法 我所做的是,我已经添加了其它附加。组件添加到名为“MapMarkersContainer”的视图中。该组件包含摄像机列表,该列表在MapMarker的“encodeBegin”被调用之前填充。 我修改了“MapMarker”的“encodeBegin”,以便通过“MapMarkersContainer”列表获取所有相机信息。

<h:body> 
    <!-- INTERFACE --> 
    <composite:interface componentType="mapMarkersContainer"> 
     <composite:attribute name="cameras" type="java.util.List" /> 
    </composite:interface> 

    <!-- IMPLEMENTATION --> 
    <composite:implementation> 

    </composite:implementation> 
</h:body> 
</html> 

下面是支持bean的源代码:

@FacesComponent(value = "mapMarkersContainer") 
public class MapMarkersContainer extends UINamingContainer { 
    private List<Camera> cameras; 

    private Integer currentIndex = 0; 

    public List<Camera> getCameras() { 
     currentIndex++; 
     return cameras; 
    } 

    public void setCameras(List<Camera> cameras) { 
     this.cameras = cameras; 
    } 

    public Integer getCurrentIndex() { 
     return currentIndex; 
    } 

    public void setCurrentIndex(Integer currentIndex) { 
     this.currentIndex = currentIndex; 
    } 
} 

这是发生在 “MapMarker” 的修改:

@FacesComponent(value = "mapMarker") 
public class MapMarker extends UINamingContainer { 

    private static final String PADDING_PROP = "padding"; 
    private static final String MAX_ZOOM_MARKER_PROP = "max_zoom_marker"; 

    private Float longitude; 
    private Float latitude; 
    private String popUpContent; 
    private Integer padding; 
    private Integer maxZoom; 
    private Camera camera; 

    public MapMarker() { 
     padding = Integer.parseInt((String) AppUtil.getProperty(PADDING_PROP)); 
     maxZoom = Integer.parseInt((String) AppUtil.getProperty(MAX_ZOOM_MARKER_PROP)); 
    } 

    @Override 
    public void encodeBegin(FacesContext context) throws IOException { 
     padding = Integer.parseInt((String) AppUtil.getProperty(PADDING_PROP)); 
     maxZoom = Integer.parseInt((String) AppUtil.getProperty(MAX_ZOOM_MARKER_PROP)); 
     MapMarkersContainer mapMarkersContainer = (MapMarkersContainer) FacesUtils.findComponentById(context, 
       "mapMarkersContainer"); 
     Integer cameraIndex = mapMarkersContainer.getCurrentIndex(); 
     Camera camera = mapMarkersContainer.getCameras().get(cameraIndex); 
     latitude = camera.getY(); 
     longitude = camera.getX(); 
     popUpContent = camera.toString(); 
     setId(camera.getNom()); 
     super.encodeBegin(context); 
    } 

    public Float getLongitude() { 
     return longitude; 
    } 

    public void setLongitude(Float longitude) { 
     this.longitude = longitude; 
    } 

    public Float getLatitude() { 
     return latitude; 
    } 

    public void setLatitude(Float latitude) { 
     this.latitude = latitude; 
    } 

    public String getPopUpContent() { 
     return popUpContent; 
    } 

    public void setPopUpContent(String popUpContent) { 
     this.popUpContent = popUpContent; 
    } 

    public Integer getPadding() { 
     return padding; 
    } 

    public void setPadding(Integer padding) { 
     this.padding = padding; 
    } 

    public Integer getMaxZoom() { 
     return maxZoom; 
    } 

    public void setMaxZoom(Integer maxZoom) { 
     this.maxZoom = maxZoom; 
    } 

    public Camera getCamera() { 
     return camera; 
    } 

    public void setCamera(Camera camera) { 
     this.camera = camera; 
    } 

} 

,这里是在“ConsultationBean发生了什么变化“查看:

<ui:composition template="/xhtml/common/layout.xhtml"> 
    <ui:define name="headTitle"> 
     <h:outputText value="#Cartographie#" /> 
    </ui:define> 

    <ui:define name="header"> 
     <ui:include src="/xhtml/common/header.xhtml"> 
      <ui:param name="headerClass" value="banner-thin" /> 
     </ui:include> 
    </ui:define> 

    <ui:define name="content"> 

     <util:mapMarkersContainer id="mapMarkersContainer"/> 
     <div id="content" class="content-home ui-corner-bottom"> 

      <h2 class="main-title content-title light-bg light-bordered-top"> 
       <h:outputText value="#Cartographie#" /> 
      </h2> 
      <h:panelGroup id="mapPanelGroup"> 
       <util:map id="mapContainer"> 
        <ui:repeat id="repeat" var="camera" value="#{consultationBean.cameras}"> 
         <util:mapMarker/> 
        </ui:repeat> 
       </util:map> 
      </h:panelGroup> 
     </div> 
    </ui:define> 
</ui:composition> 
</html> 

这里是“ConsultationBean”的Java源代码:

/** 
* Le Class ConsultationBean. 
*/ 
@Controller 
@Scope("view") 
@SuppressWarnings("serial") 
public class ConsultationBean implements Serializable { 

    /** Le cameras. */ 
    private List<Camera> cameras; 

    /** Le markers. */ 
    private List<MapMarker> markers; 

    private MapMarkersContainer mapMarkersContainer; 

    /** Le camera service. */ 
    @Autowired 
    private CameraService cameraService; 

    /** 
    * Initialise le. 
    * 
    * @throws IOException 
    */ 
    @PostConstruct 
    public void init() throws IOException { 
     cameras = cameraService.findAll(); 
     mapMarkersContainer = (MapMarkersContainer) FacesUtils.findComponentById(FacesContext.getCurrentInstance(), 
       "mapMarkersContainer"); 
     mapMarkersContainer.setCameras(cameras); 
    } 

    /** 
    * Getter : retourne le markers. 
    * 
    * @return le markers 
    */ 
    public List<MapMarker> getMarkers() { 
     return markers; 
    } 

    /** 
    * Setter : affecte le markers. 
    * 
    * @param markers le markers 
    */ 
    public void setMarkers(List<MapMarker> markers) { 
     this.markers = markers; 
    } 

    public List<Camera> getCameras() { 
     return cameras; 
    } 

    public void setCameras(List<Camera> cameras) { 
     this.cameras = cameras; 
    } 
} 

现在,每个标记已经是自己的ID和自己的正确的值。每次使用摄像机列表的getter方法时,计数器都会更新,以便您可以在正确的索引处访问正确的摄像机。

感谢Guilherme Torres Castro提供的答案和“encodeBegin”方法的发现。