我有一个使用嵌入式Jetty作为服务器的REST应用程序。大多数端点需要公开可见(并且内置了适当的身份验证),但有一些仅供内部使用。我想避免对这些进行身份验证的开销,而是使用防火墙来限制访问:
外部可见端点在端口10000上提供,外部防火墙保持打开状态。 内部可见端点在端口20000上提供,外部防火墙阻止这些端点。
但是,我无法弄清楚如何使用嵌入式Jetty来实现这一点。我已经尝试实例化两个Server
对象,一个在端口10000上,注册了相应的servlet处理程序,另一个在端口20000上注册了相应的servlet处理程序。但是,只有第二个启动的服务器实例才能工作;对首先开始的端点的请求首先导致404响应。
Jetty文档讨论了如何使用*.xml configurations 执行此操作,但不是针对嵌入式实例。
任何想法或想法?或者是否有更好的方法来实现我之后的内部/外部端点隔离?硬性要求是内部和外部端点都需要在同一个JVM中“运行”。
事实证明,问题与使用Guice和Guice-servlets扩展(问题618和635)有关。运行两个嵌入式Jetty实例的工作正常,如James Kingsbery的answer中所述。
Guice使用在服务器上下文中注册的过滤器(GuiceFilter)来获取需要请求范围的依赖注入(DI)的请求以及构建需要DI的servlet和过滤器。不幸的是,它使用静态对象来管理与之关联的servlet和过滤器列表。
在典型的设置中,包含GuiceFilter
的guice-servlet.jar包含在每个应用程序中,因此由每个应用程序的不同类加载器加载 - 并且一切正常。嵌入式Jetty就是这样,基本上所有内容都由默认的系统类加载器加载。
Guice的最新master(commit fbbb52dcc92e)包含一个更新的GuiceFilter
,支持对FilterPipeline
对象(导致问题的静态对象)的动态引用。不幸的是,注入FilterPipeline
实例的构造函数是package-private。因此,要使用它,您需要在com.google.inject.servlet
包中创建一个包装类,以暴露该构造函数:
package com.google.inject.servlet;
import com.google.inject.Inject;
public class NonStaticGuiceFilter extends GuiceFilter {
/**
* Do not use. Must inject a {@link FilterPipeline} via the constructor.
*/
@SuppressWarnings("unused")
private NonStaticGuiceFilter() {
throw new IllegalStateException();
}
@Inject
public NonStaticGuiceFilter(FilterPipeline filterPipeline) {
super(filterPipeline);
}
}
要使用此类,请使用安装了ServletModule
的进样器创建实例,并将其注册到Jetty Context
:
// Create the context handler
ServletContextHandler handler = new ServletContextHandler(myServer, "/context");
// Create the injector, registering your ServletModule
final Injector injector = Guice.createInjector(new MyServletModule());
// Add the Guice listener for this injector
handler.addEventListener(new GuiceServletContextListener() {
@Override
protected Injector getInjector() {
return injector;
}
});
// Filter all requests through Guice via NonStaticGuiceFilter.
// Guice will construct the FilterPipeline instance needed by
// NonStaticGuiceFilter.
handler.addFilter(
new FilterHolder(injector
.getInstance(NonStaticGuiceFilter.class)), "/*", null);
答案 0 :(得分:5)
我开始使用嵌入式Jetty项目的常见方法是Wicket maven原型。这是一个基于该原型的类,它应该完全符合您的需要:
package net.kingsbery;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.bio.SocketConnector;
import org.mortbay.jetty.webapp.WebAppContext;
public class Start {
public static void main(String[] args) throws Exception {
Server server = new Server();
SocketConnector connector = new SocketConnector();
// Set some timeout options to make debugging easier.
connector.setMaxIdleTime(1000 * 60 * 60);
connector.setSoLingerTime(-1);
connector.setPort(10080);
server.setConnectors(new Connector[] { connector });
WebAppContext bb = new WebAppContext();
bb.setServer(server);
bb.setContextPath("/");
bb.setWar("src/main/secret-webapp");
server.addHandler(bb);
Server server2 = new Server();
SocketConnector connector2 = new SocketConnector();
// Set some timeout options to make debugging easier.
connector2.setMaxIdleTime(1000 * 60 * 60);
connector2.setSoLingerTime(-1);
connector2.setPort(20000);
server2.setConnectors(new Connector[] { connector });
WebAppContext bb2 = new WebAppContext();
bb2.setServer(server);
bb2.setContextPath("/");
bb2.setWar("src/main/webapp");
server.addHandler(bb);
server2.addHandler(bb2);
try {
server.start();
server2.start();
} catch (Exception e) {
e.printStackTrace();
System.exit(100);
}
}
}
如果您使用其他处理程序,请将其替换为webapp处理程序。
话虽如此,我不确定这是否正确。