2
Executable War
Calvin Xiao edited this page 2013-11-14 19:06:57 -08:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

##Overview 看ThoughtWorks的技术雷达,里面提到了Micro-Service和Embedded Jetty。大家越来越喜欢用一个嵌入式Jetty加一个嵌入式的H2,不用依赖任何Container,就可以启动一个应用了。

这种嵌入式Embedded有两种风格:

一种是提供一个Zip包,里面有一个bin目录放着jsw(Java Service Wrapper),一个lib目录放着Jetty的jar,一个webapp目录放着真正的应用,一个conf目录放着jetty和jsw的配置文件。用户解开zip包后进入bin目录就可以简单的start/stop应用。像ActiveMQ, Solr, Nexus, Sonar等都是这个风格。

另一种更简洁,把jetty的jar包解开成class放入war包里,再放一个Main class进去,用户用java -jar xxxx.war 就可以启动应用,像Jenkins,Selenium的Server等都是这种风格。

在SpringSide的showcae项目里,演示了后一种风格,同样原理也可以自行制作第一种风格的包。

##打包 在showcase里,使用如下,就会在target目录生成一个showcase.war和一个showcase-xxx.standalone.war.

mvn package -Pstandalone
  1. 观察一下showcase的pom.xml,依赖的Jetty包定义成provided,既可以用来编译Main.java,又不会打包到WEB-INF/lib中. 然后定义了一个runtime级别的jstl.1.2.jar,因为Jetty用的那个Jasper的编译器只懂得从WEB-INF/lib下的jar里的META-INF中找tld,而不能从war的/META-INF中找。

  2. 然后是pom.xml里的standalone profile,可以看到是使用assembly插件实现showcase-4.xx.standalone.war的打包。

  3. 再观察assembly-standalone.xml:
    首先把org.eclipse.jetty*:* 及其依赖的包,全部解开class来, 然后打包war包里(注意要exclude掉META-INF里的内容,否则那些*.RDA之类的文件会报jar包签名错之类的错)。
    然后把原来war包里的内容同样copy到war包里。
    最后从classes中将一个Main.class也copy到war包中。

  4. 再回到pom.xml里,assembly插件还会修改war包里的META-INF/Manifest.mf,设置main class为刚才那个Main class。

最后再看一下Main.class的实现:

  System.setProperty("org.apache.jasper.compiler.disablejsr199", "true");

设置环境变量可确定使用Eclipse的JDT,而不是JDK的compiler来编译JSP。Jetty7.5后默认使用JDK Compiler,但我的机器上老是报NoJDK,郁闷死。

ProtectionDomain protectionDomain = Main.class.getProtectionDomain();
URL location = protectionDomain.getCodeSource().getLocation();
String warFile = location.toExternalForm();

神奇的语句,可以通过Main.class找到war包的路径。

String currentDir = new File(location.getPath()).getParent();
File workDir = new File(currentDir, "work");
context.setTempDirectory(workDir);

设置work dir,war包将解压到该目录,jsp编译后的文件也将放入其中。

##运行

用java -jar xxx.war -Dport=8082 可以简单的在8082端口(默认为8080)运行应用,如果要设置其他JVM参数

java-Xms2048m -Xmx2048m -XX:MaxPermSize=128m -jar xxx.war -Dport=8082

Tomcat

Tomcat的Maven Plugin自带打运行包的功能耶。使用如下命令可以在target目录生成一个showcase-xxx-standalone-tomcat.jar,不过暂时有H2 Driver找不到的问题

mvn package -Pstandalone-tomcat