Wicket 1.5和JSP/servlet包装

Wicket 1.5和JSP/servlet包装,jsp,servlets,wicket,wicket-1.5,requestdispatcher,Jsp,Servlets,Wicket,Wicket 1.5,Requestdispatcher,在我参与的项目中,我们希望从Wicket 1.4升级到1.5。经过一段时间的工作,我们大部分事情都进展顺利 然而,有一件大事还没有发生。需要将旧的JSP/servlet包装到新的基于Wicket的应用程序中,而旧的1.4方法不再有效 1.4中的简化html输出 <body> <div id="container"> wrappedContentFromJsp </div> <body> 在1.5版本中,我通过(

在我参与的项目中,我们希望从Wicket 1.4升级到1.5。经过一段时间的工作,我们大部分事情都进展顺利

然而,有一件大事还没有发生。需要将旧的JSP/servlet包装到新的基于Wicket的应用程序中,而旧的1.4方法不再有效

1.4中的简化html输出

<body>
    <div id="container">
        wrappedContentFromJsp
    </div>  
<body>
在1.5版本中,我通过
(HttpServletRequest)RequestCycle.get().getRequest().getContainerRequest()
(HttpServletResponse)RequestCycle.get().getResponse().getContainerResponse()

然后我试着:

  • 使用onRender()-magic而不使用1.5中不再提供的
    markupStream.next()
  • 将其移动到
    onComponentTagBody(标记上游标记上游,组件标记标记)
    • 注意:要调用onComponentTagBody(),我必须打开wicket:container标记
      。我还尝试了不调用
      markupStream.next()
      ,因为在调用
      onComponentTagBody
      之前,该步骤在
      Component.internalRenderComponent()中执行
  • 将其移动到
    onComponentTag(ComponentTag标签)
  • 结合上面的设置,在
    WebMarkupContatiner.onInitialize()中设置
    setRenderBodyOnly(true)
  • 使用
    标签而不是
    wicket:container
  • 使用调试模式跟踪1.5的渲染过程。但是,我想我还是遗漏了新的1.5渲染组件方法的一些关键部分
由于不可能在短期内将所有JSP功能迁移到Wicket,因此目前这对我们来说是一个阻碍

作为参考,1.4实现这一点的方法与我在文章和

如果您能帮助解决此问题,我们将不胜感激

[编辑]

根据TIJN的建议,我还尝试从
onRender()
调用
getAssociatedMarkupStream()
,但这会引发以下错误:
org.apache.wicket.markup.MarkupNotFoundException:组件的“html”类型标记。。。AbstractServletWrapperPanel$1'未找到。

以前未使用过此选项,但
(Web)MarkupContainer
有一个方法
getAssociatedMarkupStream
,该方法返回
MarkupStream
,应该适合您

1.5版迁移指南中提到了这一点,但不是很好:

关于同一主题:onRender(MarkupStream)已更改为 onRender();再也没有了。每个组件都可以获得一次 您通过getMarkupStream()调用了render()


在马丁·格里戈罗夫的大力帮助和指点下,我找到了解决这个问题的办法。要了解到达那里的过程,请看

请注意,以下只是尝试让它工作的原始输出,可能有更好的方法“打包”它。所以,照原样去做吧

//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.mockhttpservletresponse

由于某种原因,
getWriter()
getOutputStream()
都没有被调用,但我可能会在以后进一步研究。

感谢您的快速回复。我已经阅读了几次指南的这一部分,但是没有找到方法
getMarkupStream()
:)但是
getAssociatedMarkupStream()
也不能很好地工作。我得到以下异常:
org.apache.wicket.markup.MarkupNotFoundException:组件“”的类型为“html”的标记。。。AbstractServletWrapperPanel$1'未找到。
我看到它调用
MarkupContainer.getAssociatedMarkup()
然后
MarkupFactory.get().getMarkup(this,false)
,但是如果从
onRender()调用
getMarkup()
,我就可以找到标记
显式。您是否已尝试覆盖
onComponentTagBody
而不是onRender?是的,如果不够清楚,很抱歉。但是,正如我在问题中所写的那样,我必须打开标签才能完成这项任务。我将编辑该问题,并添加我在调用
onComponentTagBody
之前在
Component.internalRenderComponent()
中执行该步骤时也尝试了不使用
markupStream.next()
。通过邮件列表帮助制定了解决方案,如您在我的回答中所见。无论如何,谢谢你的帮助(现在还不能投票支持,因为代表率低…)
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>
//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
  }  
}