AEM 6.1:SlingFilter如何获取data-sly-resource引入的组件?COMPONENT scope无效
如何在SlingFilter中捕获data-sly-resource引入的组件列表
我之前也碰到过完全一样的问题!SlingFilterScope.COMPONENT确实只会抓取那些挂载在页面节点下的容器组件(比如parsys、iparsys)里的子组件——因为这些组件是作为页面的直接子节点存储在CRX中的,属于“静态挂载”的范畴。而data-sly-resource引入的组件是动态渲染的,它们可能来自任意路径,甚至是运行时生成的资源,并不会作为页面节点的子节点存在,所以COMPONENT作用域的过滤器根本碰不到它们。
下面是我亲测可行的解决方案:
1. 切换到REQUEST作用域的过滤器
REQUEST作用域的过滤器会覆盖整个请求的完整处理流程,包括所有动态资源的渲染阶段。你需要把过滤器的scope设置为SlingFilterScope.REQUEST,然后通过Sling的内部属性来获取所有被渲染过的资源。
2. 获取渲染过的资源列表
Sling在请求处理完成后,会把所有渲染过的资源记录在一个请求属性里:org.apache.sling.engine.SlingRequestProcessor.RENDERED_RESOURCES。这个属性的值是一个Set<Resource>,里面包含了页面本身、parsys里的组件,以及所有通过data-sly-resource引入的组件。
代码示例
import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.resource.Resource; import org.apache.sling.engine.SlingRequestProcessor; import org.apache.sling.engine.filter.AbstractSlingFilter; import org.osgi.service.component.annotations.Component; import javax.servlet.FilterChain; import javax.servlet.ServletException; import java.io.IOException; import java.util.Set; @Component( service = javax.servlet.Filter.class, property = { "sling.filter.scope=REQUEST", "service.ranking=1000" // 确保在渲染完成后执行,数值越大执行时机越晚 } ) public class RenderedComponentsFilter extends AbstractSlingFilter { @Override protected void doFilter(SlingHttpServletRequest request, SlingHttpServletResponse response, FilterChain chain) throws IOException, ServletException { try { chain.doFilter(request, response); // 在请求处理完成后获取完整的渲染资源列表 Set<Resource> renderedResources = (Set<Resource>) request.getAttribute(SlingRequestProcessor.RENDERED_RESOURCES); if (renderedResources != null) { for (Resource resource : renderedResources) { // 过滤掉页面本身的资源,只处理组件 if (!"/libs/wcm/foundation/components/page".equals(resource.getResourceType())) { System.out.println("已渲染组件:" + resource.getPath() + ",类型:" + resource.getResourceType()); // 这里添加你的业务处理逻辑 } } } } finally { // 可在此处添加资源清理逻辑 } } }
3. 关键注意事项
- Service Ranking设置:一定要给过滤器设置较高的
service.ranking值(比如1000+),这样过滤器会在大部分渲染逻辑执行完成后才触发,确保能拿到完整的渲染资源列表。如果排名太低,可能在部分组件还没渲染时就执行,会漏掉动态引入的组件。 - 过滤页面资源:
RENDERED_RESOURCES里会包含页面组件本身,所以需要根据资源类型或路径把它排除掉,只处理真正的业务组件。 - 版本兼容性:这个属性是Sling Engine提供的,在AEM 6.3及以上版本都能正常使用,如果你用的是更老的版本,需要确认Sling文档中属性名称是否有变化。
备选方案:使用Sling Resource Listener
如果你需要在组件被渲染的那一刻就捕获,而不是等整个请求完成,可以注册一个ResourceListener,监听资源的RESOURCE_RENDERED事件。不过这种方式会针对每个组件触发一次,需要自己手动聚合列表,不如REQUEST过滤器来得直接高效。
内容的提问来源于stack exchange,提问作者Korben_ne_Dallas
相关产品推荐
相关产品推荐

