【问题标题】:How to call a Servlet/Filter before a JSP is executed in CQ5?在 CQ5 中执行 JSP 之前如何调用 Servlet/Filter?
【发布时间】:2014-11-24 14:27:47
【问题描述】:

在 Spring MVC 应用程序中,我们有一个控制器,它将在调用 JSP 之前执行。 Controller 会从数据库中预取一些值,并将它们设置在模型中,然后将控制权转发给 JSP。

如何在 CQ 5 中实现此功能?我希望 SlingFilter 在执行 JSP 之前执行。而且JSP不是页面组件,而是出现在side kick中的组件。

注意:

我可以通过编写自己的 SlingSerlvet 来实现这一点,该 SlingSerlvet 将预取我所需的值并使用 RequestDispatcher 转发到 JSP。 但是通过这种方法,我必须通过像“/bin/.*”这样的 URL。 这又是在页面级别,我希望在组件级别具有这种功能。

【问题讨论】:

  • 如果你喜欢春天,你应该检查一下:neba.io/neba-in-a-nutshell.html
  • @nerd:很棒的链接!你认为这可以帮助我解决我的问题吗?我已经浏览了该网站,但您可以告诉我是否可以使用 NEBA 实现上述目标,从而节省我的精力

标签: java jsp aem sling


【解决方案1】:

因此,为了回答您的具体问题,如果您希望在调用组件之前执行过滤器,您将创建一个正在侦听组件级别过滤器范围的过滤器。

http://sling.apache.org/documentation/the-sling-engine/filters.html

然后您将让您的过滤器将传入请求更改为 SlingServletRequest 并确定目标资源是否是您正在寻找的资源。

但是,此过滤器将在页面中包含的每个组件上执行。可能对您有用的反向过程是 ResourceDecorator。

http://sling.apache.org/documentation/the-sling-engine/wrap-or-decorate-resources.html

这些在资源被识别时执行,在 servlet 和过滤器调用之前,这将允许您验证资源是否是您感兴趣的类型,然后允许您向资源对象添加附加信息.然而,这又是一项服务,将应用于识别的每个资源。

但是,如果您要查找的是仅针对特定路径执行的过滤器,则不需要。吊索不会那样做。您提到 Spring MVC 和 Spring MVC 的工作原理与 MVC 的 Slings 版本完全不同。

编辑

因此,在传统的 Web 应用程序中,servlet 将位于固定位置,并且在调用该 servlet 之前应用所有过滤器。在 Sling 中,您动态地将 servlet 连接在一起以生成结果页面。因此,每次您在 servlet 中并直接或间接调用请求调度程序时,它都会再次执行解析过程并在执行新的 servlet 之前应用一系列过滤器再次

为了防止只需要应用于每个内部调度的主请求的高级过滤器,他们提出了上下文的想法,或者在不同时间应用并与不同类型相关联的过滤器链包括。

这是一个基本过滤器,它会在调用时记录一条消息。我是凭记忆做的,所以你需要接受它。

@SlingFilter(scope = SlingFilterScope.COMPONENT, order = Integer.MIN_VALUE)
public class SampleFilter implements Filter {

    private static final Logger LOG = LoggerFactory.getLogger(SampleFilter.class);

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
        Resource res = slingRequest.getResource();
        if (!(res == null || ResourceUtil.isNonExistingResource(res))) {
            LOG.error("this servlet is called before resource {} at path {}", res.getName(),res.getPath());
        }
        chain.doFilter(request, response);
    }

}

其中重要的部分是 scope = SlingFilterScope.COMPONENT 看看我之前列出的页面并尝试 sligfilterscope 的不同组合,您会看到它在不同时间的应用情况. scope = SlingFilterScope.REQUEST 将在每页的顶层出现一次。

【讨论】:

  • 你能告诉我一个在渲染组件之前如何调用过滤器的例子吗?这会让事情更容易理解
  • 在 CQ5 中的每个资源之前调用此过滤器。在将数据添加到请求对象之前,我正在检查条件res.getResourceType().equals("myapp/components/mycomp"),因此我最终不会为错误的资源类型执行不必要的代码。 它有效,但我只是希望这是正确的做法。
【解决方案2】:

就过滤器而言,JE Bailey 的回答是正确的,但我怀疑您的问题可能会以更适合 Sling 的世界观的不同方式解决。

Sling 提倡在业务逻辑中使用 OSGi 服务,脚本应该是其之上的一个薄层。将您的逻辑转移到 OSGi 服务并从您的脚本中调用这些服务是推荐的方式。

您还可以查看Sling Models,它可以包括在渲染脚本启动之前的处理步骤(使用@PostConstruct)。

【讨论】:

    【解决方案3】:

    但是通过这种方法,我将不得不通过像“/bin/.*”这样的 URL。

    您还可以针对资源类型以及路径注册 servlet,例如(from the Sling documentation):

    @SlingServlet(
        resourceTypes = "sling/servlet/default",
        selectors = "hello",
        extensions = "html",
        methods = "GET")
    public class MyServlet extends SlingSafeMethodsServlet {
    
        @Override
        protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
            ...
        }
    }
    

    如果您删除注释上的“选择器”、“扩展”和“方法”参数,此 servlet 将绑定 所有sling/servlet/default 的调用,而不需要绑定到设置的路径。

    【讨论】:

    • 有没有办法使用特定的路径/uri 作为过滤器定义来过滤 CQ5 中对 jsp 的请求,即不使用选择器完成?这很有用……如果我们想要修改行为或包装来自标准 CQ5 extjs 小部件的 POST 请求,而我们无法为其指定选择器?
    猜你喜欢
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 2013-08-23
    • 2014-12-16
    相关资源
    最近更新 更多