使用嵌入式 UI 附加组件将 Vaadin + Spring Boot 应用程序嵌入到 Vaadin UI

Embedding Vaadin + Springboot application into a Vaadin UI using Emdedded UI add-on

我目前正在使用 springboot 和 Vaadin 8 开发微服务,我想为 Vaadin 使用 Embedded UI 2.0 附加组件。
我首先尝试将一个简单的 Springboot + Vaadin 嵌入到主机 Vaadin 应用程序中,如 example.
所示 这是主机应用程序的结果代码:

import ...
import org.vaadin.embedded.VaadinUIComponent;


@Theme(ValoTheme.THEME_NAME)
public class HostUI extends UI {

@Override
protected void init(VaadinRequest vaadinRequest) { 
    /*My Spring boot application */      
    VaadinUIComponent ui1 = new VaadinUIComponent("http://localhost:8081/app2/");
    ui1.setSizeFull(); 
    /* A simple vaadin application*/ 
    VaadinUIComponent ui2 = new VaadinUIComponent("http://localhost:9020");

    HorizontalSplitPanel split = new HorizontalSplitPanel(ui1, ui2);
    split.setSizeFull();
    setContent(split);
}

但我一直遇到 VAADIN/* 资源加载问题:

{"timestamp":1501683162735,"status":404,"error":"Not Found","message":"No message available","path":"
/app2/widgetsets/ws84167e472e91ff0ea8255f8f1b189aa0/ws84167e472e91ff0ea8255f8f1b189aa0.nocache.js"}

其中 /app2/ 是我的应用程序的路径。

我不确定资源路径是如何解析的,但我知道 Vaadin 目录 应该是 /app2/VAADIN/*,因为 widgetsets 和其他vaadin 编译的资源工作正常,当我直接从浏览器打开应用程序时可用。
以下是一些附加信息:

我搜索了很长时间来解决这个问题,但找不到足够的资源来解决这个特殊情况,而且我也是 Spring 和 Vaadin 的初学者,所以我绝对需要一些帮助.

TL;DR;版本

这好像是插件的BUG,还有类似的issue open on their tracker,不知道是你的还是别人的。但是为什么首先需要使用它呢?您想要实现哪些常规 Vaadin 应用程序无法实现且需要嵌入多个 UI 的目标?


详细版

所以我做了一些挖掘,你的观察是正确的,路径中缺少 /VAADIN/。 spring 引导应用程序中的 vaadinServlet 可能还会处理其他失败请求,例如 heartbeat 和 uidl。

独立应用程序请求:

嵌入式应用请求:

稍加调试,插件似乎确实使用了错误的路径:

最终追溯到 ./VAADIN 的正则表达式替换为 http://localhost:9030/ 的错误,而不是正确的 http://localhost:9030/VAADIN.

在我看来这是附加组件中的错误,但可能只有开发人员才能确认或解释为什么这样做。

作为解决方法,我们可以使用 spring 控制器将请求重定向到正确的 URL,但即使这样也有其局限性。它在第一页刷新时中断,因为通常增加的 v-uiId 保持为 0.

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;

@Controller
public class VaadinRedirectController {
    private static final String INCOMPLETE_WIDGETSET_PATH = "/widgetsets/**";
    private static final String INCOMPLETE_THEME_PATH = "/themes/**";
    private static final String INCOMPLETE_UIDL_PATH = "/UIDL/**";
    private static final String INCOMPLETE_HEARTBEAT_PATH = "/HEARTBEAT/**";

    @RequestMapping(value = {INCOMPLETE_WIDGETSET_PATH, INCOMPLETE_THEME_PATH,})
    public String redirectWidgetsetAndThemeRequests(HttpServletRequest request) {
        return createRedirectPath(request, "VAADIN");
    }

    @RequestMapping(value = {INCOMPLETE_UIDL_PATH, INCOMPLETE_HEARTBEAT_PATH})
    public String redirectUidlAndHeartbeatRequests(HttpServletRequest request) {
        return createRedirectPath(request, "vaadinServlet");
    }

    private String createRedirectPath(HttpServletRequest request, String prefix) {
        String path = "redirect:/" + prefix + getPath(request);
        if (request.getQueryString() != null && !request.getQueryString().isEmpty()) {
            path += "?" + request.getQueryString();
        }
        return path;
    }

    private Object getPath(HttpServletRequest request) {
        return request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
    }
}

Morfic 的解释很好!谢谢。是的,附加组件有问题。已在 2.1 中修复。请在 https://vaadin.com/forum#!/thread/16448312

查看更多信息