1

在我正在进行的项目中,我们希望从 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()and获取请求和响应(HttpServletResponse)RequestCycle.get().getResponse().getContainerResponse()

然后我尝试:

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

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

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

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

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

4

2 回答 2

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

于 2012-02-13T13:11:32.057 回答
1

在 Martin Grigorov 的大力帮助和指导下,我找到了解决方案。要遵循到达那里的过程,请查看用户论坛

请注意,以下只是试图让它工作的原始输出,可能有一些更好的方法来“打包”它。所以把它当作它是什么。

//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()调用,但我稍后可能会进一步研究。

于 2012-02-23T16:01:45.097 回答