Spring 引导:将另一个端口上的请求发送到自定义 Servlet
Spring Boot: Send requests on another port to a custom Servlet
我希望我的 spring-boot 应用程序在第二个端口上侦听(其中 "first" 端口 server.port 用于 spring-webmvc 端点)并直接所有进入我编写的 Servlet 实现的第二个端口上的“/”的流量。这些请求将是 json-rpc 请求,我希望将其与正常服务流量分开。我怎样才能做到这一点?
我找到代码让嵌入式 Tomcat 通过添加另一个连接器在另一个端口上侦听,如下所示:
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addAdditionalTomcatConnectors(createRpcServerConnector());
return tomcat;
}
private Connector createRpcServerConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
connector.setPort(Integer.parseInt(env.getProperty("rpc.port")));
return connector;
}
而且我发现您可以简单地通过将其公开为 Bean 来注册另一个 Servlet,就像这样
@Bean
public Servlet rpcServlet() {
return new RpcServlet();
}
但是,当像这样公开 Servlet 时,它只是将其映射到常规 server.port 上的 URL 模式。我不知道如何将它连接到 RPC 连接器,这样我的 webmvc 端口上的“/”就不会尝试处理 RPC 请求,并且 RPC 端口不会将请求转发到我的 @RestController
方法。
也许这是我对Tomcat的误解。我什至应该为此使用 Tomcat 吗?我应该切换到 spring-boot 提供的另一个嵌入式 servlet 容器吗?
要隔离一个 Connector
供单个应用程序使用,该连接器需要与其自身的 Service
相关联,然后您需要将应用程序的 Context
与Service
.
您可以通过提供自己的 TomcatEmbeddedServletContainerFactory
子类作为 @Bean
并覆盖 getEmbeddedServletContainer(Tomcat tomcat)
,在您的 Spring 启动应用程序中进行设置。这使您有机会进行所需的配置更改:
@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
return new TomcatEmbeddedServletContainerFactory() {
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
Tomcat tomcat) {
Server server = tomcat.getServer();
Service service = new StandardService();
service.setName("other-port-service");
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(8081);
service.addConnector(connector);
server.addService(service);
Engine engine = new StandardEngine();
service.setContainer(engine);
Host host = new StandardHost();
host.setName("other-port-host");
engine.addChild(host);
engine.setDefaultHost(host.getName());
Context context = new StandardContext();
context.addLifecycleListener(new FixContextListener());
context.setName("other-port-context");
context.setPath("");
host.addChild(context);
Wrapper wrapper = context.createWrapper();
wrapper.setServlet(new MyServlet());
wrapper.setName("other-port-servlet");
context.addChild(wrapper);
context.addServletMapping("/", wrapper.getName());
return super.getTomcatEmbeddedServletContainer(tomcat);
}
};
}
private static class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().println("Hello, world");
}
}
将此 bean 添加到您的应用程序后,http://localhost:8081 应由 MyServlet
和 return 处理包含 "Hello, world".
的响应
我希望我的 spring-boot 应用程序在第二个端口上侦听(其中 "first" 端口 server.port 用于 spring-webmvc 端点)并直接所有进入我编写的 Servlet 实现的第二个端口上的“/”的流量。这些请求将是 json-rpc 请求,我希望将其与正常服务流量分开。我怎样才能做到这一点?
我找到代码让嵌入式 Tomcat 通过添加另一个连接器在另一个端口上侦听,如下所示:
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addAdditionalTomcatConnectors(createRpcServerConnector());
return tomcat;
}
private Connector createRpcServerConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
connector.setPort(Integer.parseInt(env.getProperty("rpc.port")));
return connector;
}
而且我发现您可以简单地通过将其公开为 Bean 来注册另一个 Servlet,就像这样
@Bean
public Servlet rpcServlet() {
return new RpcServlet();
}
但是,当像这样公开 Servlet 时,它只是将其映射到常规 server.port 上的 URL 模式。我不知道如何将它连接到 RPC 连接器,这样我的 webmvc 端口上的“/”就不会尝试处理 RPC 请求,并且 RPC 端口不会将请求转发到我的 @RestController
方法。
也许这是我对Tomcat的误解。我什至应该为此使用 Tomcat 吗?我应该切换到 spring-boot 提供的另一个嵌入式 servlet 容器吗?
要隔离一个 Connector
供单个应用程序使用,该连接器需要与其自身的 Service
相关联,然后您需要将应用程序的 Context
与Service
.
您可以通过提供自己的 TomcatEmbeddedServletContainerFactory
子类作为 @Bean
并覆盖 getEmbeddedServletContainer(Tomcat tomcat)
,在您的 Spring 启动应用程序中进行设置。这使您有机会进行所需的配置更改:
@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
return new TomcatEmbeddedServletContainerFactory() {
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
Tomcat tomcat) {
Server server = tomcat.getServer();
Service service = new StandardService();
service.setName("other-port-service");
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(8081);
service.addConnector(connector);
server.addService(service);
Engine engine = new StandardEngine();
service.setContainer(engine);
Host host = new StandardHost();
host.setName("other-port-host");
engine.addChild(host);
engine.setDefaultHost(host.getName());
Context context = new StandardContext();
context.addLifecycleListener(new FixContextListener());
context.setName("other-port-context");
context.setPath("");
host.addChild(context);
Wrapper wrapper = context.createWrapper();
wrapper.setServlet(new MyServlet());
wrapper.setName("other-port-servlet");
context.addChild(wrapper);
context.addServletMapping("/", wrapper.getName());
return super.getTomcatEmbeddedServletContainer(tomcat);
}
};
}
private static class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().println("Hello, world");
}
}
将此 bean 添加到您的应用程序后,http://localhost:8081 应由 MyServlet
和 return 处理包含 "Hello, world".