Spring Boot:将另一个端口上的请求发送到自定义 Servlet [英] Spring Boot: Send requests on another port to a custom Servlet

查看:54
本文介绍了Spring Boot:将另一个端口上的请求发送到自定义 Servlet的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望我的 spring-boot 应用程序侦听第二个端口(其中第一个"端口是用于 spring-webmvc 端点的 server.port)并将进入第二个端口上的/"的所有流量定向到我写的 Servlet 的实现.这些请求将是 json-rpc 请求,我希望将其与正常服务流量分开.我怎样才能做到这一点?

I want my spring-boot app to listen on a second port (where the "first" one is server.port used for spring-webmvc endpoints) and direct all traffic coming in to "/" on the second port to an implementation of Servlet I have written. These requests will be json-rpc requests which I want separated from normal service traffic. How can I achieve this?

我发现通过添加另一个连接器来让嵌入式 Tomcat 侦听另一个端口的代码如下:

I have found code to have the embedded Tomcat listen on another port by adding another Connector like so:

@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;
}

而且我发现你可以简单地通过将另一个 Servlet 公开为一个 Bean 来注册另一个 Servlet,就像这样

And I have found that you can register another Servlet simply by exposing it as a Bean, like so

@Bean
public Servlet rpcServlet() {
    return new RpcServlet();
}

然而,当像这样公开一个 Servlet 时,它只是将它映射到常规 server.port 上的 URL 模式.我无法弄清楚如何将它连接到 RPC 连接器,这样我的 webmvc 端口上的/"就不会尝试处理 RPC 请求,并且 RPC 端口不会将请求转发到我的 @RestController 方法.

However, when exposing a Servlet like this, it simply maps it to a URL pattern on the regular server.port. I cannot figure out how to connect it to the RPC connector such that "/" on my webmvc port is not trying to process RPC requests, and the RPC port does not forward requests to my @RestController methods.

也许这来自于我对Tomcat的误解.我什至应该为此使用Tomcat吗?我应该切换到 spring-boot 提供的另一个嵌入式 servlet 容器吗?

Perhaps this comes from my misunderstanding of Tomcat. Should I even be using Tomcat for this? Should I switch to another embedded servlet container provided by spring-boot?

推荐答案

要隔离一个 Connector 供单个应用程序使用,该连接器需要与其自己的 Service 相关联code>,然后您需要将应用程序的 Context 与该 Service 相关联.

To isolate a Connector for use by a single application, that connector needs to be associated with its own Service and then you need to associate the Context for the application with that Service.

您可以通过提供您自己的 TomcatEmbeddedServletContainerFactory 子类作为 @Bean 并覆盖 getEmbeddedServletContainer(Tomcat tomcat).这让您有机会进行所需的配置更改:

You can set this up in your Spring Boot app by providing your own TomcatEmbeddedServletContainerFactory subclass as a @Bean and overriding getEmbeddedServletContainer(Tomcat tomcat). This gives you a chance to make the required configuration changes:

@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<处理/code> 并返回包含Hello, world"的响应.

With this bean added to your application, http://localhost:8081 should be handled by MyServlet and return a response containing "Hello, world".

这篇关于Spring Boot:将另一个端口上的请求发送到自定义 Servlet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