package io.gitlab.leibnizhu.sbnetty.bootstrap; import io.gitlab.leibnizhu.sbnetty.core.NettyContainer; import io.gitlab.leibnizhu.sbnetty.core.NettyContext; import io.netty.bootstrap.Bootstrap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.EmbeddedServletContainer; import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.ResourceLoader; import org.springframework.util.ClassUtils; import javax.servlet.ServletException; import java.net.InetSocketAddress; import java.net.URL; import java.net.URLClassLoader; import java.util.Random; /** * Spring Boot会查找EmbeddedServletContainerFactory接口的实现类(工厂类),调用其getEmbeddedServletContainer()方法,来获取web应用的容器 * 所以我们要实现这个接口,这里不直接实现,而是通过继承AbstractEmbeddedServletContainerFactory类来实现 * * @author Leibniz on 2017-08-24. */ public class EmbeddedNettyFactory extends AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware { private final Logger log = LoggerFactory.getLogger(getClass()); private static final String SERVER_INFO = "Netty@SpringBoot"; private ResourceLoader resourceLoader; @Override public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) { ClassLoader parentClassLoader = resourceLoader != null ? resourceLoader.getClassLoader() : ClassUtils.getDefaultClassLoader(); //Netty启动环境相关信息 Package nettyPackage = Bootstrap.class.getPackage(); String title = nettyPackage.getImplementationTitle(); String version = nettyPackage.getImplementationVersion(); log.info("Running with " + title + " " + version); //是否支持默认Servlet if (isRegisterDefaultServlet()) { log.warn("This container does not support a default servlet"); } //上下文 NettyContext context = new NettyContext(getContextPath(), new URLClassLoader(new URL[]{}, parentClassLoader), SERVER_INFO); for (ServletContextInitializer initializer : initializers) { try { initializer.onStartup(context); } catch (ServletException e) { throw new RuntimeException(e); } } //从SpringBoot配置中获取端口,如果没有则随机生成 int port = getPort() > 0 ? getPort() : new Random().nextInt(65535 - 1024) + 1024; InetSocketAddress address = new InetSocketAddress(port); log.info("Server initialized with port: " + port); return new NettyContainer(address, context); //初始化容器并返回 } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } }