Last active
December 20, 2015 03:18
-
-
Save monzou/6062166 to your computer and use it in GitHub Desktop.
Jetty + Yeoman : http://qiita.com/monzou/items/eb5f25ae9b9925d3c63e
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
package com.usopla.gist; | |
import static com.google.common.base.Preconditions.checkNotNull; | |
import java.io.IOException; | |
import java.net.URL; | |
import javax.annotation.Nullable; | |
import com.fasterxml.jackson.core.JsonParseException; | |
import com.fasterxml.jackson.databind.JsonMappingException; | |
import com.fasterxml.jackson.databind.ObjectMapper; | |
import com.fasterxml.jackson.databind.ObjectReader; | |
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; | |
/** | |
* コンフィギュレーションをロードするユーティリティです。 | |
* <p> | |
* YAML および JSON 形式に対応します。 | |
* | |
* @author monzou | |
*/ | |
public final class ConfigurationLoader { | |
/** | |
* コンフィギュレーションをロードします。 | |
* | |
* @param <T> コンフィギュレーションのマッピング対象の型 | |
* @param type コンフィギュレーションのマッピング対象の型 | |
* @param configurationName コンフィギュレーションファイルの名称 | |
* @return コンフィギュレーション | |
* @throws IOException コンフィギュレーションのロードに失敗した場合にスローされます。 | |
*/ | |
public static <T> T load(Class<T> type, String configurationName) throws IOException { | |
return load(type, configurationName, null); | |
} | |
/** | |
* コンフィギュレーションをロードします。 | |
* | |
* @param <T> コンフィギュレーションのマッピング対象の型 | |
* @param type コンフィギュレーションのマッピング対象の型 | |
* @param configurationName コンフィギュレーションファイルの名称 | |
* @param defaultConfigurationName デフォルトコンフィギュレーションファイルの名称 | |
* @return コンフィギュレーション | |
* @throws IOException コンフィギュレーションのロードに失敗した場合にスローされます。 | |
*/ | |
public static <T> T load(Class<T> type, String configurationName, @Nullable String defaultConfigurationName) throws IOException { | |
ClassLoader classLoader = ConfigurationLoader.class.getClassLoader(); | |
String base = defaultConfigurationName == null ? configurationName : defaultConfigurationName; | |
String overwrite = defaultConfigurationName == null ? null : configurationName; | |
try { | |
ObjectMapper mapper = mapper(base); | |
T configuration = mapper.readValue(url(classLoader, base), type); | |
if (overwrite != null) { | |
ObjectReader reader = mapper.readerForUpdating(configuration); | |
reader.withType(type).readValue(url(classLoader, overwrite)); | |
} | |
return configuration; | |
} catch (JsonParseException | JsonMappingException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private static URL url(ClassLoader classLoader, String baseName) { | |
URL url = classLoader.getResource(checkNotNull(baseName)); | |
if (url == null) { | |
throw new IllegalArgumentException("resource not found: " + baseName); | |
} | |
return url; | |
} | |
private static ObjectMapper mapper(String baseName) { | |
if (baseName.endsWith(".yml") || baseName.endsWith(".yaml")) { | |
return new ObjectMapper(new YAMLFactory()); | |
} else if (baseName.endsWith(".json")) { | |
return new ObjectMapper(); | |
} | |
throw new IllegalArgumentException("unexpected baseName: " + baseName); | |
} | |
private ConfigurationLoader() { | |
} | |
} |
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
port: 9000 | |
webapp: | |
dir: ../application-web | |
static: | |
dir: ../web-assets | |
resources: | |
- .tmp | |
- app |
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
port: 9000 | |
webapp: | |
dir: ../application-web | |
static: | |
dir: ../web-assets | |
resources: | |
- dist |
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
package com.usopla.gist; | |
import java.lang.Thread.UncaughtExceptionHandler; | |
import java.util.List; | |
import com.usopla.gist.ConfigurationLoader; | |
import org.eclipse.jetty.plus.webapp.EnvConfiguration; | |
import org.eclipse.jetty.plus.webapp.PlusConfiguration; | |
import org.eclipse.jetty.server.Server; | |
import org.eclipse.jetty.util.resource.ResourceCollection; | |
import org.eclipse.jetty.webapp.Configuration; | |
import org.eclipse.jetty.webapp.FragmentConfiguration; | |
import org.eclipse.jetty.webapp.MetaInfConfiguration; | |
import org.eclipse.jetty.webapp.WebAppContext; | |
import org.eclipse.jetty.webapp.WebInfConfiguration; | |
import org.eclipse.jetty.webapp.WebXmlConfiguration; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import com.fasterxml.jackson.annotation.JsonProperty; | |
import com.google.common.base.Function; | |
import com.google.common.collect.Collections2; | |
import com.google.common.collect.Lists; | |
/** | |
* 埋め込みの Jetty サーバを利用してスタンドアローンで起動する Web アプリケーションです。 | |
* | |
* @author monzou | |
*/ | |
public class JettyLauncher { | |
private static final Logger LOGGER = LoggerFactory.getLogger(JettyLauncher.class); | |
static { | |
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { | |
@Override | |
public void uncaughtException(Thread t, Throwable e) { | |
LOGGER.error("uncaught exception occurred.", e); | |
exit(false); | |
} | |
}); | |
} | |
/** | |
* Web アプリケーションのエントリポイントです。 | |
* | |
* @param args 引数 | |
* @throws Exception サーバ起動中に発生した例外 | |
*/ | |
public static void main(String[] args) throws Exception { | |
if (args.length != 1) { | |
throw new IllegalArgumentException("usage: you have to specify environment (`development` or `production`)."); | |
} | |
try { | |
JettyLauncher launcher = new JettyLauncher(args[0]); | |
launcher.launch(); | |
} catch (Throwable t) { | |
LOGGER.error("failed to start server.", e); | |
exit(false); | |
} | |
} | |
private static void exit(boolean normally) { | |
System.exit(normally ? 0 : -1); | |
} | |
private final String environment; | |
private JettyLauncher(String environment) { | |
this.environment = environment; | |
} | |
private void launch() throws Exception { | |
Config config = ConfigurationLoader.load(Config.class, String.format("jetty-%s.yml", environment)); | |
final WebApplication webapp = new WebApplication(config); | |
Thread shutdownHook = new Thread("shutdown-hook") { | |
@Override | |
public void run() { | |
try { | |
webapp.stop(); | |
} catch (Throwable t) { | |
LOGGER.error("unknown error occurred.", t); | |
} | |
} | |
}; | |
Runtime.getRuntime().addShutdownHook(shutdownHook); | |
webapp.boot(); | |
} | |
private static class WebApplication { | |
private final Config config; | |
private Server server; | |
WebApplication(Config config) { | |
this.config = config; | |
} | |
void boot() throws Exception { | |
server = new Server(config.port); | |
server.setHandler(createContext()); | |
server.start(); | |
server.join(); | |
} | |
private WebAppContext createContext() { | |
WebAppContext context = new WebAppContext(); | |
context.setConfigurations(new Configuration[] { // | |
new WebXmlConfiguration() // | |
, new WebInfConfiguration() // | |
, new PlusConfiguration() // | |
, new MetaInfConfiguration() // | |
, new FragmentConfiguration() // | |
, new EnvConfiguration() // | |
}); | |
context.setContextPath("/"); | |
context.setDescriptor(config.webapp.path("src/main/webapp/WEB-INF/web.xml")); | |
context.setBaseResource(new ResourceCollection(config.www.resources())); | |
context.setParentLoaderPriority(true); | |
context.setInitParameter("org.eclipse.jetty.servlet.Default.cacheControl", "max-age=0, public"); // 静的ファイルをキャッシュしないようにする | |
context.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false"); // Windows で静的ファイルがロックされてしまう問題に対応 | |
return context; | |
} | |
void stop() throws Exception { | |
if (server != null) { | |
try { | |
server.stop(); | |
} finally { | |
server = null; | |
} | |
} | |
} | |
} | |
private static class Config { | |
public int port; | |
public WebApp webapp; | |
@JsonProperty("static") | |
public Static www; | |
static class WebApp { | |
public String dir; | |
String path(String relative) { | |
return String.format("%s/%s", dir, relative); | |
} | |
} | |
static class Static implements Function<String, String> { | |
public String dir; | |
public List<String> resources = Lists.newArrayList(); | |
String[] resources() { | |
return Collections2.transform(resources, Static.this).toArray(new String[resources.size()]); | |
} | |
/** {@inheritDoc} */ | |
@Override | |
public String apply(String relative) { | |
return String.format("%s/%s", dir, relative); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment