从 Vaadin 8 应用程序生成 HTML 页面并在新窗口中打开

Bas*_*que 5 html java window vaadin vaadin8

在我的 Vaadin 8 Web 应用程序中,我希望用户能够通过单击按钮在另一个窗口中打开报告。内容将由 Vaadin 应用程序使用纯 HTML5 生成,而不是使用 Vaadin 小部件。

Vaadin 8 手册有一个页面处理浏览器窗口。它显示了使用BrowserWindowOpener对象打开一个新窗口。但是该窗口包含一个 VaadinUI子类,而我想生成自己的 HTML 内容。

传递信息(例如数据库标识符值)的奖励积分。

Bas*_*que 2

这是在 Vaadin 8.5.1 中构建的完整示例应用程序。我们将 UUID 作为文本呈现在TextField,并使用一个按钮打开第二个窗口,该窗口显示一个网页,其中包含由我们的 Vaadin 应用程序生成的 HTML,而无需使用 Vaadin 小部件或布局。该字段中的 id 会传递到新窗口,在真实的应用程序中,该窗口可用于数据库查找。

\n\n

在此输入图像描述

\n\n

在此输入图像描述

\n\n

如手册中该页所示,您确实需要使用 a BrowserWindowOpener(或 a Link)。由于浏览器常见的安全限制,必须在用户单击按钮之前提前进行配置。BrowserWindowOpener因此,我们必须提前配置该对象,并与按钮关联,而不是在按钮\xe2\x80\x99s 单击侦听器中编写代码。

\n\n

定义用户单击以生成报告的按钮。

\n\n
Button webPageButton = new Button( "Generate Person report" );\n
Run Code Online (Sandbox Code Playgroud)\n\n

定义要打开的新窗口的目的地,以及应使用什么 URL 作为其网址。我们想要回拨我们的 Vaadin 应用程序。因此,在运行时获取此 Web 应用程序的 URL。Java Servlet 术语中我们的 Web 应用程序的技术术语是 \xe2\x80\x9ccontext\xe2\x80\x9d。因此,我们向当前上下文询问其 URL(路径)。

\n\n
String servletPath = VaadinServlet.getCurrent().getServletContext().getContextPath(); // URL for this web app at runtime.\n
Run Code Online (Sandbox Code Playgroud)\n\n

Person我们需要将该 URL 缩小到我们的报告,详细说明要从数据库加载的单个对象。因此,我们将其发明person.html为 URL 中请求的资源。

\n\n

我们希望在不调用 Vaadin 小部件的情况下动态生成 HTML 页面,因此我们使用该类ExternalResource

\n\n
Resource resource = new ExternalResource( servletPath + "/person.html" );  // Defining an external resource as a URL that is not really so external -- will call back into this same web app.\n
Run Code Online (Sandbox Code Playgroud)\n\n

有了该Resource对象,我们就可以定义BrowserWindowOpener.

\n\n
BrowserWindowOpener webPageOpener = new BrowserWindowOpener( resource );\n
Run Code Online (Sandbox Code Playgroud)\n\n

让\xe2\x80\x99s配置它的一些属性,比如要打开的窗口的标题。

\n\n
webPageOpener.setWindowName( "Person ID: " + personUuid.getValue() );  // Set title of the new window to be opened.\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们希望传递 \xe2\x80\x9cperson\xe2\x80\x9d 行的 ID,以便从数据库中检索,然后显示在生成的网页中。

\n\n

将此类信息作为URL 上的查询字符串中的参数传递的一种方法。所以我们 URL 的最后一部分看起来像person.html?person_id= f0e32ddc-18ed-432c-950b-eda3f3e4a80d该值必须是文本值,因此我们使用表示 128 位UUID的规范 36 字符十六进制字符串作为数据库标识符。我们给这个值一个任意的键名,例如person_id

\n\n
String param = "person_id";\nwebPageOpener.setParameter( param , personUuid.getValue() );\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们可以设置新打开窗口的大小。我们将使其在运行时与 user\xe2\x80\x99s 当前窗口的大小相同。我们将调整窗口的大小,以便用户可以将其拉伸得更大或更小。我们希望最终得到用字符串描述的窗口功能,例如width=800,height=600,resizable。我们将在运行时插入该宽度和高度。

\n\n
String windowFeaturesString = String.format( "width=%d,height=%d,resizable" , Page.getCurrent().getBrowserWindowWidth() , Page.getCurrent().getBrowserWindowHeight() ) ; // Same size as original window.\nwebPageOpener.setFeatures( windowFeaturesString );  // Example: "width=800,height=600,resizable".\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们已经完成了要打开的新窗口的配置。由于用户在事件侦听器中单击按钮无法调用窗口打开,而通常对其他行为可能会这样做,因此我们必须提前将打开器与按钮关联起来。

\n\n
webPageOpener.extend( webPageButton ); // Associate opener with button.\n
Run Code Online (Sandbox Code Playgroud)\n\n

