我正在尝试为某些节点添加一些json处理功能。所以我编写了从SlingSafeMethodsServlet
扩展的自定义servlet,我需要在用户为以下URL进行GET时执行: /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 当然意味着任何有效符号序列。
问题是我在吊索文档中找不到如何将此模板映射为网址。
我一直试图设置这样的属性:
@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?
感谢。
答案 0 :(得分: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
答案 1 :(得分:1)
我已经解决了这个问题,正如原始海报所希望的那样。所有其他答案实际上是“它无法完成”或“如果你愿意用选择器弄脏你干净的RESTful API,这就是一种方法”
如果您想保留您想象的干净API,请按照以下方式进行操作。这也适用于没有扩展名的Apis,例如/ myservice / mythings / 123123,其中123123是一些动态ID
创建两个文件:
ResourceProvider
这样做的目的只是为了侦听/ 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
现在您只需编写一个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();
}
}
}
答案 2 :(得分: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"
})
})
答案 3 :(得分: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());
}
}
呼叫是[服务器]:[端口] / bin /解析器/ gb。[通配符]
所以可以做的是:[服务器]:[port] /bin/resolver/gb.en/something
&#34;。&#34;之后的一切被认为是一个扩展,所以需要在servlet中处理,但帮助我实现了我的要求
答案 4 :(得分:0)
似乎你的servlet的路径是相同的。只是选择器是变化的。与path一起使用时,SlingServlet中会忽略其他内容。所以使用这样的东西应该达到目的: @SlingServlet(paths =“/ data / events / any_sequence / any_sequence”,extensions =“json”)
你需要在Felix控制台(/ system / console / configMgr)的执行路径中添加/ data,就像在Apache Sling Servlet Resolver属性中默认不存在一样
答案 5 :(得分:0)
这可以通过构建Sling映射或Apache重写来使用所需的外部URI模式来有效地将JSON扩展有效地移动到&#34; data&#34;之后。在URI中,所以单个servlet位于&#34; / data&#34;最终通过请求的后缀接收任意路径。如果您还在使用选择器中的数据,则需要将它们与扩展程序一起移动。