Merge pull request #49 from wolfboys/dev

tomcat support and clean code
This commit is contained in:
Wendal Chen 2017-12-12 13:22:04 +08:00 committed by GitHub
commit 36883175b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 380 additions and 196 deletions

View File

@ -36,6 +36,8 @@ 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.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.LifeCycle;
@ -43,30 +45,34 @@ import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.resource.Scans;
@IocBean
public class JettyStarter implements ClassLoaderAware, IocAware, ServerFace, LifeCycle, AppContextAware {
private static final Log log = Logs.get();
protected static final String PRE = "jetty.";
@PropDoc(group="jetty", value="监听的ip地址", defaultValue="0.0.0.0")
public static final String PROP_HOST = PRE + "host";
private static final Log log = Logs.get();
protected static final String PRE = "jetty.";
@PropDoc(group = "jetty", value = "监听的ip地址", defaultValue = "0.0.0.0")
public static final String PROP_HOST = PRE + "host";
@PropDoc(group = "jetty", value = "监听的端口", defaultValue = "8080", type = "int")
public static final String PROP_PORT = PRE + "port";
@PropDoc(group = "jetty", value = "空闲时间,单位毫秒", defaultValue = "300000", type = "int")
public static final String PROP_IDLE_TIMEOUT = PRE + "http.idleTimeout";
@PropDoc(group = "jetty", value = "上下文路径", defaultValue = "/")
public static final String PROP_CONTEXT_PATH = PRE + "contextPath";
@PropDoc(group = "jetty", value = "表单最大尺寸", defaultValue = "1gb", type = "int")
public static final String PROP_MAX_FORM_CONTENT_SIZE = PRE + "maxFormContentSize";
@PropDoc(group = "web", value = "过滤器顺序", defaultValue = "whale,druid,shiro,nutz")
public static final String PROP_WEB_FILTERS_ORDER = "web.filters.order";
@Inject
private PropertiesProxy conf;
@PropDoc(group="jetty", value="监听的端口", defaultValue="8080", type="int")
public static final String PROP_PORT = PRE + "port";
@PropDoc(group="jetty", value="空闲时间,单位毫秒", defaultValue="300000", type="int")
public static final String PROP_IDLE_TIMEOUT = PRE + "http.idleTimeout";
@PropDoc(group="jetty", value="上下文路径", defaultValue="/")
public static final String PROP_CONTEXT_PATH = PRE + "contextPath";
@PropDoc(group="jetty", value="表单最大尺寸", defaultValue="1gb", type="int")
public static final String PROP_MAX_FORM_CONTENT_SIZE = PRE + "maxFormContentSize";
@PropDoc(group="web", value="过滤器顺序", defaultValue="whale,druid,shiro,nutz")
public static final String PROP_WEB_FILTERS_ORDER = "web.filters.order";
protected Server server;
protected ClassLoader classLoader;
protected Ioc ioc;
@ -96,45 +102,47 @@ public class JettyStarter implements ClassLoaderAware, IocAware, ServerFace, Lif
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setAppContext(AppContext appContext) {
this.appContext = appContext;
}
public void init() throws Exception {
// copy and modify from nutz-web
// 创建基础服务器
server = new Server(new QueuedThreadPool(Lang.isAndroid ? 50 : 500));
ServerConnector connector= new ServerConnector(server);
server = new Server(new QueuedThreadPool(getMaxThread()));
ServerConnector connector = new ServerConnector(server);
PropertiesProxy conf = appContext.getConfigureLoader().get();
connector.setHost(conf.get(PROP_HOST, "0.0.0.0"));
connector.setPort(conf.getInt(PROP_PORT, 8080));
connector.setIdleTimeout(conf.getInt(PROP_IDLE_TIMEOUT, 300*1000));
connector.setHost(getHost());
connector.setPort(getPort());
connector.setIdleTimeout(getIdleTimeout());
server.setConnectors(new Connector[]{connector});
// 设置应用上下文
wac = new WebAppContext();
wac.setContextPath(conf.get(PROP_CONTEXT_PATH, "/"));
wac.setContextPath(getContextPath());
//wac.setExtractWAR(false);
//wac.setCopyWebInf(true);
//wac.setProtectedTargets(new String[]{"/java", "/javax", "/org", "/net", "/WEB-INF", "/META-INF"});
wac.setTempDirectory(new File("./tmp").getAbsoluteFile());
wac.setTempDirectory(createTempDir("jetty").getAbsoluteFile());
wac.setClassLoader(classLoader);
wac.setConfigurationDiscovered(true);
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
wac.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false");
}
List<Resource> resources = new ArrayList<>();
for (String resourcePath : Arrays.asList("static/", "webapp/")) {
File f = new File(resourcePath);
if (f.exists())
resources.add(Resource.newResource(f));
Enumeration<URL> urls = appContext.getClassLoader().getResources(resourcePath);
while(urls.hasMoreElements()) {
resources.add(Resource.newResource(urls.nextElement()));
}
File f = new File(resourcePath);
if (f.exists()) {
resources.add(Resource.newResource(f));
}
Enumeration<URL> urls = appContext.getClassLoader().getResources(resourcePath);
while (urls.hasMoreElements()) {
resources.add(Resource.newResource(urls.nextElement()));
}
}
wac.setBaseResource(new ResourceCollection(resources.toArray(new Resource[resources.size()])) {
@Override
@ -154,62 +162,62 @@ public class JettyStarter implements ClassLoaderAware, IocAware, ServerFace, Lif
list.add("org.eclipse.jetty.annotations.AnnotationConfiguration");
wac.setConfigurationClasses(list);
wac.getServletContext().setExtendedListenerTypes(true);
// 设置一下额外的东西
server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize", conf.getInt(PROP_MAX_FORM_CONTENT_SIZE, 1024*1024*1024));
server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize", getMaxFormContentSize());
server.setDumpAfterStart(false);
server.setDumpBeforeStop(false);
server.setStopAtShutdown(true);
ServerContainer sc = WebSocketServerContainerInitializer.configureContext(wac);
for (Class<?> klass : Scans.me().scanPackage(appContext.getPackage())) {
if (klass.getAnnotation(ServerEndpoint.class) != null) {
sc.addEndpoint(klass);
}
}
if (klass.getAnnotation(ServerEndpoint.class) != null) {
sc.addEndpoint(klass);
}
}
// 添加其他starter提供的WebXXXX服务
addNutzSupport();
}
private void addNutzSupport() {
Map<String, WebFilterFace> filters = new HashMap<>();
for (Object object : appContext.getStarters()) {
if (object instanceof WebFilterFace) {
WebFilterFace webFilter = (WebFilterFace)object;
WebFilterFace webFilter = (WebFilterFace) object;
filters.put(webFilter.getName(), webFilter);
}
if (object instanceof WebServletFace) {
WebServletFace webServlet = (WebServletFace)object;
if (webServlet.getServlet() == null)
continue;
WebServletFace webServlet = (WebServletFace) object;
if (webServlet.getServlet() == null) {
continue;
}
ServletHolder holder = new ServletHolder(webServlet.getServlet());
holder.setName(webServlet.getName());
holder.setInitParameters(webServlet.getInitParameters());
wac.addServlet(holder, webServlet.getPathSpec());
}
if (object instanceof WebEventListenerFace) {
WebEventListenerFace contextListener = (WebEventListenerFace)object;
if (contextListener.getEventListener() == null)
continue;
wac.addEventListener(contextListener.getEventListener());
WebEventListenerFace contextListener = (WebEventListenerFace) object;
if (contextListener.getEventListener() != null) {
wac.addEventListener(contextListener.getEventListener());
}
}
}
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);
String[] filterOrders = Strings.splitIgnoreBlank(getWebFiltersOrder());
for (String filterName : filterOrders) {
addFilter(filters.remove(filterName));
}
addFilter(filters.remove(filterName));
}
for (WebFilterFace webFilter : filters.values()) {
addFilter(webFilter);
}
addFilter(webFilter);
}
}
public void addFilter(WebFilterFace webFilter) {
if (webFilter == null || webFilter.getFilter() == null)
return;
log.debugf("add filter name=%s pathSpec=%s", webFilter.getName(), webFilter.getPathSpec());
if (webFilter == null || webFilter.getFilter() == null) {
return;
}
log.debugf("add filter name=%s pathSpec=%s", webFilter.getName(), webFilter.getPathSpec());
FilterHolder holder = new FilterHolder(webFilter.getFilter());
holder.setName(webFilter.getName());
holder.setInitParameters(webFilter.getInitParameters());
@ -222,4 +230,51 @@ public class JettyStarter implements ClassLoaderAware, IocAware, ServerFace, Lif
public void depose() throws Exception {
}
private File createTempDir(String prefix) {
try {
File tempDir = File.createTempFile(prefix + ".", "." + getPort());
tempDir.delete();
tempDir.mkdir();
tempDir.deleteOnExit();
return tempDir;
} catch (IOException ex) {
throw new RuntimeException(
"Unable to create tempDir. java.io.tmpdir is set to "
+ System.getProperty("java.io.tmpdir"),
ex);
}
}
// --getConf---
public int getPort() {
return conf.getInt(PROP_PORT, 8080);
}
public String getHost() {
return conf.get(PROP_HOST, "0.0.0.0");
}
public int getMaxFormContentSize() {
return conf.getInt(PROP_MAX_FORM_CONTENT_SIZE, 1024 * 1024 * 1024);
}
public String getWebFiltersOrder() {
String filterOrder = conf.get(PROP_WEB_FILTERS_ORDER);
return filterOrder == null
? "whale,druid,shiro,nutz"
: filterOrder.replaceFirst("\\+$", ",whale,druid,shiro,nutz");
}
public String getContextPath() {
return conf.get(PROP_CONTEXT_PATH, "/");
}
public int getIdleTimeout() {
return conf.getInt(PROP_IDLE_TIMEOUT, 300 * 1000);
}
public int getMaxThread() {
return Lang.isAndroid ? 50 : 500;
}
}

