ameba.container.grizzly.server.GrizzlyContainer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ameba-container-grizzly Show documentation
Show all versions of ameba-container-grizzly Show documentation
A useful Java framework grizzly container!
package ameba.container.grizzly.server;
import ameba.Ameba;
import ameba.container.Container;
import ameba.container.grizzly.server.http.GrizzlyHttpContainer;
import ameba.container.grizzly.server.http.GrizzlyServerUtil;
import ameba.container.grizzly.server.http.websocket.WebSocketServerContainer;
import ameba.container.server.Connector;
import ameba.core.Application;
import ameba.exception.AmebaException;
import ameba.i18n.Messages;
import ameba.util.ClassUtils;
import ameba.websocket.WebSocketAddon;
import ameba.websocket.WebSocketException;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.glassfish.grizzly.GrizzlyFuture;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.http.server.ServerConfiguration;
import org.glassfish.grizzly.http.util.Constants;
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder;
import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.server.ContainerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.tyrus.core.Utils;
import javax.websocket.DeploymentException;
import javax.websocket.server.ServerContainer;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
/**
* @author icode
*/
public class GrizzlyContainer extends Container {
public static final String WEB_SOCKET_CONTEXT_PATH = "websocket.contextPath";
/**
* Server-side property to set custom worker {@link org.glassfish.grizzly.threadpool.ThreadPoolConfig}.
*
* Value is expected to be instance of {@link org.glassfish.grizzly.threadpool.ThreadPoolConfig}, can be {@code null} (it won't be used).
*/
public static final String WORKER_THREAD_POOL_CONFIG = "container.server.workerThreadPoolConfig";
public static final String WORKER_THREAD_POOL_CORE_SIZE = "container.server.worker.coreSize";
public static final String WORKER_THREAD_POOL_MAX_SIZE = "container.server.worker.maxSize";
/**
* Server-side property to set custom selector {@link org.glassfish.grizzly.threadpool.ThreadPoolConfig}.
*
* Value is expected to be instance of {@link org.glassfish.grizzly.threadpool.ThreadPoolConfig}, can be {@code null} (it won't be used).
*/
public static final String SELECTOR_THREAD_POOL_CONFIG = "container.server.selectorThreadPoolConfig";
public static final String SELECTOR_THREAD_POOL_SIZE = "container.server.selector.size";
private static final String TYPE_NAME = "Grizzly";
private HttpServer httpServer;
private GrizzlyHttpContainer container;
private WebSocketContainerProvider webSocketServerContainerProvider;
private WebSocketServerContainer webSocketServerContainer;
private List connectors;
private boolean webSocketEnabled;
public GrizzlyContainer(Application app) {
super(app);
}
@Override
public ServiceLocator getServiceLocator() {
return container.getApplicationHandler().getServiceLocator();
}
private void buildWebSocketContainer() {
webSocketServerContainer = new WebSocketServerContainer(getApplication().getProperties());
}
@Override
protected void configureHttpServer() {
final Map properties = getApplication().getProperties();
connectors = Connector.createDefaultConnectors(properties);
if (connectors.size() == 0) {
logger.warn(Messages.get("info.connector.none"));
connectors.add(Connector.createDefault(Maps.newHashMap()));
}
List listeners = GrizzlyServerUtil.createListeners(connectors,
GrizzlyServerUtil.createCompressionConfig("http", properties));
webSocketEnabled = !"false".equals(properties.get(WebSocketAddon.WEB_SOCKET_ENABLED_CONF));
final String contextPath = StringUtils.defaultIfBlank((String) properties.get(WEB_SOCKET_CONTEXT_PATH), "/");
if (webSocketEnabled) {
buildWebSocketContainer();
GrizzlyServerUtil.bindWebSocket(contextPath, getWebSocketContainerProvider(), listeners);
}
String charset = StringUtils.defaultIfBlank((String) properties.get("app.encoding"), "utf-8");
System.setProperty(Constants.class.getName() + ".default-character-encoding", charset);
httpServer = new HttpServer() {
@Override
public synchronized void start() throws IOException {
if (webSocketServerContainer != null)
try {
webSocketServerContainer.start(contextPath, -1);
} catch (DeploymentException e) {
logger.error("启动websocket容器失败", e);
}
super.start();
}
@Override
public synchronized GrizzlyFuture shutdown(long gracePeriod, TimeUnit timeUnit) {
if (webSocketServerContainer != null)
webSocketServerContainer.stop();
return super.shutdown(gracePeriod, timeUnit);
}
@Override
public synchronized void shutdownNow() {
if (webSocketServerContainer != null)
webSocketServerContainer.stop();
super.shutdownNow();
}
};
httpServer.getServerConfiguration().setJmxEnabled(getApplication().isJmxEnabled());
ThreadPoolConfig workerThreadPoolConfig = null;
String workerThreadPoolConfigClass = Utils.getProperty(properties, WORKER_THREAD_POOL_CONFIG, String.class);
if (StringUtils.isNotBlank(workerThreadPoolConfigClass)) {
workerThreadPoolConfig = ClassUtils.newInstance(workerThreadPoolConfigClass);
}
ThreadPoolConfig selectorThreadPoolConfig = null;
String selectorThreadPoolConfigClass = Utils.getProperty(properties, SELECTOR_THREAD_POOL_CONFIG, String.class);
if (StringUtils.isNotBlank(selectorThreadPoolConfigClass)) {
selectorThreadPoolConfig = ClassUtils.newInstance(selectorThreadPoolConfigClass);
}
TCPNIOTransportBuilder transportBuilder = null;
if (workerThreadPoolConfig != null || selectorThreadPoolConfig != null) {
transportBuilder = TCPNIOTransportBuilder.newInstance();
if (workerThreadPoolConfig != null) {
transportBuilder.setWorkerThreadPoolConfig(workerThreadPoolConfig);
}
if (selectorThreadPoolConfig != null) {
transportBuilder.setSelectorThreadPoolConfig(selectorThreadPoolConfig);
}
}
Integer selectorSize = Utils.getProperty(properties, SELECTOR_THREAD_POOL_SIZE, Integer.class);
Integer workerCoreSize = Utils.getProperty(properties, WORKER_THREAD_POOL_CORE_SIZE, Integer.class);
Integer workerMaxSize = Utils.getProperty(properties, WORKER_THREAD_POOL_MAX_SIZE, Integer.class);
for (NetworkListener listener : listeners) {
if (transportBuilder != null) {
listener.setTransport(transportBuilder.build());
}
if (workerThreadPoolConfig == null) {
TCPNIOTransport transport = listener.getTransport();
workerThreadPoolConfig = transport.getWorkerThreadPoolConfig();
boolean change = false;
if (workerCoreSize != null && workerCoreSize > 0) {
workerThreadPoolConfig.setCorePoolSize(workerCoreSize);
change = true;
}
if (workerMaxSize != null && workerMaxSize > 0) {
workerThreadPoolConfig.setMaxPoolSize(workerMaxSize);
change = true;
}
if (change) {
transport.setWorkerThreadPoolConfig(workerThreadPoolConfig);
}
}
if (selectorThreadPoolConfig == null && selectorSize != null && selectorSize > 0) {
listener.getTransport().setSelectorRunnersCount(selectorSize);
}
httpServer.addListener(listener);
}
final ServerConfiguration config = httpServer.getServerConfiguration();
config.setPassTraceRequest(true);
config.setHttpServerName(getApplication().getApplicationName());
String version = getApplication().getApplicationVersion().toString();
config.setHttpServerVersion(
config.getHttpServerName().equals(Application.DEFAULT_APP_NAME) ? Ameba.getVersion() : version);
config.setName("Ameba-HttpServer-" + getApplication().getApplicationName());
}
@Override
protected void configureHttpContainer() {
container = ContainerFactory.createContainer(GrizzlyHttpContainer.class, getApplication().getConfig());
ServerConfiguration serverConfiguration = httpServer.getServerConfiguration();
serverConfiguration.setSendFileEnabled(true);
String charset = StringUtils.defaultIfBlank((String) getApplication().getProperty("app.encoding"), "utf-8");
serverConfiguration.setDefaultQueryEncoding(Charset.forName(charset));
GrizzlyHttpContainer httpHandler = container;
httpHandler.setRequestURIEncoding(charset);
serverConfiguration.addHttpHandler(httpHandler);
}
@Override
public ServerContainer getWebSocketContainer() {
return webSocketServerContainer;
}
@Override
protected void configureWebSocketContainerProvider() {
webSocketServerContainerProvider = new WebSocketContainerProvider() {
@Override
public void dispose(ServerContainer serverContainer) {
if (serverContainer instanceof org.glassfish.tyrus.spi.ServerContainer)
((org.glassfish.tyrus.spi.ServerContainer) serverContainer).stop();
}
};
}
@Override
protected WebSocketContainerProvider getWebSocketContainerProvider() {
return webSocketServerContainerProvider;
}
@Override
protected void doReload() {
WebSocketServerContainer old = null;
if (webSocketEnabled) {
old = webSocketServerContainer;
buildWebSocketContainer();
}
final Application application = getApplication();
container.reload(new Callable() {
@Override
public ResourceConfig call() throws Exception {
application.reconfigure();
registerBinder(application.getConfig());
return application.getConfig();
}
});
if (webSocketServerContainer != null && old != null)
try {
old.stop();
webSocketServerContainer.start(old.getContextPath(), old.getPort());
} catch (IOException | DeploymentException e) {
throw new WebSocketException("reload web socket endpoint error", e);
}
}
@Override
public void doStart() {
try {
httpServer.start();
} catch (IOException e) {
throw new AmebaException("端口无法使用", e);
}
}
@Override
public void doShutdown() throws Exception {
httpServer.shutdown().get();
}
@Override
public List getConnectors() {
return connectors;
}
@Override
public String getType() {
return TYPE_NAME;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy