【问题标题】:Struts2 Interceptor *after* JSP is rendered - how?Struts2 Interceptor *after* JSP 被渲染 - 如何?
【发布时间】:2009-08-23 04:33:10
【问题描述】:

我想知道是否可以在结果返回并呈现 JSP 后捕获操作的结果。我希望能够获取整个结果(生成的 HTML)并将其推送到 memcached 中,这样我就可以通过 Nginx 带来它而无需访问应用程序服务器。有什么想法吗?

PS:我知道我可以在动作执行之后但在结果返回和呈现 JSP 之前运行拦截器,但不能在呈现 JSP 之后运行。

【问题讨论】:

    标签: struts2 memcached interceptor


    【解决方案1】:

    我还没有找到在 struts2 中执行此操作的方法,最好创建一个 servlet 过滤器并让它修改 OutputStream。

    http://onjava.com/pub/a/onjava/2003/11/19/filters.html

    【讨论】:

      【解决方案2】:

      嘿,我知道现在回答已经很晚了,您可能已经找到了答案,但是为了其他人受益,我发布了答案。 与您正在做的事情非常相似的一件事是通过 sitemesh 过滤器完成的。 是的,过滤器出现在 Struts2 过滤器本身之前和之后,因此您可以轻松地弄乱输入和输出。 但是 struts 确实会评估 JSP/freemarker/velocity 并生成传递给用户的最终 html。 JSP 有点棘手,因为在内部调用了一个 servlet,但是查看org.apache.struts2.views.freemarker.FreemarkerResult class,您可以看到在template.process(model, writer); 中生成了实际的 html。这个作者其实是ServletActionContext.getResponse().getWriter()

      现在要获取 html,您需要做的就是 ServletActionContext.getResponse().getWriter().toString() //This does not work out of box。要让 toString() 工作,您需要使用 ResponseWrapper - 这与在过滤器中获取结果 html 的方法相同。见-Programming Customized Requests and Responses

      在 struts 2 中修改生成的 html 的列表。这未经测试,但它是从我之前为自定义模板引擎编写的代码中提取的。我可能会在Custom template engine for struts2 中发布完整的描述

      public class DecoratorInterceptor implements Interceptor {
          public String intercept(ActionInvocation invocation) throws Exception {
             final ActionContext context = invocation.getInvocationContext ();
             HttpServletResponse responseParent = (HttpServletResponse) 
                                     context.get(ServletActionContext.HTTP_RESPONSE);
             CharResponseWrapper wrapper = new CharResponseWrapper(responseParent);
      
             ServletActionContext.setResponse(wrapper);
      
             //Actual Action called
             String result =  invocation.invoke();
      
             String htmlReturned = wrapper.toString();
             //play with htmlReturned ...
             String modifiedhtml = pushintoMemCache(htmlReturned );           
      
             CharArrayWriter car = new CharArrayWriter();           
             car.write(modifiedhtml );
      
             PrintWriter out = responseParent.getWriter();
              out.write(car.toString());
              out.flush();
         }
      
        @Override
          public void destroy() {
          // TODO Auto-generated method stub
      
          }
      
        @Override
          public void init() {
          // TODO Auto-generated method stub
      
          }
      
      }         
      

      【讨论】:

        【解决方案3】:

        阅读这篇文章 - http://struts.apache.org/2.0.6/docs/interceptors.html

        摘要:当您请求资源时 映射到一个“动作”, 框架调用 Action 对象。 但是,在执行 Action 之前, 调用可以被拦截 另一个对象。行动后 执行,调用可能是 再次被拦截。不出所料,我们 将这些对象称为“拦截器”。

        【讨论】:

        • 你所指的让我拦截(),即在它执行之前,或者添加一个 PreResultListener,根据文档,它说:“如果你需要使用最终结果对象在执行之前...”,这意味着 JSP 还没有被渲染。在操作的结果获取 JSP 并呈现它之后,我需要访问整个 生成的 HTML,而不是之前。考虑一下:客户端->请求->调度->动作->结果->JSP渲染-> HTML->我想要的客户端:客户端->请求->调度->动作->结果->JSP渲染->HTML- > 我的代码 -> 客户
        【解决方案4】:

        问题:如何确定视图是否已生成?您是否设置了请求标头或某种标志来确定是否已生成视图?

        您可以尝试抛出 MemCachedException 来指示是时候加载到内存缓存中了。您的拦截器代码可以读取

        try {
           return invocation.invoke();
        } catch (MemCachedException mce) {
           // Your code to upload to MemCache.
        } finally {
          // blah blah clean up.
        }
        

        【讨论】:

          【解决方案5】:

          在您的拦截器的intercept() 方法中,ActionInvocation 参数有一个getResult() 方法,该方法在Action 执行之前(即在您在intercept() 方法中调用invocation.invoke() 之前)返回null,并包含一个实现Result 之后。该对象应该为您提供一些访问所需数据的方法,但如何完成可能取决于实际使用的类。

          另请参阅my somewhat related question 以及我在弄清楚后发布的答案。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-04-19
            • 1970-01-01
            • 1970-01-01
            • 2012-03-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多