View File

@ -78,15 +78,11 @@
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
</dependency>
<!--tomcat end-->
<dependency>
<groupId>org.nutz</groupId>

View File

@ -1,13 +1,16 @@
package org.nutz.boot.starter.tomcat;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Wrapper;
import org.apache.catalina.*;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardThreadExecutor;
@ -25,14 +28,21 @@ import org.nutz.boot.starter.WebServletFace;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Files;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.LifeCycle;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import javax.servlet.ServletContext;
/**
* tomcat 启动器
* <p>
* 十步杀一人 千里不留行
* 事了扶衣去 深藏功与名
* </p>
*
* @author benjobs (benjobs@qq.com)
* @author wendal (wendal1985@gmail.com)
@ -59,32 +69,45 @@ public class TomcatStarter implements ClassLoaderAware, ServerFace, LifeCycle, A
@PropDoc(group = "tomcat", value = "过滤器顺序", defaultValue = "whale,druid,shiro,nutz")
public static final String PROP_WEB_FILTERS_ORDER = "web.filters.order";
@PropDoc(group = "tomcat", value = "静态文件路径", defaultValue = "/static/")
@PropDoc(group = "tomcat", value = "静态文件路径", defaultValue = "static")
public static final String PROP_STATIC_PATH = PRE + "staticPath";
public static final String PROP_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol";
private static final String PROP_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol";
private static final Charset DEFAULT_CHARSET = Charset.forName("utf-8");
@Inject
private PropertiesProxy conf;
protected Tomcat tomcat;
protected StandardContext tomcatContext;
protected ClassLoader classLoader;
protected AppContext appContext;
@Inject
private PropertiesProxy conf;
private final AtomicInteger containerCounter = new AtomicInteger(-1);
private final Object monitor = new Object();
private volatile boolean started;
//tomcat await thread
private Thread tomcatAwaitThread;
@Override
public void init() throws LifecycleException {
this.tomcat = new Tomcat();
// 貌似Tomcat死活需要一个temp目录
File baseDir = new File("./temp");
File baseDir = createTempDir("tomcat");
this.tomcat.setBaseDir(baseDir.getAbsolutePath());
// 当前支持Http就够了
Connector connector = new Connector(PROP_PROTOCOL);
connector.setPort(getPort());
connector.setURIEncoding("UTF-8");
connector.setURIEncoding(DEFAULT_CHARSET.name());
// 设置一下最大线程数
this.tomcat.getService().addConnector(connector);
@ -98,22 +121,41 @@ public class TomcatStarter implements ClassLoaderAware, ServerFace, LifeCycle, A
this.tomcat.getHost().setAutoDeploy(false);
this.tomcat.getEngine().setBackgroundProcessorDelay(30);
prepareContext(this.tomcat.getHost());
this.nutzSupport();
this.prepareContext();
}
public void start() throws LifecycleException {
this.tomcat.start();
synchronized (this.monitor) {
if (this.started) {
return;
}
this.tomcat.start();
tomcatAwaitThread = new Thread("container-" + (containerCounter.get())) {
@Override
public void run() {
TomcatStarter.this.tomcat.getServer().await();
}
};
tomcatAwaitThread.setContextClassLoader(getClass().getClassLoader());
tomcatAwaitThread.setDaemon(false);
tomcatAwaitThread.start();
this.started = true;
}
}
public void stop() throws LifecycleException {
this.tomcat.stop();
this.tomcat = null;
synchronized (this.monitor) {
if (started) {
this.tomcat.stop();
this.tomcat = null;
this.tomcatAwaitThread.interrupt();
this.started = false;
}
}
}
public boolean isRunning() {
return true;
return this.started;
}
public void setAppContext(AppContext appContext) {
@ -128,72 +170,76 @@ public class TomcatStarter implements ClassLoaderAware, ServerFace, LifeCycle, A
return false;
}
public void fetch() {}
public void depose() throws LifecycleException {
if (this.tomcat != null)
this.tomcat.stop();
public void fetch() {
}
private void prepareContext(Host host) {
public void depose() throws LifecycleException {
if (this.tomcat != null) {
this.stop();
}
}
private void prepareContext() {
File docBase = Files.findFile(getStaticPath());
docBase = (docBase != null && docBase.isDirectory()) ? docBase : createTempDir("tomcat-docbase");
this.tomcatContext = new StandardContext();
this.tomcatContext.setDocBase(docBase.getAbsolutePath());
this.tomcatContext.setName(getContextPath());
this.tomcatContext.setPath(getContextPath());
this.tomcatContext.setDelegate(false);
this.tomcatContext.addLifecycleListener(new Tomcat.FixContextListener());
this.tomcatContext.setParentClassLoader(classLoader);
this.tomcatContext.setSessionTimeout(getSessionTimeout());
this.tomcatContext.addLifecycleListener(new StoreMergedWebXmlListener());
for (String welcomeFile : Arrays.asList("index.html",
"index.htm",
"index.jsp",
"index.do")) {
this.tomcatContext.addWelcomeFile(welcomeFile);
try {
this.tomcatContext.setUseRelativeRedirects(false);
} catch (NoSuchMethodError ex) {
// Tomcat is < 8.0.30. Continue
}
this.tomcatContext.setUseRelativeRedirects(false);
for (String welcomeFile : Arrays.asList("index.html",
"index.htm",
"index.jsp",
"index.do")) {
this.tomcatContext.addWelcomeFile(welcomeFile);
}
// 注册defaultServlet
addDefaultServlet();
// 注册JspServlet
addJspServlet();
addNutzSupport();
host.addChild(tomcatContext);
this.tomcat.getHost().addChild(tomcatContext);
}
private void nutzSupport() {
// 添加其他starter提供的WebXXXX服务
private void addNutzSupport() {
Map<String, WebFilterFace> filters = new HashMap<String, WebFilterFace>();
for (Object object : appContext.getStarters()) {
if (object instanceof WebFilterFace) {
WebFilterFace webFilter = (WebFilterFace) object;
if (webFilter == null || webFilter.getFilter() == null) {
continue;
if (webFilter != null && webFilter.getFilter() != null) {
filters.put(webFilter.getName(), webFilter);
}
filters.put(webFilter.getName(), webFilter);
}
if (object instanceof WebServletFace) {
WebServletFace webServlet = (WebServletFace) object;
if (webServlet == null || webServlet.getServlet() == null) {
continue;
if (webServlet != null && webServlet.getServlet() != null) {
addServlet(webServlet);
}
addServlet(webServlet);
}
if (object instanceof WebEventListenerFace) {
WebEventListenerFace contextListener = (WebEventListenerFace) object;
if (contextListener == null || contextListener.getEventListener() == null) {
continue;
if (contextListener != null && contextListener.getEventListener() != null) {
this.tomcatContext.addApplicationEventListener(contextListener.getEventListener());
}
this.tomcatContext.addApplicationEventListener(contextListener.getEventListener());
}
}
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);
String[] filterOrders = Strings.splitIgnoreBlank(getWebFiltersOrder());
for (String filterName : filterOrders) {
addFilter(filters.remove(filterName));
@ -215,23 +261,8 @@ public class TomcatStarter implements ClassLoaderAware, ServerFace, LifeCycle, A
addServletMapping("/", "default");
}
private void addJspServlet() {
// 暂不支持jsp了
// Wrapper jspServlet = this.tomcatContext.createWrapper();
// jspServlet.setName("jsp");
// jspServlet.setServletClass(JspServlet.class.getName());
// jspServlet.addInitParameter("fork", "false");
// jspServlet.addInitParameter("development", "false");
// jspServlet.setLoadOnStartup(3);
// this.tomcatContext.addChild(jspServlet);
// addServletMapping("*.jsp", "jsp");
// addServletMapping("*.jspx", "jsp");
}
private void addServlet(WebServletFace webServlet) {
log.debugf("[NutzBoot] add servlet name=%s pathSpec=%s",
webServlet.getName(),
webServlet.getPathSpec());
log.debugf("[NutzBoot] add servlet name=%s pathSpec=%s", webServlet.getName(), webServlet.getPathSpec());
Wrapper servlet = tomcatContext.createWrapper();
servlet.setName(webServlet.getName());
@ -241,7 +272,7 @@ public class TomcatStarter implements ClassLoaderAware, ServerFace, LifeCycle, A
servlet.addInitParameter(entry.getKey(), entry.getValue());
}
servlet.setOverridable(true);
tomcatContext.addChild(servlet);
this.tomcatContext.addChild(servlet);
addServletMapping(webServlet.getPathSpec(), webServlet.getName());
}
@ -249,9 +280,7 @@ public class TomcatStarter implements ClassLoaderAware, ServerFace, LifeCycle, A
if (filterFace == null || filterFace.getFilter() == null) {
return;
}
log.debugf("[NutzBoot] add filter name=%s pathSpec=%s",
filterFace.getName(),
filterFace.getPathSpec());
log.debugf("[NutzBoot] add filter name=%s pathSpec=%s", filterFace.getName(), filterFace.getPathSpec());
FilterDef filterDef = new FilterDef();
filterDef.setFilter(filterFace.getFilter());
filterDef.setFilterName(filterFace.getName());
@ -262,8 +291,9 @@ public class TomcatStarter implements ClassLoaderAware, ServerFace, LifeCycle, A
}
}
this.tomcatContext.addFilterDef(filterDef);
FilterMap filterMap = new FilterMap();
filterMap.addURLPattern(filterFace.getPathSpec());
filterMap.addURLPatternDecoded(filterFace.getPathSpec());
filterMap.setFilterName(filterFace.getName());
this.tomcatContext.addFilterMap(filterMap);
}
@ -272,6 +302,66 @@ public class TomcatStarter implements ClassLoaderAware, ServerFace, LifeCycle, A
this.tomcatContext.addServletMappingDecoded(pattern, name);
}
private File createTempDir(String prefix) {
try {
File tempDir = File.createTempFile(prefix + ".", "." + getPort());
tempDir.delete();
tempDir.mkdir();
tempDir.deleteOnExit();
return tempDir;
} catch (IOException ex) {
throw new RuntimeException(
"Unable to create tempDir. java.io.tmpdir is set to "
+ System.getProperty("java.io.tmpdir"),
ex);
}
}
private static class StoreMergedWebXmlListener implements LifecycleListener {
private static final String MERGED_WEB_XML = "org.apache.tomcat.util.scan.MergedWebXml";
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
onStart((Context) event.getLifecycle());
}
}
private void onStart(Context context) {
ServletContext servletContext = context.getServletContext();
if (servletContext.getAttribute(MERGED_WEB_XML) == null) {
servletContext.setAttribute(MERGED_WEB_XML, getEmptyWebXml());
}
}
private String getEmptyWebXml() {
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("empty-web.xml");
if (stream == null) {
throw new IllegalArgumentException("Unable to read empty web.xml");
}
try {
try {
StringBuilder out = new StringBuilder();
InputStreamReader reader = new InputStreamReader(stream, DEFAULT_CHARSET);
char[] buffer = new char[1024 * 4];
int bytesRead = -1;
while ((bytesRead = reader.read(buffer)) != -1) {
out.append(buffer, 0, bytesRead);
}
return out.toString();
} finally {
stream.close();
}
} catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
}
// --getConf---
public int getPort() {
return conf.getInt(PROP_PORT, 8080);
@ -285,6 +375,13 @@ public class TomcatStarter implements ClassLoaderAware, ServerFace, LifeCycle, A
return conf.get(PROP_STATIC_PATH, "static");
}
public String getWebFiltersOrder() {
String filterOrder = conf.get(PROP_WEB_FILTERS_ORDER);
return filterOrder == null
? "whale,druid,shiro,nutz"
: filterOrder.replaceFirst("\\+$", ",whale,druid,shiro,nutz");
}
public String getContextPath() {
return conf.get(PROP_CONTEXT_PATH, "");
}
@ -296,4 +393,6 @@ public class TomcatStarter implements ClassLoaderAware, ServerFace, LifeCycle, A
public int getMaxThread() {
return Lang.isAndroid ? 50 : 500;
}
}

View File

@ -21,7 +21,10 @@ 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.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Files;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.LifeCycle;
import org.nutz.log.Log;
@ -46,6 +49,8 @@ import io.undertow.servlet.util.ImmediateInstanceFactory;
* Undertow 启动器
* @author qinerg(qinerg@gmail.com)
*/
@IocBean
public class UndertowStarter implements ClassLoaderAware, IocAware, ServerFace, LifeCycle, AppContextAware {
private static final Log log = Logs.get();
@ -66,10 +71,13 @@ public class UndertowStarter implements ClassLoaderAware, IocAware, ServerFace,
@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";
@Inject
private PropertiesProxy conf;
protected Undertow server;
protected ClassLoader classLoader;
protected Ioc ioc;
@ -108,21 +116,39 @@ public class UndertowStarter implements ClassLoaderAware, IocAware, ServerFace,
}
public void init() throws Exception {
PropertiesProxy conf = appContext.getConfigureLoader().get();
String contextPath = conf.get(PROP_CONTEXT_PATH, "/");
String contextPath = getContextPath();
deployment = Servlets.deployment().setDeploymentName("nb").setClassLoader(classLoader).setEagerFilterInit(true).setSecurityDisabled(true);
deployment.setContextPath(contextPath).setDefaultSessionTimeout(conf.getInt(PROP_SESSION, 20) * 60);
deployment.setContextPath(contextPath).setDefaultSessionTimeout(getSessionTimeout());
String staticPath = conf.get(PROP_STATIC_PATH, "static");
File resRootDir = Files.findFile(staticPath);
File resRootDir = Files.findFile(getStaticPath());
if (resRootDir != null && resRootDir.isDirectory()) {
deployment.setResourceManager(new FileResourceManager(resRootDir, 1024));
} else {
deployment.setResourceManager(new ClassPathResourceManager(classLoader, staticPath));
deployment.setResourceManager(new ClassPathResourceManager(classLoader, getStaticPath()));
}
// 添加其他starter提供的WebXXXX服务
addNutzSupport();
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(getPort(),getHost()).setHandler(pathHandler);
server = builder.build();
}
private void addNutzSupport() {
Map<String, WebFilterFace> filters = new HashMap<>();
for (Object object : appContext.getStarters()) {
if (object instanceof WebFilterFace) {
@ -139,57 +165,35 @@ public class UndertowStarter implements ClassLoaderAware, IocAware, ServerFace,
}
}
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);
String[] filterOrders = Strings.splitIgnoreBlank(getWebFiltersOrder());
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;
log.debugf("add servlet name=%s pathSpec=%s", webServlet.getName(), webServlet.getPathSpec());
ImmediateInstanceFactory<Servlet> factory = new ImmediateInstanceFactory<Servlet>(webServlet.getServlet());
ServletInfo servlet = new ServletInfo(webServlet.getName(), webServlet.getServlet().getClass(), factory);
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());
deployment.addServlet(servlet);
if (webServlet == null || webServlet.getServlet() == null) {
return;
}
log.debugf("add servlet name=%s pathSpec=%s", webServlet.getName(), webServlet.getPathSpec());
ImmediateInstanceFactory<Servlet> factory = new ImmediateInstanceFactory<Servlet>(webServlet.getServlet());
ServletInfo servlet = new ServletInfo(webServlet.getName(), webServlet.getServlet().getClass(), factory);
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());
deployment.addServlet(servlet);
}
public void addFilter(WebFilterFace webFilter) {
if (webFilter == null || webFilter.getFilter() == null)
if (webFilter == null || webFilter.getFilter() == null) {
return;
}
log.debugf("add filter name=%s pathSpec=%s", webFilter.getName(), webFilter.getPathSpec());
ImmediateInstanceFactory<Filter> factory = new ImmediateInstanceFactory<Filter>(webFilter.getFilter());
FilterInfo filter = new FilterInfo(webFilter.getName(), webFilter.getFilter().getClass(), factory);
@ -202,10 +206,11 @@ public class UndertowStarter implements ClassLoaderAware, IocAware, ServerFace,
.addFilterUrlMapping(webFilter.getName(), webFilter.getPathSpec(), DispatcherType.REQUEST)
.addFilterUrlMapping(webFilter.getName(), webFilter.getPathSpec(), DispatcherType.FORWARD);
}
public void addEventListener(WebEventListenerFace webEventListener) {
if (webEventListener.getEventListener() == null)
if (webEventListener.getEventListener() == null) {
return;
}
EventListener et = webEventListener.getEventListener();
log.debugf("add listener %s", et.getClass());
@ -220,4 +225,33 @@ public class UndertowStarter implements ClassLoaderAware, IocAware, ServerFace,
public void depose() throws Exception {
}
// --getConf---
public int getPort() {
return conf.getInt(PROP_PORT, 8080);
}
public String getHost() {
return conf.get(PROP_HOST, "0.0.0.0");
}
public String getStaticPath() {
return conf.get(PROP_STATIC_PATH, "static");
}
public String getWebFiltersOrder() {
String filterOrder = conf.get(PROP_WEB_FILTERS_ORDER);
return filterOrder == null
? "whale,druid,shiro,nutz"
: filterOrder.replaceFirst("\\+$", ",whale,druid,shiro,nutz");
}
public String getContextPath() {
return conf.get(PROP_CONTEXT_PATH, "/");
}
public int getSessionTimeout() {
return conf.getInt(PROP_SESSION, 20) * 60;
}
}