为了好玩,我们可以预览新窗口要调用的 URL。实际工作中,这里使用SLF4JLogBack等日志框架。对于这个演示,我们转储到控制台。

\n\n
System.out.println( "TRACE BrowserWindowOpener URL: " + webPageOpener.getUrl() );\n
Run Code Online (Sandbox Code Playgroud)\n\n

很好,我们现在有一个带有开启器的按钮,用于要求生成基于 HTML 的报告。接下来我们必须生成该报告。为此,请告诉我们的 Vaadin 应用程序期待传入的 URL 与person.html我们上面指定的 URL 相同。我们通过实现RequestHandler接口来做到这一点。请参阅手册

\n\n

在我们的工作中,RequestHandler我们做了四件事:

\n\n
    \n
  1. 检索在新窗口中打开的 URL 的查询字符串中作为参数传递的 UUID 的十六进制字符串。
  2. \n
  3. UUID从该十六进制字符串重建一个对象。
  4. \n
  5. 将该UUID对象传递给生成要在该新窗口中显示的 HTML 的例程。
  6. \n
  7. 通过将 HTML 传递给对象来在新窗口中显示该 HTML,VaadinResponse该对象通过 Java Servlet 技术传递回用户\xe2\x80\x99s Web 浏览器。
  8. \n
\n\n

我们必须实例化我们的RequestHandler实现,并将实例注册到 user\xe2\x80\x99s 会话(一个VaadinSession对象)。

