2015-04-20 3 views
2

Я хочу, чтобы мое приложение для загрузки Spring прослушивало второй порт (где «первый» - сервер.порт используется для конечных точек spring-webmvc) и направляет весь трафик входящий в «/» на втором порту к реализации Сервлета, который я написал. Этими запросами будут запросы 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; 
} 

И я обнаружил, что вы можете зарегистрировать другой Servlet просто выставляя его как Bean, как так

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

Однако при экспонировании сервлета, как это, он просто отображает его в шаблон URL на регулярной server.port. Я не могу понять, как подключить его к разъему RPC, чтобы «/» на моем веб-порту не пытался обрабатывать запросы RPC, а порт RPC не перенаправляет запросы на мои методы @RestController.

Возможно, это происходит из-за моего непонимания Tomcat. Должен ли я использовать Tomcat для этого? Должен ли я переключиться на другой встроенный контейнер сервлетов, предоставленный весной-загрузкой?

+0

Мне любопытно, почему вы используете эти два в одном приложении, а не как два отдельных приложения? – Tim

+0

Это отличный вопрос, Тим. К сожалению, это не мое решение. Мне поручено реализовать его таким образом. Я считаю, что мотивация заключается в том, чтобы устанавливать разные типы трафика на разные порты по причинам, не зависящим от моего понимания. – BigFuzzyDoor

+0

И в чем мотивация отсутствия двух отдельных приложений, каждый из которых прослушивает один порт? Как спросил @Tim, почему он должен быть в одном приложении? –

ответ

1

Для выделения Connector для использования одним приложением, что разъем должен быть связан со своим собственным Service, а затем вам нужно связать Context для применения с этим Service.

Вы можете установить это в своем приложении Spring Boot, предоставив свой собственный подкласс TomcatEmbeddedServletContainerFactory как @Bean и переопределяя getEmbeddedServletContainer(Tomcat tomcat). Это дает возможность сделать необходимые изменения в конфигурации:

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

} 

С этим боб добавлен к вашему приложению, http://localhost:8081 должны быть обработаны MyServlet и возвращает ответ, содержащий «Привет, мир».

+0

Я добавлю к этому, что для того, чтобы обработать обработчики обработанных этим сервлетами запросов, обработанные обработанными компонентами, добавьте RequestContextListener в контекст, например: context.addApplicationEventListener (new RequestContextListener()); – BigFuzzyDoor

Смежные вопросы