【问题标题】:Wicket 1.5 and JSP/servlet wrappingWicket 1.5 和 JSP/servlet 包装
【发布时间】:2012-02-13 08:52:18
【问题描述】:

在我正在进行的项目中,我们希望从 Wicket 1.4 升级到 1.5。经过一些工作,我们得到了大部分工作正常。

但是,一件主要的事情还没有奏效。需要将旧的 JSP/servlet 包装到基于 Wicket 的新应用程序中,而旧的 1.4 方法不再适用。

1.4 中简化的 html 输出

<body>
    <div id="container">
        wrappedContentFromJsp
    </div>  
<body>

1.5 中简化的 html 输出

<body>
    wrappedContentFromJsp   
    <div id="container">        
    </div>  
<body>

因此,所有 JSP 内容都呈现在我们喜欢将其包装在其中的标记之外

包装魔法发生在我们内部的AbstractServletWrapperPanelWebMarkupContainer.onRender(MarkupStream markupStream) 覆盖中。但是,在 Wicket 1.5 中,我们无法调用 markupStream.next(),因为它不再提供。我还没有找到解决方法。

1.4 的工作代码,以示例面板实现作为参考:

public abstract class AbstractServletWrapperPanel extends Panel {

    public AbstractServletWrapperPanel(String id, final  String servletName, String tagId) {
        super(id);
        add(new WebMarkupContainer(tagId) {

            @Override
            protected void onRender(MarkupStream markupStream) {
                markupStream.next();
                try {
                    WebRequestCycle cycle = (WebRequestCycle) RequestCycle.get();
                    ServletRequest request = cycle.getWebRequest().getHttpServletRequest();
                    ServletResponse response = cycle.getWebResponse().getHttpServletResponse();
                    ServletContext context = ((WebApplication) Application.get()).getServletContext();
                    RequestDispatcher rd = context.getNamedDispatcher(servletName);
                    if (rd != null) {
                        rd.include(request, response);
                    } else {
                        // handling...
                    }
                } catch (Exception e) {
                    // handling...
                }
            }
        });
    }
}

//Impl
public class WrapperPanel extends AbstractServletWrapperPanel {
    private static final long serialVersionUID = 1L;

    public WrapperPanel(String id, final String servletName) {
        super(id, servletName, "wrappedContentId");
    }   
}

//WrapperPanel html
<body>
    <wicket:panel>
        <wicket:container wicket:id="wrappedContentId"/>
    </wicket:panel>
</body>

在 1.5 版本中,我通过 (HttpServletRequest)RequestCycle.get().getRequest().getContainerRequest()(HttpServletResponse)RequestCycle.get().getResponse().getContainerResponse() 获得请求和响应

然后我尝试:

  • 使用 1.5 中不再提供的不带 markupStream.next() 的 onRender()-magic
  • 将其移至onComponentTagBody(MarkupStream markupStream, ComponentTag tag)
    • 注意:要调用 onComponentTagBody(),我必须打开 wicket:container 标签&lt;wicket:container wicket:id="wrappedContentId"&gt;&lt;/wicket:container&gt;。我也尝试不调用markupStream.next(),因为该步骤是在Component.internalRenderComponent() 中执行的,就在onComponentTagBody 被调用之前。
  • 将其移至onComponentTag(ComponentTag tag)
  • 结合上面设置setRenderBodyOnly(true)WebMarkupContatiner.onInitialize()
  • 使用&lt;div&gt; 标签而不是wicket:container
  • 使用调试模式跟踪 1.5 的渲染过程。但是,我想我还是错过了新的 1.5 渲染组件方式的一些关键部分。

由于短期内无法将所有 JSP 功能迁移到 Wicket,所以目前这对我们来说是一个很好的选择。

作为参考,1.4 的做法与我在文章 jsp-and-wicket-sitting-in-a-treeWicket wiki 上找到的方法非常相似

任何解决此问题的帮助将不胜感激!

