当我在前一个用户界面中点击链接后,在创建的新用户界面中点击按钮时,为什么会出现“通信问题”?

4

当我尝试做以下操作时,我遇到了一个奇怪的“通信问题” Vaadin 错误:

我有两个 UI,第一个 UI 有一个指向另一个 UI 的链接,以下是代码:

public class MenuUI extends UI {

    @WebServlet(value = "/*", asyncSupported = true)
    @VaadinServletConfiguration(productionMode = false, ui = MenuUI.class)
    public static class Servlet extends VaadinServlet {
    }

    @Override
    protected void init(VaadinRequest request) {
        final VerticalLayout layout = new VerticalLayout();
        layout.setMargin(true);
        layout.setSpacing(true);
        setContent(layout);

        MenuBar menuBar = new MenuBar();

        MenuItem submenu1 = menuBar.addItem("Submenu 1", null);
        MenuItem submenu2 = menuBar.addItem("Submenu 2", null);

        submenu1.addItem("Option 1", null);
        submenu1.addItem("Option 2", null);

        submenu2.addItem("Option 3", null);
        submenu2.addItem("Option 4", new Command() {
            @Override
            public void menuSelected(MenuItem selectedItem) {
                Notification.show("That was option 4");
            }
        });
        layout.addComponent(menuBar);

        Link link = new Link("Go to ShortcutKeys",
                             new ExternalResource(Page.getCurrent().getLocation().toString() + "Shortcut"));
        link.setTargetName("_blank");
        layout.addComponent(link);
    }

}

这个 UI 显示的结果如下: enter image description here 当我点击链接时,会初始化一个新的 UI,这是新 UI 的代码:
public class ShortcutUI extends UI {

    @WebServlet(value = "/Shortcut", asyncSupported = true)
    @VaadinServletConfiguration(productionMode = false, ui = ShortcutUI.class)
    public static class Servlet extends VaadinServlet {
    }

    @Override
    protected void init(VaadinRequest request) {
        final VerticalLayout layout = new VerticalLayout();
        layout.setMargin(true);
        layout.setSpacing(true);
        setContent(layout);

        final TextField tf = new TextField("Your data:");
        layout.addComponent(tf);

        Button button = new Button("Send data (ENTER)");
        button.setClickShortcut(KeyCode.ENTER, ModifierKey.SHIFT);

        button.addClickListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                layout.addComponent(new Label(tf.getValue()));
                tf.setValue("");
                tf.focus();
            }
        });

        layout.addComponent(button);
    }

这将导致以下结果:
在这里我输入一些文本,然后当我点击“发送数据”按钮时,我会得到以下内容:
为什么会出现通信问题?如果UI不是从点击的链接创建的,例如如果我将ShortcutUI init()内容放在MenuUI中,就像以下类中一样:
public class MenuUI extends UI {

    @WebServlet(value = "/*", asyncSupported = true)
    @VaadinServletConfiguration(productionMode = false, ui = MenuUI.class)
    public static class Servlet extends VaadinServlet {
    }

    @Override
    protected void init(VaadinRequest request) {
        final VerticalLayout layout = new VerticalLayout();
        layout.setMargin(true);
        layout.setSpacing(true);
        setContent(layout);

        MenuBar menuBar = new MenuBar();

        MenuItem submenu1 = menuBar.addItem("Submenu 1", null);
        MenuItem submenu2 = menuBar.addItem("Submenu 2", null);

        submenu1.addItem("Option 1", null);
        submenu1.addItem("Option 2", null);

        submenu2.addItem("Option 3", null);
        submenu2.addItem("Option 4", new Command() {
            @Override
            public void menuSelected(MenuItem selectedItem) {
                Notification.show("That was option 4");
            }
        });
        layout.addComponent(menuBar);

        Link link = new Link("Go to ShortcutKeys",
                             new ExternalResource(Page.getCurrent().getLocation().toString() + "Shortcut"));
        link.setTargetName("_blank");
        layout.addComponent(link);

        // Shortcut Keys
        final TextField tf = new TextField("Your data:");
        layout.addComponent(tf);

        Button button = new Button("Send data (ENTER)");
        button.setClickShortcut(KeyCode.ENTER, ModifierKey.SHIFT);

        button.addClickListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                layout.addComponent(new Label(tf.getValue()));
                tf.setValue("");
                tf.focus();
            }
        });

        layout.addComponent(button);
    }

}

