将信息传递给正在使用 Vaadin 8 中的 BrowserWindowOpener 打开的新网络浏览器 window/tab

Pass information to new web-browser window/tab being opened with BrowserWindowOpener in Vaadin 8

在 Vaadin 8 中,我们可以让用户通过单击与 BrowserWindowOpener. As discussed in the manual 相关联的按钮在其网络浏览器中打开一个新的 tab/window,一个新的 UI 是代表我们实例化。我们传递的只是一个 .class 对象,我们的 UI 子 class 的 class 将被实例化以显示在新的 window/tab 中。例如:

BrowserWindowOpener opener = new BrowserWindowOpener( PersonDetailUI.class );

这对我有用。我的问题是:如何将一些信息传递给新 window/tab 中的新 UI 对象?

例如,我可能需要传递:


我明白了I asked about this same issue for Vaadin 7。将此视为 Vaadin 8 问题的更新版本。唯一的答案推测是将参数添加到新 window 的 URI。但这将我限制在一小段文字中。我更喜欢传递智能对象而不是哑字符串。

基本上可以使用三种方法,以及这些方法的组合

  1. 使用 URI 参数。正如您提到的,这仅限于 String 类型的数据。

    • 您可以阅读 UI 中的 URI 片段,例如String uriFragment = Page.getCurrent().getUriFragment();
    • 您可以使用 VaadinRequest.getParameter() 读取 URI 参数,VaadinRequest 在 main UI
    • 的 init(...) 中作为参数给出
  2. UI 在不同的浏览器选项卡中共享同一个 Vaadin 会话。这提供了一些工具,即

    • 您可以使用会话属性,即 VaadinSession.getCurrent().getAttribute(…)VaadinSession.getCurrent().setAttribute(…)

    • 如果您使用 CDI 或 Spring,您可以注入/自动装配 @VaadinSessionScoped bean。然后将该实例绑定到 Session 并因此在选项卡之间共享。

  3. 从数据库中读取数据(可能使用1.and/or2.作为键的帮助)

Lund 提到将 URI 参数传递给正在打开的新 window。

示例应用程序,将 URI 参数传递给新 window

这是 Vaadin 8.5.0 中的一个简单的小型演示应用程序,用于展示该技术。

我们从假装从数据库中检索的三只猫开始。每次用户选择一只猫时,我们都会得到猫的标识符,一个 UUID 对象。我们生成该 UUID 的规范 32 字符十六进制字符串表示。我们将其指定为要与参数键 cat_id 一起传递的参数值。我们通过调用 BrowserWindowOpener::setParameter.

来指定该参数

请注意,我们在 Grid 列出的猫中选择一个项目时执行此操作。由于浏览器打开 windows 的限制,BrowserWindowOpener 必须在 用户单击其按钮之前配置 。据我所知,我们无法 运行 代码响应按钮点击。

新浏览器 window 填充了 UI 的自动实例化子 class。在这种情况下 CatUI 就是我们写的。在 CatUI 中,我们获取 URI 参数,提取表示 UUID 的字符串,重新创建 UUID 对象,然后将其传递给我们假装的数据库服务以获取 cat题。然后用 Cat 对象值填充布局的字段。我们不会为 cat-to-layout 的数据绑定而烦恼,因为这不是本演示的重点。

警告:这只是一个演示,忽略了与通过 URI 参数将信息传递给新 window 的问题没有直接关系的问题。例如,并发的关键问题在这里被忽略,但不会在实际工作中。

此演示包含四个 class 个文件,全部粘贴在下方。

  • MainUI(应用启动时默认打开)
  • CatUI(用户点击按钮时打开)
  • Cat(业务对象,具有 nameid 属性)
  • DatabaseService(伪装猫记录库)

MainUI

package com.basilbourque.example;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.server.BrowserWindowOpener;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Button;
import com.vaadin.ui.Grid;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

import javax.servlet.annotation.WebServlet;
import java.util.List;
import java.util.Set;
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 MainUI extends UI {
    private Grid< Cat > grid;
    private Button button;

    @Override
    protected void init ( VaadinRequest vaadinRequest ) {
        // Configure button to open now browser window/tab.
        this.button = new Button( "Open in new window" );
        BrowserWindowOpener opener = new BrowserWindowOpener( CatUI.class );
        opener.setFeatures( "height=300,width=500,resizable" );
        opener.extend( this.button );
        opener.setParameter( "cat_id" , new UUID(0,0).toString());  // Send nil UUID (all zeros) if nothing selected.
        System.out.println( "BWO URL: " + opener.getUrl() );
        this.button.setEnabled( false );

        this.grid = new Grid<>( Cat.class );
        this.grid.setCaption( "Cats" );
        List<Cat> cats = new DatabaseService().fetchAllCats() ;
        this.grid.setItems( cats  );
        // Every time the user selects a cat in the Grid, assign that cat’s ID to our `BrowserWindowOpener`. This way our button is always prepared to open a window for the selected cat.
        this.grid.addSelectionListener( event -> {
            Set< Cat > selectedCats = event.getAllSelectedItems();
            this.button.setEnabled( selectedCats.size() > 0 );
            if ( selectedCats.size() > 0 ) {  // If the user selected an item.
                Cat cat = selectedCats.stream().findFirst().get();
                opener.setParameter( "cat_id" , cat.getId().toString() );  // A UUID’s canonical presentation is as a 36-character hexadecimal string in five groups with HYPHEN-MINUS as delimiter.
            } else {
                opener.setParameter( "cat_id" , new UUID(0,0).toString());  // Send nil UUID (all zeros) if nothing selected.
            }
            System.out.println( "BWO URL: " + opener.getUrl() );
        } );
        this.grid.select( cats.stream().findFirst().get() ); // Select first item arbitrarily, to provoke the grid’s selection-listener above to fire.

        button.addClickListener( e -> {
            System.out.println( "BASIL opening now window" );
        } );

        final VerticalLayout layout = new VerticalLayout();
        layout.addComponents( this.grid , button );
        setContent( layout );
    }

    @WebServlet ( urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true )
    @VaadinServletConfiguration ( ui = MainUI.class, productionMode = false )
    public static class MyUIServlet extends VaadinServlet {
    }
}