[编辑]
根据 TheStijn 的建议,我也尝试从 onRender() 调用 getAssociatedMarkupStream() 但这会引发以下错误:org.apache.wicket.markup.MarkupNotFoundException: Markup of type 'html' for component '... AbstractServletWrapperPanel$1' not found.

【问题讨论】:

    标签: jsp servlets wicket wicket-1.5 requestdispatcher


    【解决方案1】:

    以前没有使用过,但(Web)MarkupContainer 有一个方法getAssociatedMarkupStream 返回MarkupStream,这应该适合你。

    在 1.5 迁移指南中提到但不是很好:

    关于同一主题:onRender(MarkupStream) 已更改为 onRender();没有更多的标记流。您可以为每个组件获取一次 你通过 getMarkupStream() 调用了 render()。

    https://cwiki.apache.org/WICKET/migration-to-wicket-15.html#MigrationtoWicket1.5-Componentrendering

    【讨论】:

    • 感谢您的快速回复。我已经多次阅读指南的该部分,但从未找到getMarkupStream() 的方法:) 但是getAssociatedMarkupStream() 也不能很好地工作。我得到以下异常:org.apache.wicket.markup.MarkupNotFoundException: Markup of type 'html' for component '... AbstractServletWrapperPanel$1' not found. 我看到它调用MarkupContainer.getAssociatedMarkup() 然后MarkupFactory.get().getMarkup(this, false) 但是如果我从onRender() 显式调用getMarkup(),我找到标记没有问题。
    • 您是否已经尝试覆盖 onComponentTagBody 而不是 onRender?
    • 是的,如果不够清楚,抱歉。但是正如我在问题中所写的那样,我必须打开标签才能完成&lt;wicket:container&gt;&lt;/wicket:container&gt;。我将编辑问题并补充说我也尝试过不使用markupStream.next(),因为该步骤是在Component.internalRenderComponent() 中执行的,就在onComponentTagBody 被调用之前。
    • 通过一些邮件列表帮助制定了一个解决方案,您可以在我的回答中看到。无论如何,感谢您的帮助(还不能投票,为此要低代表...)
    【解决方案2】:

    在 Martin Grigorov 的大力帮助和指导下,我找到了解决方案。要按照到达那里的过程,请查看user's forum

    请注意,以下只是试图让它工作的原始输出,可能有一些更好的方法来“打包”它。因此,请接受它。

    //Stripped code for clarity
    
    @Override
    public void onComponentTagBody(MarkupStream markupStream, ComponentTag tag) {
    
     //Set up mock response and dispatch.   
     ServletContext context = WebApplication.get().getServletContext(); 
     ServletRequest request = (HttpServletRequest)RequestCycle.get().getRequest().getContainerRequest();
     MockResponse mockResponse = new MockResponse((HttpServletResponse)RequestCycle.get().getResponse().getContainerResponse());
     RequestDispatcher rd = context.getNamedDispatcher(aServletName);
     rd.include(request, mockResponse);
    
     //As in Wicket's Include.onComponentTagBody(MarkupStream markupStream, ComponentTag tag)
     replaceComponentTagBody(markupStream, tag, mockResponse.getOutput());
    }
    
    
    private static class MockResponse extends HttpServletResponseWrapper {    
     ServletOutputStream servletStream;
     ByteArrayOutputStream byteStream;
    
     public MockResponse(HttpServletResponse response) {
      super(response);      
      byteStream = new ByteArrayOutputStream();
      servletStream = new ServletOutputStream() {
    
        @Override
        public void write(int b) {
           byteStream.write(b);
         }
       };
     }
    
     @Override
     public ServletOutputStream getOutputStream() {
      return servletStream;
     }
    
     public String getOutput() {
        //NOTE: Remember to clean up IO in real usage...
        return byteStream.toString("UTF-8"); //Provide desired encoding
      }  
    }
    

    那我为什么不改用org.apache.wicket.protocol.http.mockMockHttpServletResponse 呢? 由于某种原因,getWriter()getOutputStream() 都没有被调用,但我稍后可能会进一步研究。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多