这段代码的结果如下所示: enter image description here 一切都按照预期工作,没有任何通信问题(当单击“发送数据”按钮时,“Some text”和“Some other text”是添加的标签)。那么,为什么从链接创建的UI,在按钮上触发的单击事件会导致Vaadin中的“通信问题”呢?
这是完整的错误信息,来自于?debug Vaadin控制台:
Communication error: (SyntaxError) : Unexpected token < - Original JSON-text: html> 
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta 
http-equiv="X-UA-Compatible" content="IE=11;chrome=1" /> <style type="text/css">html, 
body {height:100%;margin:0;}</style> <link rel="shortcut icon" 
type="image/vnd.microsoft.icon" 
href="./../../VAADIN/themes/chapter_4_menubar_and_shortcutkeys/favicon.ico" /> <link 
rel="icon" type="image/vnd.microsoft.icon" 
href="./../../VAADIN/themes/chapter_4_menubar_and_shortcutkeys/favicon.ico" /> </head> 
<body scroll="auto" class=" v-generated-body"> <div id="Chapter4MenuBarandShortcutKeys-
1103734620" class=" v-app chapter_4_menubar_and_shortcutkeys"> <div class=" v-app-
loading"></div> <noscript> You have to enable javascript in your browser to use an  
application built with Vaadin. </noscript> </div> <script type="text/javascript" 
src="./../../VAADIN/vaadinBootstrap.js"></script> <script type="text/javascript">//<!
[CDATA[ if (!window.vaadin) alert("Failed to load the bootstrap javascript: 
./../../VAADIN/vaadinBootstrap.js"); if (typeof window.__gwtStatsEvent != 'function') { 
vaadin.gwtStatsEvents = []; window.__gwtStatsEvent = function(event) 
{vaadin.gwtStatsEvents.push(event); return true;}; } 
vaadin.initApplication("Chapter4MenuBarandShortcutKeys-1103734620",{ "authErrMsg": { 
"caption": "Authentication problem", "message": "Take note of any unsaved data, and 
<u>click here<\/u> or press ESC to continue." }, "comErrMsg": { "caption": "Communication 
problem", "message": "Take note of any unsaved data, and <u>click here<\/u> or press ESC 
to continue." }, "debug": true, "heartbeatInterval": 300, "serviceUrl": "./../..", 
"sessExpMsg": { "caption": "Session Expired", "message": "Take note of any unsaved data, 
and <u>click here<\/u> or press ESC key to continue." }, "standalone": true, "theme": 
"chapter_4_menubar_and_shortcutkeys", "vaadinDir": "./../../VAADIN/", "versionInfo": 
{"vaadinVersion": "7.3.7"}, "widgetset": "com.vaadin.DefaultWidgetSet" }); //]]></script> 
</body> </html

为什么会发生这种情况?

嘿,我有完全相同的问题:( 你能找出原因吗?如果你能给我一个答案,那会对我很有帮助,谢谢:) - LoremIpsum
1
@WarGodNT,请查看我下面的答案,希望它也能对您有所帮助! - tonix
1个回答

6

如果有人遇到我所面临的相同问题,以下是一些解决方案的注意事项。

问题出在负责显示ShortcutUI的VaadinServlet映射上:

简而言之,即:

 @WebServlet(value = "/Shortcut", asyncSupported = true)

Should become this:

 @WebServlet(value = "/Shortcut/*", asyncSupported = true)

当在ShortcutUI上触发事件并发送到服务器时,它们会通过请求发送到类似于以下URL的位置:

http://localhost:8080/myapp/Shortcut/UIDL/?v-uiId=0

如果应用程序的上下文根为/myapp,或类似于:

http://localhost:8080/Shortcut/UIDL/?v-uiId=0

如果应用程序的上下文根是servlet容器的DocumentRoot(例如,在使用嵌入式Jetty运行mvn jetty:run命令创建的Maven项目中),那么/Shortcut永远不会匹配/Shortcut/UIDL/?v-uiId=0,因此会出现错误。而Shortcut/*将匹配,因为在Shortcut后面的"/*"将匹配/UIDL/?v-uiId=0
另一个需要注意的重要事项是,您可能会想修改“入口点”UI的servlet映射(即映射到/*的UI),并将其更改为: @WebServlet(urlPatterns = {"", "/VAADIN/*"}, asyncSupported = true) 绝对不要这样做!这将有效,直到Vaadin应用程序发出/HEARTBEAT请求或触发用户界面上的事件并发送到服务器(进行"/UIDL"请求)。Vaadin仍然需要那个"*",因为它将与此类请求匹配(如"/HEARTBEAT"、"/UIDL"等)。
因此,在我看来,解决这个问题的唯一方法是使用:
@WebServlet(value = "/*", asyncSupported = true)

对于,以及:
@WebServlet(value = "/Shortcut/*", asyncSupported = true)
ShortcutUI和应用程序的任何“子-UI”都需要进行相同的处理,如果需要多个UI,则需要这样做。
否则,另一种选择是使用Navigator API -> https://vaadin.com/book/-/page/advanced.navigator.html

非常感谢您的高质量回答! - LoremIpsum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接