我的目标是配置Jetty服务器以使用Vaadin 11框架。 我正在尝试的是以下内容:
public static void main(final String[] args) {
final Server server = new Server();
final ServerConnector httpConnector = new ServerConnector(server);
httpConnector.setPort(8080);
final ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.setContextPath("/");
final ServletHolder servletHolder = new ServletHolder(new VaadinServlet());
contextHandler.addServlet(servletHolder, "/*");
final WebAppContext context = new WebAppContext();
context.setServer(server);
context.setContextPath("/");
context.setClassLoader(Thread.currentThread().getContextClassLoader());
server.addConnector(httpConnector);
server.setHandler(contextHandler);
server.setHandler(context);
try {
server.start();
} catch (final Exception e) {
e.printStackTrace();
}
}
@Route("/")
public class MainView extends Div {
public MainView() {
System.out.println("main");
setText("aha bye");
}
}
但从未调用过MainView。如何告诉Jetty将请求转发给Vaadin?
在这里回答我自己的问题。
但是这仍然无法按预期工作。为什么?因为你在同一个contextPath
contextHandler
上有2个不同的上下文(context
和/
)。但同样,这似乎是倒退,因为你的
WebAppContext
没有宣布资源基础或战争,所以它在你的示例代码中没有为你做任何事情。
Joakim Erdfelt是绝对正确的。我用两个上下文搞砸了代码,我要么设置资源库,要么设置war文件。非常感谢你指出解决方案的方法!
感谢Leif Åstrand也提供了使用@Route
注释查找所有类的提示!
我将服务器代码与“客户端”代码分开,并为jetty服务器构建war文件。
我用作工作解决方案的内容如下:
final WebAppContext context = new WebAppContext();
context.setServer(httpServer);
context.setContextPath("/");
context.addServlet(new ServletHolder(new TestServlet()), "/*");
context.setWar(warFile.getAbsolutePath());
context.setExtractWAR(true);
context.setClassLoader(Thread.currentThread().getContextClassLoader());
context.setInitParameter("ui", MainUI.class.getCanonicalName());
httpServer.setHandler(context);
在Testservlet
(扩展VaadinServlet
)我有以下两种方法:
@SuppressWarnings("unchecked")
private void findRouteClasses() {
final Set<Class<?>> routeClasses = ReflectionUtils.findClassesWithAnnotation(Route.class,
"com.example.myproject");
this.routeClasses = new HashSet<>();
for (final Class<?> clazz : routeClasses)
this.routeClasses.add((Class<? extends Component>) clazz);
}
@Override
protected void servletInitialized() throws ServletException {
final ServletContext context = getServletContext();
final Object routeRegistryObject = context.getAttribute(RouteRegistry.class.getName());
if (routeRegistryObject == null)
throw new ServletException("routeRegistryObject is null");
if ((routeRegistryObject instanceof RouteRegistry) == false)
throw new ServletException("routeRegistryObject is not of type RouteRegistry");
final RouteRegistry routeRegistry = (RouteRegistry) routeRegistryObject;
findRouteClasses();
try {
routeRegistry.setNavigationTargets(routeClasses);
} catch (final InvalidRouteConfigurationException e) {
throw new ServletException(e);
}
super.servletInitialized();
}
所有带有注释com.vaadin.flow.router.Route
的类都将被隔离,然后设置为导航目标。
server.setHandler(contextHandler);
server.setHandler(context);
你用contextHandler
用你的代码替换你的context
。
试试这个......
HandlerList handlers = new HandlerList();
handlers.addHandler(contextHandler);
handlers.addHandler(context);
handlers.addHandler(new DefaultHandler()); // to report errors if nothing above matches
server.setHandler(handlers);
但是这仍然无法按预期工作。为什么?因为你在同一个contextPath contextHandler
上有2个不同的上下文(context
和/
)。
将使用HandlerList
中的第一个上下文,并且永远不会调用下一个上下文。为什么?因为一旦输入上下文,就不会退出它(该上下文必须提供响应,甚至是错误)。
您可以修改您的WebAppContext
以包含VaadinServlet
(完全不需要ServletContextHandler
)
例如:
final WebAppContext context = new WebAppContext();
final ServletHolder servletHolder = new ServletHolder(new VaadinServlet());
context.addServlet(servletHolder, "/*");
但同样,这似乎是倒退,因为你的WebAppContext
没有宣布资源基础或战争,所以它在你的示例代码中没有为你做任何事情。
如果是我,我正在使用embedded-jetty,我会完全避免使用WebAppContext
而只是坚持使用ServletContextHandler
。