CatUI

package com.basilbourque.example;

import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.*;

import java.util.Optional;
import java.util.UUID;

public class CatUI extends UI {
    private Cat cat = null;

    @Override
    protected void init ( VaadinRequest vaadinRequest ) {
        // Retrieve a parameter from the URI of this UI/window.
        String catUuidString = vaadinRequest.getParameter( "cat_id" );  // In the URI key-value parameters, "cat_id" is our key, and a UUID’s hex string is the expected value.
        if ( null == catUuidString ) {  // If we did not receive the UUID-string parameter we expected.
            this.setContent( this.buildLayoutForNoCat( null ) );
            return;
        }
        UUID uuid = UUID.fromString( catUuidString );  // Rehydrate the `UUID` from our passed hex string representing the UUID’s value.
        Optional< Cat > cat = new DatabaseService().fetchCat( uuid );
        if ( cat.isPresent() ) {  // NULL check.
            System.out.println( "uuidString: " + uuid + " and cat: " + cat.get() );
            this.setContent( this.buildLayoutForCat( cat.get() ) );  // Retrieve the `Cat` object from our `Optional< Cat >` object by calling `get()` only after checking for NULL.
            return;
        } else {  // Failed to find cat.
            this.setContent( this.buildLayoutForNoCat( uuid ) );
            return;
        }
    }

    private Layout buildLayoutForCat ( Cat cat ) {
        this.cat = cat ;
        this.getPage().setTitle( "Cat details" );

        // Have some content for it
        TextField name = new TextField( "Name: " );
        name.setWidth( 100 , Unit.PERCENTAGE );
        name.setValue( this.cat.getName() );

        TextField id = new TextField( "Id: " );
        id.setWidth( 100 , Unit.PERCENTAGE );
        id.setValue( this.cat.getId().toString() );

        VerticalLayout layout = new VerticalLayout();
        layout.addComponent( name );
        layout.addComponent( id );
        return layout;
    }

    private Layout buildLayoutForNoCat ( UUID uuid ) {
        VerticalLayout layout = new VerticalLayout();
        String message = "No cat found for the id: " + uuid;
        Label label = new Label( message );
        layout.addComponentsAndExpand( label );
        return layout;
    }
}

Cat

package com.basilbourque.example;

import java.util.UUID;

public class Cat {
    private UUID id;
    private String name;

    public Cat ( UUID id , String name ) {
        this.id = id;
        this.name = name;
    }

    public UUID getId () {
        return id;
    }

    public void setId ( UUID id ) {
        this.id = id;
    }

    public String getName () {
        return name;
    }

    public void setName ( String name ) {
        this.name = name;
    }

    // Override `Object`.

    @Override
    public String toString () {
        return "Cat{ " +
                "id=" + id +
                ", name='" + name + '\'' +
                " }";
    }


}

DatabaseService

package com.basilbourque.example;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

// Pretending to be our gateway to a database.
public class DatabaseService {
    static private List< Cat > cats;

    {
        DatabaseService.cats = List.of(  // Produces an unmodifiable list. (A new feature in Java 9 and later.)
                new Cat( UUID.fromString( "adf5c1a0-912e-11e8-9eb6-529269fb1459" ) , "Fluffy" ) ,
                new Cat( UUID.fromString( "d37401c6-912e-11e8-9eb6-529269fb1459" ) , "Spot" ) ,
                new Cat( UUID.fromString( "de29b6d8-912e-11e8-9eb6-529269fb1459" ) , "Lilly Mae" )
        );
    }

    public List< Cat > fetchAllCats () {
        return new ArrayList<>( DatabaseService.cats );  // Copy the list, then return.
    }

    public Optional< Cat > fetchCat ( UUID uuid ) {
        return DatabaseService.cats.stream().filter( cat -> cat.getId().equals( uuid ) ).findFirst();
    }

    public static void main ( String[] args ) {
        Optional< Cat > cat = new DatabaseService().fetchCat(  UUID.fromString( "de29b6d8-912e-11e8-9eb6-529269fb1459" ) );
        if ( cat.isPresent() ) {
            System.out.println( "cat: " + cat.get() );
        } else {
            System.out.println( "No cat found." );
        }
    }
}