java - 从 Vaadin 8 应用程序生成 HTML 页面并在新窗口中打开
问题描述
在我的 Vaadin 8 Web 应用程序中,我希望用户能够通过单击按钮在另一个窗口中打开报告。内容将由 Vaadin 应用程序使用纯 HTML5 生成,而不是使用 Vaadin 小部件。
Vaadin 8 手册有一个页面处理浏览器窗口。它显示了使用一个BrowserWindowOpener
对象打开一个新窗口。但是该窗口包含一个 VaadinUI
子类,而我想生成自己的 HTML 内容。
传递数据库标识符值等信息的奖励积分。
解决方案
这是一个完整的示例应用程序,内置于 Vaadin 8.5.1。我们将 UUID 显示为 中的文本TextField
,并带有一个按钮,该按钮打开第二个窗口,显示一个网页,其中包含由我们的 Vaadin 应用程序生成的 HTML,而不使用 Vaadin 小部件或布局。该字段的 id 被传递到新窗口,在实际应用程序中可用于数据库查找。
如手册中该页所示,您确实需要使用 a BrowserWindowOpener
(或 a Link
)。由于浏览器常见的安全限制,这必须在用户单击按钮之前提前配置。BrowserWindowOpener
因此,我们必须提前配置对象并与按钮关联,而不是在按钮的单击侦听器中编写代码。
定义用户单击以生成报告的按钮。
Button webPageButton = new Button( "Generate Person report" );
定义要打开的新窗口的目的地,它应该使用哪个 URL 作为其网址。我们想回调我们的 Vaadin 应用程序。因此,在运行时获取此 Web 应用程序的 URL。在 Java Servlet 术语中,我们的 Web 应用程序的技术术语是“上下文”。所以我们向当前上下文询问它的 URL(路径)。
String servletPath = VaadinServlet.getCurrent().getServletContext().getContextPath(); // URL for this web app at runtime.
我们需要将该 URL 缩小到我们的报告,详细说明Person
要从数据库加载的单个对象。因此,我们发明person.html
为在我们的 URL 中请求的资源。
我们想在不调用 Vaadin 小部件的情况下请求动态生成的 HTML 页面,因此我们使用了ExternalResource
该类。
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.
有了这个Resource
对象,我们就可以定义BrowserWindowOpener
.
BrowserWindowOpener webPageOpener = new BrowserWindowOpener( resource );
让我们配置它的一些属性,比如要打开的窗口的标题。
webPageOpener.setWindowName( "Person ID: " + personUuid.getValue() ); // Set title of the new window to be opened.
我们希望传递要从数据库中检索的“人员”行的 ID,然后显示在我们生成的网页中。
将诸如此类的信息作为参数传递到 URL 上的查询字符串中的一种方法。所以我们 URL 的最后一部分看起来像person.html?person_id= f0e32ddc-18ed-432c-950b-eda3f3e4a80d
. 该值必须是文本的,因此我们使用代表UUID的 128 位的规范 36 字符十六进制字符串作为我们的数据库标识符。我们给这个值一个任意的键名,例如person_id
.
String param = "person_id";
webPageOpener.setParameter( param , personUuid.getValue() );
我们可以设置要打开的新窗口的大小。我们将使其在运行时与用户当前窗口的大小相同。我们将使窗口可调整大小,以便用户可以将其拉伸得更大或更小。我们希望以字符串描述的窗口特征结束,例如width=800,height=600,resizable
. 我们将在运行时插入该宽度和高度。
String windowFeaturesString = String.format( "width=%d,height=%d,resizable" , Page.getCurrent().getBrowserWindowWidth() , Page.getCurrent().getBrowserWindowHeight() ) ; // Same size as original window.
webPageOpener.setFeatures( windowFeaturesString ); // Example: "width=800,height=600,resizable".
我们完成了要打开的新窗口的配置。由于用户在事件侦听器中单击按钮时不能调用打开窗口,而其他行为通常会这样做,因此我们必须提前将打开器与按钮相关联。
webPageOpener.extend( webPageButton ); // Associate opener with button.
为了好玩,我们可以预览要被新窗口调用的 URL。在实际工作中,这里使用SLF4J和LogBack等日志框架。对于这个演示,我们转储到控制台。
System.out.println( "TRACE BrowserWindowOpener URL: " + webPageOpener.getUrl() );
好的,我们现在有一个带有开启器设置的按钮,用于请求生成基于 HTML 的报告。接下来我们必须生成该报告。为此,请告诉我们的 Vaadin 应用程序期待一个带有person.html
我们上面指定的 URL 的传入 URL。我们通过实现RequestHandler
接口来做到这一点。请参阅手册。
在我们的RequestHandler
工作中,我们做四件事:
- 检索在新窗口中打开的 URL 的查询字符串中作为参数传递的 UUID 的十六进制字符串。
- 从该十六进制字符串重构一个
UUID
对象。 - 将该
UUID
对象传递给生成要在此新窗口中显示的 HTML 的例程。 VaadinResponse
通过将 HTML 传递给通过 Java Servlet 技术传递回用户 Web 浏览器的对象,在新窗口中显示该 HTML 。
我们必须实例化我们的RequestHandler
实现,并将实例注册到用户的会话中,一个VaadinSession
对象。
VaadinSession.getCurrent().addRequestHandler(
new RequestHandler() {
@Override
public boolean handleRequest ( VaadinSession session ,
VaadinRequest request ,
VaadinResponse response )
throws IOException {
if ( "/panel.html".equals( request.getPathInfo() ) ) {
// Retrieve the hex-string of the UUID from the URL’s query string parameter.
String uuidString = request.getParameter( "person_id" ); // In real-work, validate the results here.
UUID uuid = UUID.fromString( uuidString ); // Reconstitute a `UUID` object from that hex-string. In real-work, validate the results here.
System.out.println( "UUID object reconstituted from string passed as parameter in query string of URL opened in new window: " + uuid );
// Build HTML.
String html = renderHtml( uuid );
// Send out the generated text as HTML, in UTF-8 character encoding.
response.setContentType( "text/html; charset=utf-8" );
response.getWriter().append( html );
return true; // We wrote a response
} else
return false; // No response was written
}
} );
填写该方法以生成 HTML。
// Generate the HTML to report on the details of a `person` from the database, given the UUID of that database row.
private String renderHtml ( UUID uuid ) {
String eol = "\n"; // End-of-line character(s) to use in the HTML.
StringBuilder html = new StringBuilder();
html.append( "<!DOCTYPE html>" ).append( eol );
html.append( "<html>" ).append( eol );
html.append( "<head>" ).append( eol );
html.append( "<title>Person</title>" ).append( eol );
html.append( "</head>" ).append( eol );
html.append( "<body style='color:DarkSlateGray' >" ).append( eol );
html.append( "<h1>Demo</h1>" ).append( eol );
html.append( "<p>This is a drill. This is only a drill.</p>" ).append( eol );
html.append( "<p>If this had been a real application, you would have seen some data.</p>" ).append( eol );
html.append( "<p>Person ID: " ).append( uuid.toString() ).append( ".</p>" ).append( eol );
html.append( "<p style='color:DimGray ; font-family: Pragmata Hack Menlo monospaced' >Report generated " ).append( Instant.now() ).append( ".</p>" ).append( eol );
html.append( "</body>" ).append( eol );
html.append( "</html>" ).append( eol );
String s = html.toString();
return s;
}
生成的 HTML 源代码如下所示:
<!DOCTYPE html>
<html>
<head>
<title>Person</title>
</head>
<body style='color:DarkSlateGray' >
<h1>Demo</h1>
<p>This is a drill. This is only a drill.</p>
<p>If this had been a real application, you would have seen some data.</p>
<p>Person ID: cc5e975b-2632-4c92-a1cb-b25085c60e60.</p>
<p style='color:DimGray ; font-family: Pragmata , Hack , Menlo , monospace' >Report generated 2018-08-05T02:33:13.028594Z.</p>
</body>
</html>
为了您的方便,这里是整个 Vaadin 8 应用程序,MyUI.java
文件的内容首先由 Vaadin Ltd 公司提供的最简单的 Maven 原型生成。
package com.basilbourque.example;
import javax.servlet.annotation.WebServlet;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.server.*;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import java.io.IOException;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.UUID;
/**
* This UI is the application entry point. A UI may either represent a browser window
* (or tab) or some part of an HTML page where a Vaadin application is embedded.
* <p>
* The UI is initialized using {@link #init(VaadinRequest)}. This method is intended to be
* overridden to add component to the user interface and initialize non-component functionality.
*/
@Theme ( "mytheme" )
public class MyUI extends UI {
@Override
protected void init ( VaadinRequest vaadinRequest ) {
final VerticalLayout layout = new VerticalLayout();
TextField personUuid = new TextField( "UUID of Person:" );
personUuid.setWidth( 22 , Unit.EM );
personUuid.setValue( UUID.randomUUID().toString() );
personUuid.setReadOnly( true );
Button webPageButton = new Button( "Generate Person report" );
webPageButton.setWidthUndefined();
webPageButton.addClickListener( e -> {
System.out.println( "Button clicked. " + ZonedDateTime.now() );
} );
// Configure web page opener object. Must be done *before* user clicks on button, not after.
String servletPath = VaadinServlet.getCurrent().getServletContext().getContextPath(); // URL for this web app at runtime.
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.
BrowserWindowOpener webPageOpener = new BrowserWindowOpener( resource );
webPageOpener.setWindowName( "Person ID: " + personUuid.getValue() ); // Set title of the new window to be opened.
String param = "person_id";
webPageOpener.setParameter( param , personUuid.getValue() );
String windowFeaturesString = String.format( "width=%d,height=%d,resizable" , Page.getCurrent().getBrowserWindowWidth() , Page.getCurrent().getBrowserWindowHeight() ); // Same size as original window.
webPageOpener.setFeatures( windowFeaturesString ); // Example: "width=800,height=600,resizable".
webPageOpener.extend( webPageButton ); // Connect opener with button.
System.out.println( "TRACE BrowserWindowOpener URL: " + webPageOpener.getUrl() );
layout.addComponents( personUuid , webPageButton );
setContent( layout );
// A request handler for generating some content
VaadinSession.getCurrent().addRequestHandler(
new RequestHandler() {
@Override
public boolean handleRequest ( VaadinSession session ,
VaadinRequest request ,
VaadinResponse response )
throws IOException {
if ( "/person.html".equals( request.getPathInfo() ) ) {
// Retrieve the hex-string of the UUID from the URL’s query string parameter.
String uuidString = request.getParameter( "person_id" ); // In real-work, validate the results here.
UUID uuid = UUID.fromString( uuidString ); // Reconstitute a `UUID` object from that hex-string. In real-work, validate the results here.
System.out.println( "UUID object reconstituted from string passed as parameter in query string of URL opened in new window: " + uuid );
// Build HTML.
String html = renderHtml( uuid );
// Send out the generated text as HTML, in UTF-8 character encoding.
response.setContentType( "text/html; charset=utf-8" );
response.getWriter().append( html );
return true; // We wrote a response
} else
return false; // No response was written
}
} );
}
// Generate the HTML to report on the details of a `person` from the database, given the UUID of that database row.
private String renderHtml ( UUID uuid ) {
String eol = "\n"; // End-of-line character(s) to use in the HTML.
StringBuilder html = new StringBuilder();
html.append( "<!DOCTYPE html>" ).append( eol );
html.append( "<html>" ).append( eol );
html.append( "<head>" ).append( eol );
html.append( "<title>Person</title>" ).append( eol );
html.append( "</head>" ).append( eol );
html.append( "<body style='color:DarkSlateGray' >" ).append( eol );
html.append( "<h1>Demo</h1>" ).append( eol );
html.append( "<p>This is a drill. This is only a drill.</p>" ).append( eol );
html.append( "<p>If this had been a real application, you would have seen some data.</p>" ).append( eol );
html.append( "<p>Person ID: " ).append( uuid.toString() ).append( ".</p>" ).append( eol );
html.append( "<p style='color:DimGray ; font-family: Pragmata , Hack , Menlo , monospace' >Report generated " ).append( Instant.now() ).append( ".</p>" ).append( eol );
html.append( "</body>" ).append( eol );
html.append( "</html>" ).append( eol );
String s = html.toString();
System.out.println( "\n\n" + s + "\n\n" );
return s;
}
@WebServlet ( urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true )
@VaadinServletConfiguration ( ui = MyUI.class, productionMode = false )
public static class MyUIServlet extends VaadinServlet {
}
}
推荐阅读
- c++ - 我想打印一个和零的模式
- java - 使用来自 ByteBuffer 的消息摘要计算校验和
- php - LdapRecord 没有从 Laravel-permissions 获得任何权限
- react-native - react-native,Android Freshchat isFreshchatNotification 未处理 Firebase 远程消息
- java - spring boot 2.4.0 或更高版本中的多文档属性和配置文件
- jmeter - 如何处理 JMeter 主从问题
- html - 如何在 1 个单个 div 中生成 *ngFor 循环项,而不是每个项目周围都有一个 div 容器
- amazon-web-services - 502 访问 API 网关时发生内部服务器错误
- mysql - 递归类别连接名称仅叶子mysql查询
- java - 如何关闭假装客户端请求?