使用Emdedded UI插件将Vaadin + Springboot应用程序嵌入到Vaadin UI中

时间:2017-08-02 15:32:37

标签: spring spring-boot vaadin embed vaadin8

我目前正在使用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编译的资源正在运行很好,当我直接从浏览器打开应用程序时可以使用 以下是一些其他信息:

  • Vaadin版本:8.0.5
  • 嵌入式UI插件版本:2.0
  • 我将ValoTheme用于所有3个应用程序(主机和嵌入式)
  • vaadin.widgetset.mode设置为fetch模式
  • 我确保为应用程序启用了CORS。

我搜索了一段时间来解决这个问题,但找不到足够的资源来解决这个问题,而且我也是Spring和Vaadin的初学者,所以我绝对可以使用一些帮助。

2 个答案:

答案 0 :(得分:0)

<强> TL; DR;版本

这似乎是附加组件中的一个错误,并且有类似的issue open on their tracker,不确定它是您还是其他人。但为什么你需要首先使用它?您想要实现的是通过常规Vaadin应用程序无法实现的,并且需要嵌入多个UI?

详细版本

所以我做了一些挖掘,你的观察是正确的,路径中缺少/VAADIN/。可能还有其他失败请求由vaadinServlet在Spring启动应用中处理,例如heartbeat和uidl。

独立应用请求:

stand alone app request

嵌入式应用请求:

embedded app request

通过一点模式调试,似乎加载项确实使用了错误的路径: incorrect path

最后使用./VAADIN而不是正确的http://localhost:9030/追溯到http://localhost:9030/VAADIN的错误正则表达式替换。

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

regex replacement

作为一种解决方法,我们可以使用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);
    }
}

答案 1 :(得分:0)

Morfic的好解释!谢谢。是的,加载项存在问题。在2.1中修复。请在https://vaadin.com/forum#!/thread/16448312

上查看更多信息