Adobe AEM 6.5 Cloud:SlingServletPaths 中的通配符?

问题描述 投票:0回答:1

我们想要构建一个单一的代理 servlet,它将服务于许多不同的路径,例如

/api/注册

/api/播放器/1234/

/api/播放器/12312/交易

基本上,/api/下面的所有路径

目前我们正在使用这种模式,它只允许单个或固定路径列表:

@SlingServletPaths(value="/bin/somepath")
private class MyServlet extends SlingAllMethodsServlet

关于如何处理变量路径有什么建议吗?

我在这里找到了一个使用自定义 ResourceResolver 的潜在解决方案,但不幸的是它无法编译(注释和导入等在 AEM 6.5 中不再可用):

https://stackoverflow.com/a/41990177/1072187

aem sling
1个回答
0
投票

你不能用 Sling-Servlets 做到这一点。但是您可以在 Sling MainServlet 旁边有一个 OSGi Whiteboard-Pattern Servlet。最简单的情况是使用与 Sling 相同的上下文名称(因为 Sling 已经注册了整个 URL 空间)

详情请参考: https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.http.whiteboard.html

我也喜欢为一些外部服务使用代理 servlet(例如 Solr、Commerce-System 等)。对于开发来说,它比在每台开发人员机器上设置额外的基础设施要简单得多。

但是:

  1. 仅将此方法用于本地开发(或者可能在 PROD 上进行错误分析)
  2. 使用一种信号量来限制请求的数量。如果你的代理很慢,或者不工作 - 它可以很容易地吃掉所有 100 个并行请求,直到 Sling 阻止传入请求。这将完全终止您的 AEM 实例。对我来说,限制为 4/5 并行代理请求和 200-500 毫秒的等待时间就足够了。

PS: scope=PROTOTYPE 对 HttpWhiteboard 服务很重要

@Component(service = Servlet.class, scope = ServiceScope.PROTOTYPE)
@HttpWhiteboardServletPattern("/api/*")
@HttpWhiteboardContextSelect("(" + HTTP_WHITEBOARD_CONTEXT_NAME + "=org.apache.sling)")
public class OsgiProxyServlet extends HttpServlet {

    public static final Logger LOGGER = LoggerFactory.getLogger(OsgiProxyServlet.class);

    private final Semaphore semaphore;

    @Activate
    public OsgiProxyServlet() {
        this.semaphore = new Semaphore(/* max. parallel requests */ 5, true);
        LOGGER.info("Proxy Servlet instantiated");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {

        LOGGER.info("Got API Request: {}", request.getRequestURL());

        boolean permitAcquired = false;
        try {
            permitAcquired = semaphore.tryAcquire(/* timeout */ 500, TimeUnit.MILLISECONDS);
            if (permitAcquired) {
                doProxyGet(request, response);
            } else {
                respond(response, SC_REQUEST_TIMEOUT, "Failed to acquire a proxy connection");
            }
        } catch (InterruptedException e) {
            // in the Servlet.doGet()-method we cannot propagate the InterruptedException,
            // so we have to set the flag back to true
            Thread.currentThread().interrupt();
        } finally {
            if (permitAcquired) {
                semaphore.release();
            }
        }
    }


    private void doProxyGet(HttpServletRequest request, HttpServletResponse response) {
        // put your proxy code here
        LOGGER.info("Proxy request {}", request.getRequestURI());
        respond(response, SC_OK, "Proxy request for path " + request.getPathInfo());
    }

    private static void respond(HttpServletResponse response, int status, String message) {
        response.setContentType("text/plain");
        response.setCharacterEncoding("utf-8");
        response.setStatus(status);
        try {
            response.getWriter().print(message);
        } catch (IOException e) {
            LOGGER.error("Failed to write output", e);
        }
    }
}

这是一个工作的 ServletFilter,您要求的(有关更多信息,请参阅 https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.http.whiteboard.html):

@Component(scope = ServiceScope.PROTOTYPE)
@HttpWhiteboardFilterPattern("/api/*")
@HttpWhiteboardContextSelect("(" + HTTP_WHITEBOARD_CONTEXT_NAME + "=org.apache.sling)")
public class OsgiFilter implements Filter {

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response,
                         final FilterChain filterChain) throws IOException, ServletException {

        filterChain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) {
        // empty
    }

    @Override
    public void destroy() {
        // empty
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.