如何为 Sling Servlet 启用异步支持 - Felix

How to enable Async support for Sling Servlet - Felix

我有这个代码

  @Component(service = Servlet.class, scope = ServiceScope.PROTOTYPE, property={
    HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN+"=/content/*",
    HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_ASYNC_SUPPORTED+"=true",
    HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED+"=true"}
    )
  @SlingServletResourceTypes(
    resourceTypes="cq/Page",
    methods=HttpConstants.METHOD_GET,
    selectors = "asynctest",
    extensions="json")
   public class ReactiveServlet extends HttpServlet {

@Override
protected void doGet(
        HttpServletRequest  request, HttpServletResponse response)
        throws ServletException, IOException {
         AsyncContext async = request.startAsync();
        // Some logic
        }
 }          

当调用这个 servlet /content/mypage.asynctest.json 然后得到这个错误

 java.lang.IllegalStateException: null
at org.apache.felix.http.base.internal.dispatch.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:338) [org.apache.felix.http.jetty:4.1.10]
at javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:369) [org.apache.felix.http.servlet-api:1.1.2]
at javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:369) [org.apache.felix.http.servlet-api:1.1.2]

简短的回答是 Sling-Servlets 不支持 异步。您的异常在 class:

中抛出

https://github.com/apache/felix-dev/blob/master/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletRequestWrapper.java

@Override
public AsyncContext startAsync() throws IllegalStateException
{
    if ( !this.asyncSupported )
    {
        throw new IllegalStateException();
    }
    return super.startAsync();
}

但是您将 OSGi Http-Whiteboard Pattern 与 Sling-Servlets 混合在一起。我不确定,你想做什么。

Sling/AEM是一个技术栈,层层叠叠。不幸的是,这些层中的多个层允许注册一个 servlet。

  • Sling Servlets = Apache Sling(推荐,默认)
  • OSGi HTTP 白板模式 = Apache Felix(仅适用于特殊情况)
  • JEE Servlet = Jetty Servlet 容器(不推荐)

Sling-Servlet

您注册的 Sling-Servlet @SlingServletResourceTypes 不支持异步。以下 servlet 的输出是:Async is not supported by an Sling-Servlet! (http://localhost:4502/content/we-retail.asynctest.json)

import static org.apache.sling.api.servlets.ServletResolverConstants.*;

import javax.servlet.AsyncContext;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.IOException;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.service.component.annotations.Component;

@Component(service = Servlet.class, property = {
        SLING_SERVLET_RESOURCE_TYPES + "=cq:Page",
        SLING_SERVLET_SELECTORS + "=asynctest",
        SLING_SERVLET_EXTENSIONS + "=json",
        SLING_SERVLET_METHODS + "=GET"
})
public class AsyncSlingServlet extends SlingSafeMethodsServlet {

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

        if (request.isAsyncSupported() /* false */) {
            final AsyncContext async = request.startAsync();
            async.start(() -> {
                async.getResponse().setContentType("text/plain");
                async.getResponse().setCharacterEncoding("utf-8");
                try {
                    async.getResponse().getWriter().println(
                            "Hello from the Sling-Servlet!");
                } catch (IOException e) {
                    // ignore
                }
                async.complete();
            });
        } else {
            response.setContentType("text/plain");
            response.setCharacterEncoding("utf-8");
            response.getWriter().println(
                    "Async is not supported by an Sling-Servlet!");
        }
    }
}

OSGi HTTP 白板模式

通过 OSGi HTTP 白板模式注册的几乎相同的 servlet 支持异步。它 returns Hello from the OSGi Http-Whiteboard Servlet! (http://localhost:4502/my-project/hello)。但这样的 servlet 是 Sling 的一旁,所以它们是“竞争对手”或“竞争者”。您必须小心,不要对 Sling 产生负面影响。所以应该避免 /content 路径。

import javax.servlet.AsyncContext;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ServiceScope;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;

@Component(
        service = Servlet.class,
        scope = ServiceScope.PROTOTYPE,
        property = {
                HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN
                        + "=/my-project/*",
                HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT
                        + "=("
                        + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME
                        + "=org.apache.sling)",
                HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_ASYNC_SUPPORTED
                        + "=true",
                HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED
                        + "=true" }
)
public class AsyncOSGiServlet extends HttpServlet {

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

        if (request.isAsyncSupported() /* true */) {
            final AsyncContext async = request.startAsync();
            async.start(() -> {
                async.getResponse().setContentType("text/plain");
                async.getResponse().setCharacterEncoding("utf-8");
                try {
                    async.getResponse().getWriter().println(
                            "Hello from the OSGi Http-Whiteboard Servlet!");
                } catch (IOException e) {
                    // ignore
                }
                async.complete();
            });
        } else {
            response.setContentType("text/plain");
            response.setCharacterEncoding("utf-8");
            response.getWriter().println(
                    "Async is not supported by an OSGi Http-Whiteboard Servlet!");
        }
    }
}