Wicket 1.5和JSP/servlet包装
在我参与的项目中,我们希望从Wicket 1.4升级到1.5。经过一段时间的工作,我们大部分事情都进展顺利 然而,有一件大事还没有发生。需要将旧的JSP/servlet包装到新的基于Wicket的应用程序中,而旧的1.4方法不再有效 1.4中的简化html输出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版本中,我通过(
<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()中执行
- 注意:要调用onComponentTagBody(),我必须打开wicket:container标记
- 将其移动到
onComponentTag(ComponentTag标签)
- 结合上面的设置,在
WebMarkupContatiner.onInitialize()中设置
setRenderBodyOnly(true)
- 使用
标签而不是wicket:container
- 使用调试模式跟踪1.5的渲染过程。但是,我想我还是遗漏了新的1.5渲染组件方法的一些关键部分李>
根据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
}
}