jetty で vhost でいい感じにアプリケーション動かしていく
jetty で vhost 使う方法みたいな話が、意外と情報ない。
例えば、web 画面と admin 画面があるようなサイトで、実際には vhost を利用して運用したいという場合、一般的な ide や servlet container の想定では PATH_INFO でアプリケーションを切り替えて頑張る、みたいなのが多いのだが、こういったアプローチはあまり現代的ではないと思う。
named vhost でやりたいよ!!
最近、以下のような構造のでアプリケーションを構築している。
- pom.xml
+ common ← jar
- pom.xml
+ admin ← war
- pom.xml
- src/main/webapp/WEB-INF/web.xml
+ web ← war
- pom.xml
- src/main/webapp/WEB-INF/web.xml
このような状況で、local で開発したいというシナリオだと思いねえ。
ってわけで、jetty でやるには、vhost を設定したWebAppContext を HandlerCollection に詰め込んでハンドラとして設定すればよろしい。
private Server startServer(int port) throws Exception {
Server server = new Server(port);
HandlerCollection handler = new HandlerCollection();
for (final String module : Arrays.asList("web", "admin")) {
handler.addHandler(createContext(module));
}
server.setHandler(handler);
server.start();
return server;
}
それで、WebAppContext は以下のような形で作れば、IntelliJ から起動する分には意外といい感じに動く。mvn exec:java からだとなんかうまくイカなくて困ってるけど。。本当は war を作って explode したほうが正しいが、そのへん工夫してる暇ないのでこういう感じになっている。
private WebAppContext createContext(String module) throws Exception {
String descriptorPath = appBase + "/" + module + "/src/main/webapp/WEB-INF/web.xml";
if (!new File(descriptorPath).exists()) {
log.error("There is no {}", descriptorPath);
throw new RuntimeException("Invalid descriptor path: " + descriptorPath);
}
String resourcePath = appBase + "/" + module + "/src/main/webapp/";
if (!new File(resourcePath).exists()) {
log.error("There is no {}", resourcePath);
throw new RuntimeException("Invalid resourcePath " + resourcePath);
}
String hostname = module + "-proj.example.com";
log.info("Starting {} server: {}, {}, {}", module, descriptorPath, resourcePath, hostname);
WebAppContext context = new WebAppContext();
context.setDescriptor(descriptorPath);
context.setResourceBase(resourcePath);
context.setContextPath("/");
context.setParentLoaderPriority(true);
context.setVirtualHosts(new String[] {hostname});
return context;
}