使用嵌入式 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 编译的资源工作正常,当我直接从浏览器打开应用程序时可用。
以下是一些附加信息:
- Vaadin 版本:8.0.5
- 嵌入式UI附加版本:2.0
- 我将 ValoTheme 用于所有 3 个应用程序(主机和嵌入式)
vaadin.widgetset.mode
设置为fetch
模式
- 我确保为应用程序启用了 CORS。
我搜索了很长时间来解决这个问题,但找不到足够的资源来解决这个特殊情况,而且我也是 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
查看更多信息
我目前正在使用 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 的初学者,所以我绝对需要一些帮助.
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
查看更多信息