add: 增加undertow启动器的实现

This commit is contained in:
qinerg 2017-11-30 16:09:29 +08:00
parent b9f0c7684b
commit cfb8c4f2e9
3 changed files with 242 additions and 0 deletions

View File

@ -12,6 +12,7 @@
<name>nutzboot-starter-undertow</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<undertow.version>1.4.20.Final</undertow.version>
</properties>
<description>NutzBoot, micoservice base on Nutz</description>
@ -33,6 +34,12 @@
<email>wendal1985@gmail.com</email>
<url>http://wendal.net/</url>
</developer>
<developer>
<id>qinerg</id>
<name>gong qin</name>
<email>qinerg@gmail.com</email>
<url>https://my.oschina.net/qinerg</url>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/nutzam/nutzboot.git</connection>
@ -52,4 +59,28 @@
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
</repository>
</distributionManagement>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
<version>${undertow.version}</version>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
<version>${undertow.version}</version>
<exclusions>
<exclusion>
<artifactId>jboss-annotations-api_1.2_spec</artifactId>
<groupId>org.jboss.spec.javax.annotation</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,210 @@
package org.nutz.boot.starter.undertow;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.DispatcherType;
import org.nutz.boot.AppContext;
import org.nutz.boot.annotation.PropDoc;
import org.nutz.boot.aware.AppContextAware;
import org.nutz.boot.aware.ClassLoaderAware;
import org.nutz.boot.aware.IocAware;
import org.nutz.boot.starter.ServerFace;
import org.nutz.boot.starter.WebEventListenerFace;
import org.nutz.boot.starter.WebFilterFace;
import org.nutz.boot.starter.WebServletFace;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.lang.Files;
import org.nutz.lang.Strings;
import org.nutz.lang.util.LifeCycle;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.Undertow.Builder;
import io.undertow.server.HttpHandler;
import io.undertow.server.handlers.PathHandler;
import io.undertow.server.handlers.resource.ClassPathResourceManager;
import io.undertow.server.handlers.resource.FileResourceManager;
import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.servlet.api.FilterInfo;
import io.undertow.servlet.api.ListenerInfo;
import io.undertow.servlet.api.ServletInfo;
/**
* Undertow 启动器
* @author qinerg(qinerg@gmail.com)
*/
public class UndertowStarter implements ClassLoaderAware, IocAware, ServerFace, LifeCycle, AppContextAware {
private static final Log log = Logs.get();
protected static final String PRE = "undertow.";
@PropDoc(group = "undertow", value = "监听的ip地址", defaultValue = "0.0.0.0")
public static final String PROP_HOST = PRE + "host";
@PropDoc(group = "undertow", value = "监听的端口", defaultValue = "8080", type = "int")
public static final String PROP_PORT = PRE + "port";
@PropDoc(group = "undertow", value = "上下文路径", defaultValue = "/")
public static final String PROP_CONTEXT_PATH = PRE + "contextPath";
@PropDoc(group = "undertow", value = "session过期时间", defaultValue = "20")
public static final String PROP_SESSION = PRE + "session";
@PropDoc(group = "undertow", value = "过滤器顺序", defaultValue = "whale,druid,shiro,nutz")
public static final String PROP_WEB_FILTERS_ORDER = "web.filters.order";
@PropDoc(group = "undertow", value = "静态文件路径", defaultValue = "/static/")
public static final String PROP_STATIC_PATH = PRE + "staticPath";
protected Undertow server;
protected ClassLoader classLoader;
protected Ioc ioc;
protected AppContext appContext;
protected Builder builder = Undertow.builder();
protected DeploymentInfo deployment;
public void start() throws Exception {
server.start();
}
public void stop() throws Exception {
server.stop();
}
public boolean isRunning() {
return !server.getWorker().isShutdown();
}
public boolean failsafe() {
return false;
}
public void setIoc(Ioc ioc) {
this.ioc = ioc;
}
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setAppContext(AppContext appContext) {
this.appContext = appContext;
}
public void init() throws Exception {
PropertiesProxy conf = appContext.getConfigureLoader().get();
String contextPath = conf.get(PROP_CONTEXT_PATH, "/");
deployment = Servlets.deployment().setDeploymentName("nb").setClassLoader(classLoader).setEagerFilterInit(true).setSecurityDisabled(true);
deployment.setContextPath(contextPath).setDefaultSessionTimeout(conf.getInt(PROP_SESSION, 20) * 60);
String staticPath = conf.get(PROP_STATIC_PATH, "static");
File resRootDir = Files.findFile(staticPath);
if (resRootDir != null && resRootDir.isDirectory()) {
deployment.setResourceManager(new FileResourceManager(resRootDir, 1024));
} else {
deployment.setResourceManager(new ClassPathResourceManager(classLoader, staticPath));
}
// 添加其他starter提供的WebXXXX服务
Map<String, WebFilterFace> filters = new HashMap<>();
for (Object object : appContext.getStarters()) {
if (object instanceof WebFilterFace) {
WebFilterFace webFilter = (WebFilterFace) object;
filters.put(webFilter.getName(), webFilter);
}
if (object instanceof WebServletFace) {
WebServletFace webServlet = (WebServletFace) object;
addServlet(webServlet);
}
if (object instanceof WebEventListenerFace) {
WebEventListenerFace contextListener = (WebEventListenerFace) object;
if (contextListener.getEventListener() == null)
continue;
ListenerInfo listener = new ListenerInfo(contextListener.getEventListener().getClass());
deployment.addListener(listener);
}
}
String _filterOrders = conf.get(PROP_WEB_FILTERS_ORDER);
if (_filterOrders == null)
_filterOrders = "whale,druid,shiro,nutz";
else if (_filterOrders.endsWith("+")) {
_filterOrders = _filterOrders.substring(0, _filterOrders.length() - 1) + ",whale,druid,shiro,nutz";
}
String[] filterOrders = Strings.splitIgnoreBlank(_filterOrders);
for (String filterName : filterOrders) {
addFilter(filters.remove(filterName));
}
for (WebFilterFace webFilter : filters.values()) {
addFilter(webFilter);
}
deployment.addWelcomePages("index.html", "index.htm", "index.do");
DeploymentManager manager = Servlets.defaultContainer().addDeployment(deployment);
manager.deploy();
HttpHandler servletHandler = manager.start();
PathHandler pathHandler;
if ("/".equals(contextPath)) {
pathHandler = Handlers.path(servletHandler);
} else {
pathHandler = Handlers.path(Handlers.redirect(contextPath)).addPrefixPath(contextPath, servletHandler);
}
builder.addHttpListener(conf.getInt(PROP_PORT, 8080), conf.get(PROP_HOST, "0.0.0.0")).setHandler(pathHandler);
server = builder.build();
}
public void addServlet(WebServletFace webServlet) {
if (webServlet == null || webServlet.getServlet() == null)
return;
ServletInfo servlet = new ServletInfo(webServlet.getName(), webServlet.getServlet().getClass());
Iterator<Map.Entry<String, String>> entries = webServlet.getInitParameters().entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, String> entry = entries.next();
servlet.addInitParam(entry.getKey(), entry.getValue());
}
servlet.addMapping(webServlet.getPathSpec());
log.debugf("add servlet name=%s pathSpec=%s", webServlet.getName(), webServlet.getPathSpec());
deployment.addServlet(servlet);
}
public void addFilter(WebFilterFace webFilter) {
if (webFilter == null || webFilter.getFilter() == null)
return;
log.debugf("add filter name=%s pathSpec=%s", webFilter.getName(), webFilter.getPathSpec());
FilterInfo filter = new FilterInfo(webFilter.getName(), webFilter.getFilter().getClass());
Iterator<Map.Entry<String, String>> entries = webFilter.getInitParameters().entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, String> entry = entries.next();
filter.addInitParam(entry.getKey(), entry.getValue());
}
deployment.addFilter(filter)
.addFilterUrlMapping(webFilter.getName(), webFilter.getPathSpec(), DispatcherType.REQUEST)
.addFilterUrlMapping(webFilter.getName(), webFilter.getPathSpec(), DispatcherType.FORWARD);
}
public void fetch() throws Exception {
}
public void depose() throws Exception {
}
}

View File

@ -0,0 +1 @@
org.nutz.boot.starter.undertow.UndertowStarter