mirror of
https://gitee.com/nutz/nutzboot.git
synced 2024-12-04 04:38:30 +08:00
commit
36883175b6
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user