是否可以将变量放入吊索servlet中的资源路径中?

时间:2014-01-08 00:18:26

标签: cq5 sling aem

我们正在尝试为外部端点提供一个干净的URI结构,以便从CQ5中提取json信息。

例如,如果您想获取有关特定用户历史记录的信息(假设您拥有权限等),理想情况下我们希望端点能够执行以下操作:

/bin/api/user/abc123/phone/555-klondike-5/history.json

在URI中,我们将指定/bin/api/user/{username}/phone/{phoneNumber}/history.json,这样可以非常轻松地利用调度程序使缓存更改无效等,而不会使广泛的区域无效缓存信息。

我们想使用sling servlet来处理请求,但是,我不知道如何将变量放入路径中。

如果有来自JaxRS的@PathParam之类的内容添加到sling路径变量会很棒,但我怀疑它不可用。

我们想到的另一种方法是使用选择器来识别我们何时访问api,从而可以从路径返回我们想要的任何内容,但是需要一个单一的sling servlet来处理所有请求,所以我对这种方法并不满意,因为它将很多不相关的代码粘合在一起。

对此有任何帮助将不胜感激。


更新:

如果我们要使用OptingServlet,然后在接受函数中放入一些逻辑,我们可以堆叠一系列sling servlet并使用正则表达式从路径做出接受决定。

然后在执行期间,可以为变量解析路径本身。

5 个答案:

答案 0 :(得分:5)

如果您提供的数据来自JCR存储库,那么最好是按照您希望的URL来完全构建它,这是使用Sling执行操作的推荐方法。

如果数据是外部的,您可以创建一个自定义Sling ResourceProvider,它安装在/ bin / api / user路径上,并根据路径的其余部分获取或生成相应的数据。

Sling测试套件的PlanetsResourceProvider就是一个简单的例子,请参阅http://svn.apache.org/repos/asf/sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/resourceprovider/

https://sling.apache.org/documentation/the-sling-engine/resources.html处的Sling资源文档记录了一般资源解析机制。

答案 1 :(得分:2)

现在可以将jersy(JAX-RS)与CQ集成。我们可以创建原始原型来向世界说“你好”。

https://github.com/hstaudacher/osgi-jax-rs-connector

有了这个,我们可以使用@PathParam来映射请求

谢谢和问候, 圣

答案 2 :(得分:1)

没有直接的方法来创建这样的动态路径。您可以在/bin/api/user.json下注册servlet,并将其余路径作为suffix提供:

/bin/api/user.json/abc123/phone/555-klondike-5/history
^                 ^
|                 |
servlet path      suffix starts here

然后你可以手动解析后缀:

@SlingServlet(paths = "/bin/api/user", extensions = "json")
public class UserServlet extends SlingSafeMethodsServlet {
    public void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
        String suffix = request.getRequestPathInfo().getSuffix();
        String[] split = StringUtils.split(suffix, '/');
        // parse split path and check if the path is valid
        // if path is not valid, send 404:
        // response.sendError(HttpURLConnection.HTTP_NOT_FOUND);
    }
}

答案 3 :(得分:0)

解决此问题的RESTful方法是将信息存储在您要使用的结构中。即/ content / user / abc123 / phone / 555-klondike-5 / history /将包含该路径的所有历史节点。

在那种用法中。只需调用

即可获得开箱即用的json响应
/content/user/abc123/phone/555-klondike-5/history.json

或者,如果您需要特定json格式的内容,则可以使用sling资源解析来使用自定义json响应。

答案 4 :(得分:0)

很高兴分享这个!我已经工作了一个星期来解决这个问题,最后得到了最好的答案。

首先:尝试使用Jersey

kallada提出的osgi-jax-rs-connector是最好的,但我无法让它在Sling 8上工作。我失去了整整一天的尝试,所有我必须展示它是怪异的类未找到错误和依赖性问题。

解决方案:ResourceProvider

Bertrand的链接仅适用于Sling 9,但未发布。所以这就是你在Sling 8及更早版本中的表现!

两个文件:

  • ResourceProvider
  • 的Servlet

ResourceProvider

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

@Component
@Service(value=ResourceProvider.class)
@Properties({
        @Property(name = ResourceProvider.ROOTS, value = "service/image"),
        @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

现在您只需编写一个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();
        }
    }
}

显然你的servlet会做一些更聪明的事情,例如更智能地处理“path”字符串并且可能产生JSON。