AEM 6.1技术问询:如何获取页面所有parsys与iparsys组件
Hey there! Let's walk through a few solid ways to fetch all parsys and iparsys components from a given AEM page using Java. I'll break down each approach with code snippets and call out their pros and cons so you can pick what fits your use case best.
1. Directly Traverse the Page's Resource Tree
This is a straightforward approach: we start from the page's jcr:content resource and recursively check every child resource to find matches for parsys/iparsys resource types.
import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ValueMap; import java.util.ArrayList; import java.util.List; public List<Resource> getParsysAndIparsysComponents(ResourceResolver resolver, String pagePath) { List<Resource> targetComponents = new ArrayList<>(); // Grab the page's content resource (lives under /jcr:content) Resource pageContent = resolver.getResource(pagePath + "/jcr:content"); if (pageContent != null) { traverseResources(pageContent, targetComponents); } return targetComponents; } private void traverseResources(Resource currentResource, List<Resource> targetComponents) { ValueMap properties = currentResource.getValueMap(); String resourceType = properties.get("sling:resourceType", String.class); // Check if this resource is a parsys or iparsys if ("foundation/components/parsys".equals(resourceType) || "foundation/components/iparsys".equals(resourceType)) { targetComponents.add(currentResource); } // Recursively check all child resources for (Resource child : currentResource.getChildren()) { traverseResources(child, targetComponents); } }
Pros: Simple to implement, no extra dependencies.
Cons: Recursive traversal might hit performance issues on extremely deep/complex page structures.
Note: Update the sling:resourceType values if you're using Core Components (e.g., core/wcm/components/container/v1/container) or custom parsys variants.
2. Use AEM QueryBuilder for Indexed Searches
QueryBuilder leverages JCR indexes to efficiently find matching resources, making it a better choice for large pages or complex query needs.
import com.day.cq.search.PredicateGroup; import com.day.cq.search.Query; import com.day.cq.search.QueryBuilder; import com.day.cq.search.result.SearchResult; import org.apache.sling.api.resource.ResourceResolver; import org.osgi.service.component.annotations.Reference; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; // Inject QueryBuilder via OSGi reference in your component/service @Reference private QueryBuilder queryBuilder; public List<Resource> getParsysAndIparsysViaQueryBuilder(ResourceResolver resolver, String pagePath) { Map<String, String> predicates = new HashMap<>(); // Focus the query on the page's content node predicates.put("path", pagePath + "/jcr:content"); // Match either parsys or iparsys resource type predicates.put("property", "sling:resourceType"); predicates.put("property.1_value", "foundation/components/parsys"); predicates.put("property.2_value", "foundation/components/iparsys"); predicates.put("property.operation", "OR"); // Return all matching results (no limit) predicates.put("p.limit", "-1"); Query query = queryBuilder.createQuery(PredicateGroup.create(predicates), resolver.adaptTo(javax.jcr.Session.class)); SearchResult result = query.getResult(); // Convert search hits to Resource objects return result.getHits().stream() .map(hit -> hit.getResource()) .collect(Collectors.toList()); }
Pros: Fast and scalable, especially for large pages, since it uses indexed searches.
Cons: Requires understanding QueryBuilder predicates; ensure relevant JCR indexes (like cqPageLucene) are enabled and maintained.
3. Leverage PageManager for WCM-Centric Traversal
If you're already working with AEM Page objects, this approach uses the PageManager API to access the page content and then traverses child resources.
import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageManager; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import java.util.ArrayList; import java.util.List; public List<Resource> getParsysFromPageManager(ResourceResolver resolver, String pagePath) { List<Resource> targetComponents = new ArrayList<>(); PageManager pageManager = resolver.adaptTo(PageManager.class); Page page = pageManager.getPage(pagePath); if (page != null) { Resource contentResource = page.getContentResource(); if (contentResource != null) { collectParsysResources(contentResource, targetComponents); } } return targetComponents; } private void collectParsysResources(Resource resource, List<Resource> targetList) { String resourceType = resource.getResourceType(); if ("foundation/components/parsys".equals(resourceType) || "foundation/components/iparsys".equals(resourceType)) { targetList.add(resource); } // Check all child resources for (Resource child : resource.getChildren()) { collectParsysResources(child, targetList); } }
Pros: Aligns with AEM's WCM layer, intuitive if you're already handling Page instances.
Cons: Same recursion performance consideration as the first method for complex pages.
Key Reminders
- Permissions: Ensure the
ResourceResolverhas read access to the page and its components, otherwise you'll get null resources. - Custom Components: Always update the
sling:resourceTypevalues to match your actual component types (Core Components, custom parsys, etc.).
内容的提问来源于stack exchange,提问作者Korben_ne_Dallas