\n\n
VaadinSession.getCurrent().addRequestHandler(\n        new RequestHandler() {\n            @Override\n            public boolean handleRequest ( VaadinSession session ,\n                                           VaadinRequest request ,\n                                           VaadinResponse response )\n                    throws IOException {\n                if ( "/panel.html".equals( request.getPathInfo() ) ) {\n                    // Retrieve the hex-string of the UUID from the URL\xe2\x80\x99s query string parameter.\n                    String uuidString = request.getParameter( "person_id" );  // In real-work, validate the results here.\n                    UUID uuid = UUID.fromString( uuidString ); // Reconstitute a `UUID` object from that hex-string. In real-work, validate the results here.\n                    System.out.println( "UUID object reconstituted from string passed as parameter in query string of URL opened in new window: " + uuid );\n                    // Build HTML.\n                    String html = renderHtml( uuid );\n                    // Send out the generated text as HTML, in UTF-8 character encoding.\n                    response.setContentType( "text/html; charset=utf-8" );\n                    response.getWriter().append( html );\n                    return true; // We wrote a response\n                } else\n                    return false; // No response was written\n            }\n        } );\n
Run Code Online (Sandbox Code Playgroud)\n\n

填写该方法以生成 HTML。

\n\n
// Generate the HTML to report on the details of a `person` from the database, given the UUID of that database row.\nprivate String renderHtml ( UUID uuid ) {\n    String eol = "\\n"; // End-of-line character(s) to use in the HTML.\n    StringBuilder html = new StringBuilder();\n    html.append( "<!DOCTYPE html>" ).append( eol );\n    html.append( "<html>" ).append( eol );\n    html.append( "<head>" ).append( eol );\n    html.append( "<title>Person</title>" ).append( eol );\n    html.append( "</head>" ).append( eol );\n    html.append( "<body style=\'color:DarkSlateGray\' >" ).append( eol );\n    html.append( "<h1>Demo</h1>" ).append( eol );\n    html.append( "<p>This is a drill. This is only a drill.</p>" ).append( eol );\n    html.append( "<p>If this had been a real application, you would have seen some data.</p>" ).append( eol );\n    html.append( "<p>Person ID: " ).append( uuid.toString() ).append( ".</p>" ).append( eol );\n    html.append( "<p style=\'color:DimGray ; font-family: Pragmata Hack Menlo monospaced\' >Report generated " ).append( Instant.now() ).append( ".</p>" ).append( eol );\n    html.append( "</body>" ).append( eol );\n    html.append( "</html>" ).append( eol );\n    String s = html.toString();\n    return s;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

生成的 HTML 源代码如下所示:

\n\n
Button webPageButton = new Button( "Generate Person report" );\n
Run Code Online (Sandbox Code Playgroud)\n\n

为了您的方便,这里是整个 Vaadin 8 应用程序,文件的内容MyUI.java首先由 Vaadin Ltd 公司提供的最简单的 Maven 原型生成。

\n\n
package com.basilbourque.example;\n\nimport javax.servlet.annotation.WebServlet;\n\nimport com.vaadin.annotations.Theme;\nimport com.vaadin.annotations.VaadinServletConfiguration;\nimport com.vaadin.server.*;\nimport com.vaadin.ui.Button;\nimport com.vaadin.ui.Label;\nimport com.vaadin.ui.TextField;\nimport com.vaadin.ui.UI;\nimport com.vaadin.ui.VerticalLayout;\n\nimport java.io.IOException;\nimport java.time.Instant;\nimport java.time.ZonedDateTime;\nimport java.util.UUID;\n\n/**\n * This UI is the application entry point. A UI may either represent a browser window\n * (or tab) or some part of an HTML page where a Vaadin application is embedded.\n * <p>\n * The UI is initialized using {@link #init(VaadinRequest)}. This method is intended to be\n * overridden to add component to the user interface and initialize non-component functionality.\n */\n@Theme ( "mytheme" )\npublic class MyUI extends UI {\n\n    @Override\n    protected void init ( VaadinRequest vaadinRequest ) {\n        final VerticalLayout layout = new VerticalLayout();\n\n        TextField personUuid = new TextField( "UUID of Person:" );\n        personUuid.setWidth( 22 , Unit.EM );\n        personUuid.setValue( UUID.randomUUID().toString() );\n        personUuid.setReadOnly( true );\n\n        Button webPageButton = new Button( "Generate Person report" );\n        webPageButton.setWidthUndefined();\n        webPageButton.addClickListener( e -> {\n            System.out.println( "Button clicked. " + ZonedDateTime.now() );\n        } );\n\n        // Configure web page opener object. Must be done *before* user clicks on button, not after.\n        String servletPath = VaadinServlet.getCurrent().getServletContext().getContextPath(); // URL for this web app at runtime.\n        Resource resource = new ExternalResource( servletPath + "/person.html" );  // Defining an external resource as a URL that is not really so external -- will call back into this same web app.\n        BrowserWindowOpener webPageOpener = new BrowserWindowOpener( resource );\n        webPageOpener.setWindowName( "Person ID: " + personUuid.getValue() );  // Set title of the new window to be opened.\n        String param = "person_id";\n        webPageOpener.setParameter( param , personUuid.getValue() );\n        String windowFeaturesString = String.format( "width=%d,height=%d,resizable" , Page.getCurrent().getBrowserWindowWidth() , Page.getCurrent().getBrowserWindowHeight() ); // Same size as original window.\n        webPageOpener.setFeatures( windowFeaturesString );  // Example: "width=800,height=600,resizable".\n        webPageOpener.extend( webPageButton ); // Connect opener with button.\n        System.out.println( "TRACE BrowserWindowOpener URL: " + webPageOpener.getUrl() );\n\n        layout.addComponents( personUuid , webPageButton );\n        setContent( layout );\n\n        // A request handler for generating some content\n        VaadinSession.getCurrent().addRequestHandler(\n                new RequestHandler() {\n                    @Override\n                    public boolean handleRequest ( VaadinSession session ,\n                                                   VaadinRequest request ,\n                                                   VaadinResponse response )\n                            throws IOException {\n                        if ( "/person.html".equals( request.getPathInfo() ) ) {\n                            // Retrieve the hex-string of the UUID from the URL\xe2\x80\x99s query string parameter.\n                            String uuidString = request.getParameter( "person_id" );  // In real-work, validate the results here.\n                            UUID uuid = UUID.fromString( uuidString ); // Reconstitute a `UUID` object from that hex-string. In real-work, validate the results here.\n                            System.out.println( "UUID object reconstituted from string passed as parameter in query string of URL opened in new window: " + uuid );\n                            // Build HTML.\n                            String html = renderHtml( uuid );\n                            // Send out the generated text as HTML, in UTF-8 character encoding.\n                            response.setContentType( "text/html; charset=utf-8" );\n                            response.getWriter().append( html );\n                            return true; // We wrote a response\n                        } else\n                            return false; // No response was written\n                    }\n                } );\n    }\n\n    // Generate the HTML to report on the details of a `person` from the database, given the UUID of that database row.\n    private String renderHtml ( UUID uuid ) {\n        String eol = "\\n"; // End-of-line character(s) to use in the HTML.\n        StringBuilder html = new StringBuilder();\n        html.append( "<!DOCTYPE html>" ).append( eol );\n        html.append( "<html>" ).append( eol );\n        html.append( "<head>" ).append( eol );\n        html.append( "<title>Person</title>" ).append( eol );\n        html.append( "</head>" ).append( eol );\n        html.append( "<body style=\'color:DarkSlateGray\' >" ).append( eol );\n        html.append( "<h1>Demo</h1>" ).append( eol );\n        html.append( "<p>This is a drill. This is only a drill.</p>" ).append( eol );\n        html.append( "<p>If this had been a real application, you would have seen some data.</p>" ).append( eol );\n        html.append( "<p>Person ID: " ).append( uuid.toString() ).append( ".</p>" ).append( eol );\n        html.append( "<p style=\'color:DimGray ; font-family: Pragmata , Hack , Menlo , monospace\' >Report generated " ).append( Instant.now() ).append( ".</p>" ).append( eol );\n        html.append( "</body>" ).append( eol );\n        html.append( "</html>" ).append( eol );\n        String s = html.toString();\n        System.out.println( "\\n\\n" + s + "\\n\\n" );\n        return s;\n    }\n\n    @WebServlet ( urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true )\n    @VaadinServletConfiguration ( ui = MyUI.class, productionMode = false )\n    public static class MyUIServlet extends VaadinServlet {\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n