1

我正在尝试为某些节点的 json 处理添加一些功能。因此,我编写了扩展的自定义 servlet SlingSafeMethodsServlet,当用户为以下 url 进行 GET 时,我需要执行该 servlet:/data/events/any_sequence/any_sequence.json/data/events/any_sequence/any_sequence.infinity.json或例如/data /events/any_sequence/any_sequence.2.json其中any_sequence当然意味着任何有效的符号序列。

问题是我在 sling 文档中找不到如何像 url 一样映射这个模板。

我一直在尝试设置这样的属性:

@Component
@Service
@Properties({
    @Property(name = "sling.servlet.resourceTypes", value = "data/events/-/-"),
    @Property(name = "sling.servlet.extensions", value = "json"),
    @Property(name = "sling.servlet.methods", value = "GET"),
    @Property(name = "service.description", value = "JSON advanced renderer")
})

但这没有帮助。我检查了 felix 控制台,发现我的服务已经启动并运行,所以问题是如何设置 url 映射。所以我的问题是如何在我的情况下设置 url 映射来调用我的自定义 servlet 的 doGet ?

谢谢。

4

6 回答 6

5

据我了解,CQ5 不提供在通配符 url 上映射自定义 servlet 的能力。实现类似于我需要的目标的唯一方法是为此 servlet 选择器使用一些独特的方法,如下所示:

@Component
@Service
@Properties({
    @Property(name = "sling.servlet.resourceTypes", value = "sling/servlet/default"),
    @Property(name = "sling.servlet.extensions", value = "json"),
    @Property(name = "sling.servlet.selectors", value = "advanced"),
    @Property(name = "sling.servlet.methods", value = "GET"),
    @Property(name = "service.description", value = "JSON advanced renderer")
})

这段代码意味着,如果我尝试使用*.advanced.json选择器和扩展名在某个节点上进行 GET,那么请求将被转发到我的自定义 servlet。

请参阅http://apache-sling.73963.n3.nabble.com/Register-servlet-for-subtree-td84106.html

于 2012-06-26T05:47:55.027 回答
2

我已经解决了这个问题,正如原始海报所希望的那样。所有其他答案实际上都是“无法完成”或“如果您愿意使用选择器弄脏干净的 RESTful API,这是一种方法”

如果你想保持你设想的干净的 API,下面是方法。这也适用于没有扩展的 API,例如 /myservice/mythings/123123 ,其中 123123 是一些动态 ID

创建两个文件:

  • 资源提供者
  • 小服务程序

资源提供者

这样做的目的只是侦听 /data/events 处的所有请求,然后在该虚拟路径上生成一个“资源”,该路径实际上并不存在于 JCR 中。

@Component
@Service(value=ResourceProvider.class)
@Properties({
        @Property(name = ResourceProvider.ROOTS, value = "data/events"),
        @Property(name = ResourceProvider.OWNS_ROOTS, value = "true")
})
public class ImageResourceProvider implements ResourceProvider  {

@Override
public Resource getResource(ResourceResolver resourceResolver, String path) {

    AbstractResource abstractResource;
    abstractResource = new AbstractResource() {
        @Override
        public String getResourceType() {
            return TypeServlet.RESOURCE_TYPE;
        }

        @Override
        public String getResourceSuperType() {
            return null;
        }

        @Override
        public String getPath() {
            return path;
        }

        @Override
        public ResourceResolver getResourceResolver() {
            return resourceResolver;
        }

        @Override
        public ResourceMetadata getResourceMetadata() {
            return new ResourceMetadata();
        }
    };

    return abstractResource;
}

@Override
public Resource getResource(ResourceResolver resourceResolver, HttpServletRequest httpServletRequest, String path) {
    return getResource(resourceResolver , path);
}

@Override
public Iterator<Resource> listChildren(Resource resource) {
    return null;
}
}

小服务程序

现在您只需编写一个 servlet 来处理来自该路径的任何资源 - 但这是通过处理具有由在该路径上侦听的 ResourceProvider 生成的资源类型的任何资源来完成的。

@SlingServlet(
        resourceTypes = TypeServlet.RESOURCE_TYPE,
        methods = {"GET" , "POST"})
public class TypeServlet extends SlingAllMethodsServlet {


    static final String RESOURCE_TYPE = "mycompany/components/service/myservice";

    @Override
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {

        final String [] pathParts = request.getResource().getPath().split("/");
        final String id = pathParts[pathParts.length-1];
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        try {
            out.print("<html><body>Hello, received this id: " + id + "</body></html>");
        } finally {
             out.close();
        }
    }
}
于 2017-02-01T21:33:36.210 回答
0

这是我用来完成类似任务的语法:

@Component(immediate = true, description = "JSON advanced renderer")
@Service(value = javax.servlet.Servlet.class)
@Properties(value = {
        @Property(name = "sling.servlet.extensions", value = { "json" }),
        @Property(name = "sling.servlet.methods", value = { "GET" }),
        @Property(name = "sling.servlet.paths", value = {
                        "/data/events/any_sequence/any_sequence",
                        "/data/events/any_sequence/any_sequence.infinity",
                        "/data/events/any_sequence/any_sequence.2"
        })
})
于 2012-06-25T22:46:31.030 回答
0

我有一个类似的问题,我需要我使用的通配符

@Service
@Component
@Properties({
        @Property(name = "sling.servlet.paths", value = "/bin/resolver/gb"),
        @Property(name = "sling.servlet.extensions", value = "*")
})
public class Test extends SlingAllMethodsServlet {
    @Override
    public void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
       PrintWriter out = response.getWriter();
       out.print("The path you used is:" + request.getPathInfo());
    }
}

调用是 [server]:[port]/bin/resolver/gb.[wildcard]

所以可以做的是:[server]:[port]/bin/resolver/gb.en/something

“。”之后的所有内容 被认为是扩展,因此需要在 servlet 中处理,但帮助我实现了我的要求

于 2015-07-15T16:55:53.373 回答
0

看来您的 servlet 的路径是相同的。只是选择器有所不同。与路径一起使用时,SlingServlet 中会忽略其他内容。所以使用这样的东西应该可以达到目的:@SlingServlet(paths = " /data/events/any_sequence/any_sequence", extensions = "json")

您需要在 Felix 控制台(/system/console/configMgr)的执行路径中添加 /data,因为它在 Apache Sling Servlet Resolver 属性中默认不存在

于 2015-07-17T10:30:07.477 回答
0

这可以通过构建 Sling 映射或 Apache 重写使用所需的外部 URI 模式来完成,以有效地将 JSON 扩展移动到 URI 中的“数据”之后,因此“/data”处的单个 servlet 最终通过以下方式接收任意路径请求的后缀。如果您还使用来自选择器的数据,则需要将它们与扩展一起移动。

于 2016-03-31T22:57:45.210 回答