-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from Unknow0/27-use-commons-cli-instead-of-picoli
gh-27 switch cli lib
- Loading branch information
Showing
13 changed files
with
261 additions
and
317 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 62 additions & 59 deletions
121
unknow-server-http/src/main/java/unknow/server/http/AbstractHttpServer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,103 +1,106 @@ | ||
package unknow.server.http; | ||
|
||
import java.net.InetSocketAddress; | ||
import java.util.ServiceLoader; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.SynchronousQueue; | ||
import java.util.concurrent.ThreadPoolExecutor; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
import org.apache.commons.cli.CommandLine; | ||
import org.apache.commons.cli.Option; | ||
|
||
import jakarta.servlet.ServletContainerInitializer; | ||
import jakarta.servlet.ServletException; | ||
import picocli.CommandLine.Option; | ||
import unknow.server.http.servlet.FilterConfigImpl; | ||
import unknow.server.http.servlet.ServletConfigImpl; | ||
import unknow.server.http.servlet.ServletContextImpl; | ||
import unknow.server.http.utils.EventManager; | ||
import unknow.server.http.utils.ServletManager; | ||
import unknow.server.nio.cli.NIOServerCli; | ||
import unknow.server.nio.NIOServer; | ||
import unknow.server.nio.NIOServerBuilder; | ||
|
||
/** | ||
* Abstract server | ||
* | ||
* @author unknow | ||
*/ | ||
public abstract class AbstractHttpServer extends NIOServerCli { | ||
|
||
/** | ||
* public vhost seen be the servlet (default to the binded address) | ||
*/ | ||
@Option(names = "--vhost", description = "public vhost seen be the servlet (default to the binded address)", descriptionKey = "vhost") | ||
public String vhost; | ||
|
||
/** | ||
* min number of execution thread to use, default to 0 | ||
*/ | ||
@Option(names = "--exec-min", description = "min number of exec thread to use, default to 0", descriptionKey = "exec-min") | ||
public int execMin = 0; | ||
|
||
/** | ||
* max number of execution thread to use, default to Integer.MAX_VALUE | ||
*/ | ||
@Option(names = "--exec-max", description = "max number of exec thread to use, default to Integer.MAX_VALUE", descriptionKey = "exec-max") | ||
public int execMax = Integer.MAX_VALUE; | ||
|
||
/** | ||
* max idle time for exec thread, default to 60 | ||
*/ | ||
@Option(names = "--exec-idle", description = "max idle time for exec thread in seconds, default to 60", descriptionKey = "exec-idle") | ||
public long execIdle = 60L; | ||
|
||
/** | ||
* max time to keep idle keepalive connection, default to -1 | ||
*/ | ||
@Option(names = "--keep-alive-idle", description = "max time to keep idle keepalive connection, -1: infinite, 0: no keep alive, default to -1", descriptionKey = "keep-alive-idle") | ||
public int keepAliveIdle = 2000; | ||
|
||
protected final ServletContextImpl ctx; | ||
protected final ServletManager servlets; | ||
protected final EventManager events; | ||
|
||
protected AbstractHttpServer() { | ||
servlets = createServletManager(); | ||
events = createEventManager(); | ||
ctx = createContext(); | ||
} | ||
public abstract class AbstractHttpServer extends NIOServerBuilder { | ||
private Opt addr; | ||
private Opt vhost; | ||
private Opt execMin; | ||
private Opt execMax; | ||
private Opt execIdle; | ||
private Opt keepAlive; | ||
|
||
protected ServletContextImpl ctx; | ||
protected ServletManager servlets; | ||
protected EventManager events; | ||
|
||
protected abstract ServletManager createServletManager(); | ||
|
||
protected abstract EventManager createEventManager(); | ||
|
||
protected abstract ServletContextImpl createContext(); | ||
protected abstract ServletContextImpl createContext(String vhost); | ||
|
||
protected abstract ServletConfigImpl[] createServlets(); | ||
|
||
protected abstract FilterConfigImpl[] createFilters(); | ||
|
||
protected void loadInitializer() throws ServletException { | ||
for (ServletContainerInitializer i : ServiceLoader.load(ServletContainerInitializer.class)) { | ||
i.onStartup(null, ctx); | ||
} | ||
@Override | ||
protected void beforeParse() { | ||
addr = withOpt("addr").withCli(Option.builder("a").longOpt("addr").hasArg().desc("address to bind to").build()).withValue(":8080"); | ||
vhost = withOpt("vhost").withCli(Option.builder().longOpt("vhost").desc("public vhost seen by the servlet, default to the binded address").build()); | ||
execMin = withOpt("exec-min").withCli(Option.builder().longOpt("exec-min").desc("min number of exec thread to use").build()).withValue("0"); | ||
execMax = withOpt("exec-max").withCli(Option.builder().longOpt("exec-max").desc("max number of exec thread to use").build()) | ||
.withValue(Integer.toString(Integer.MAX_VALUE)); | ||
execIdle = withOpt("exec-idle").withCli(Option.builder().longOpt("exec-idle").desc("max idle time for exec thread in seconds").build()).withValue("60"); | ||
keepAlive = withOpt("exec-idle") | ||
.withCli(Option.builder().longOpt("exec-idle").desc("max time to keep idle keepalive connection, -1: infinite, 0: no keep alive").build()).withValue("2000"); | ||
} | ||
|
||
@Override | ||
protected final void init() throws Exception { | ||
AtomicInteger i = new AtomicInteger(); | ||
ExecutorService executor = new ThreadPoolExecutor(execMin, execMax, execIdle, TimeUnit.SECONDS, new SynchronousQueue<>(), r -> { | ||
Thread t = new Thread(r, "exec-" + i.getAndIncrement()); | ||
t.setDaemon(true); | ||
return t; | ||
}); | ||
protected void process(NIOServer server, CommandLine cli) throws Exception { | ||
InetSocketAddress address = parseAddr(cli, addr, ""); | ||
String value = cli.getOptionValue(vhost.name()); | ||
if (value == null) | ||
value = address.getHostString(); | ||
|
||
handler = () -> new HttpConnection(executor, ctx, keepAliveIdle); | ||
servlets = createServletManager(); | ||
events = createEventManager(); | ||
ctx = createContext(value); | ||
|
||
loadInitializer(); | ||
servlets.initialize(ctx, createServlets(), createFilters()); | ||
events.fireContextInitialized(ctx); | ||
|
||
AtomicInteger i = new AtomicInteger(); | ||
ExecutorService executor = new ThreadPoolExecutor(parseInt(cli, execMin, 0), parseInt(cli, execMax, 0), parseInt(cli, execIdle, 0), TimeUnit.SECONDS, | ||
new SynchronousQueue<>(), r -> { | ||
Thread t = new Thread(r, "exec-" + i.getAndIncrement()); | ||
t.setDaemon(true); | ||
return t; | ||
}); | ||
int keepAliveIdle = parseInt(cli, keepAlive, -1); | ||
server.bind(address, () -> new HttpConnection(executor, ctx, keepAliveIdle)); | ||
} | ||
|
||
@Override | ||
protected final void destroy() { | ||
events.fireContextDestroyed(ctx); | ||
protected void loadInitializer() throws ServletException { | ||
for (ServletContainerInitializer i : ServiceLoader.load(ServletContainerInitializer.class)) { | ||
i.onStartup(null, ctx); | ||
} | ||
} | ||
|
||
public void process(String[] arg) throws Exception { | ||
NIOServer nioServer = build(arg); | ||
try { | ||
nioServer.start(); | ||
nioServer.await(); | ||
} finally { | ||
nioServer.stop(); | ||
nioServer.await(); | ||
events.fireContextDestroyed(ctx); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.