/* * Copyright 2012-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.boot.web.embedded.jetty; import java.net.InetSocketAddress; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.thread.ThreadPool; import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory; import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.boot.web.server.WebServer; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.JettyHttpHandlerAdapter; /** * {@link ReactiveWebServerFactory} that can be used to create {@link JettyWebServer}s. * * @author Brian Clozel * @since 2.0.0 */ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory { private static final Log logger = LogFactory .getLog(JettyReactiveWebServerFactory.class); /** * The number of acceptor threads to use. */ private int acceptors = -1; /** * The number of selector threads to use. */ private int selectors = -1; private ThreadPool threadPool; /** * Create a new {@link JettyServletWebServerFactory} instance. */ public JettyReactiveWebServerFactory() { super(); } /** * Create a new {@link JettyServletWebServerFactory} that listens for requests using * the specified port. * @param port the port to listen on */ public JettyReactiveWebServerFactory(int port) { super(port); } @Override public WebServer getWebServer(HttpHandler httpHandler) { JettyHttpHandlerAdapter servlet = new JettyHttpHandlerAdapter(httpHandler); Server server = createJettyServer(servlet); return new JettyWebServer(server, getPort() >= 0); } protected Server createJettyServer(JettyHttpHandlerAdapter servlet) { int port = (getPort() >= 0 ? getPort() : 0); InetSocketAddress address = new InetSocketAddress(getAddress(), port); Server server = new Server(getThreadPool()); server.addConnector(createConnector(address, server)); ServletHolder servletHolder = new ServletHolder(servlet); ServletContextHandler contextHandler = new ServletContextHandler(server, "", false, false); contextHandler.addServlet(servletHolder, "/"); JettyReactiveWebServerFactory.logger .info("Server initialized with port: " + port); return server; } private AbstractConnector createConnector(InetSocketAddress address, Server server) { ServerConnector connector = new ServerConnector(server, this.acceptors, this.selectors); connector.setHost(address.getHostName()); connector.setPort(address.getPort()); for (ConnectionFactory connectionFactory : connector.getConnectionFactories()) { if (connectionFactory instanceof HttpConfiguration.ConnectionFactory) { ((HttpConfiguration.ConnectionFactory) connectionFactory) .getHttpConfiguration().setSendServerVersion(false); } } return connector; } /** * Returns a Jetty {@link ThreadPool} that should be used by the {@link Server}. * @return a Jetty {@link ThreadPool} or {@code null} */ public ThreadPool getThreadPool() { return this.threadPool; } /** * Set a Jetty {@link ThreadPool} that should be used by the {@link Server}. If set to * {@code null} (default), the {@link Server} creates a {@link ThreadPool} implicitly. * @param threadPool a Jetty ThreadPool to be used */ public void setThreadPool(ThreadPool threadPool) { this.threadPool = threadPool; } /** * Set the number of acceptor threads to use. * @param acceptors the number of acceptor threads to use */ public void setAcceptors(int acceptors) { this.acceptors = acceptors; } /** * Set the number of selector threads to use. * @param selectors the number of selector threads to use */ public void setSelectors(int selectors) { this.selectors = selectors; } }