嵌入式Jetty Web开发

前端时间为了快速迭代一些工具类应用,选择嵌入式Jetty作为web容器,现将配置记录如下。

POM配置

添加Jetty和springMVC的依赖包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<properties>
<org.springframework.version>3.2.2.RELEASE</org.springframework.version>
<jetty.version>9.2.9.v20150224</jetty.version>
</properties>

<!-- jetty dependency-->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>

<!-- springmvc dependency-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>

目录结构

创建一个Maven Web工程,项目结构如下图所示:

project_structure.png
  • applicationContext.xml:spring配置文件
  • log4j.xml:log4j配置文件
  • mvc-context.xml:mvc配置文件
  • toolbox.xml:velocity工具配置文件
  • web.xml:web工程配置文件,将平时以classpath:指定文件位置替换成/WEB_INF/

springMVC的配置跟平常配置一样,无需变化。

嵌入式Jetty

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import java.io.File;
import java.net.URL;
import java.security.ProtectionDomain;

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.webapp.WebAppContext;

public class JettyBootstrap {

public static final int PORT = 8080;
public static final String CONTEXT = "/";
private static final String DEFAULT_WEBAPP_PATH = "src/main/webapp";

/**
* 创建用于生产环境的Jetty Server
*/

public static Server createProdServer(int port, String contextPath) {
Server server = new Server(port);
server.setStopAtShutdown(true);

ProtectionDomain protectionDomain = JettyBootstrap.class.getProtectionDomain();
URL location = protectionDomain.getCodeSource().getLocation();

String warFile = location.toExternalForm();
System.out.println("war file path:"+warFile);
WebAppContext context = new WebAppContext(warFile, contextPath);
context.setServer(server);

// 设置work dir,war包将解压到该目录,jsp编译后的文件也将放入其中。
String currentDir = new File(location.getPath()).getParent();
File workDir = new File(currentDir, "work");
context.setTempDirectory(workDir);

server.setHandler(context);
return server;
}

/**
* 创建用于开发运行调试的Jetty Server, 以src/main/webapp为Web应用目录.
*/

public static Server createDevServer(int port, String contextPath) {
Server server = new Server();
// 设置在JVM退出时关闭Jetty的钩子。
server.setStopAtShutdown(true);

//这是http的连接器
ServerConnector connector = new ServerConnector(server);
connector.setPort(port);
// 解决Windows下重复启动Jetty居然不报告端口冲突的问题.
connector.setReuseAddress(false);
server.setConnectors(new Connector[] { connector });

WebAppContext webContext = new WebAppContext(DEFAULT_WEBAPP_PATH, contextPath);
//webContext.setContextPath("/");
webContext.setDescriptor("src/main/webapp/WEB-INF/web.xml");
// 设置webapp的位置
webContext.setResourceBase(DEFAULT_WEBAPP_PATH);
webContext.setClassLoader(Thread.currentThread().getContextClassLoader());
server.setHandler(webContext);
return server;
}

/**
* 启动jetty服务
*
* @param port
* @param context
*/

public void startJetty(int port, String context, String env) {
Server server = null;
if ("dev".equals(env)) {
server= JettyBootstrap.createDevServer(port, context);
}else {
server= JettyBootstrap.createProdServer(port, context);
}
try {
server.stop();
server.start();
server.join();
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}

public static void main(String[] args) {
new JettyBootstrap().startJetty(8888, "/","dev");
}

}

到此为止,如果实在Eclipse中进行开发的话,可以运行JettyBootstrap启动应用。

打包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<archive>
<manifest>
<mainClass>com.javan.pbgen.jetty.JettyBootstrap</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>main-class-placement</id>
<phase>prepare-package</phase>
<configuration>
<target>
<move todir="${project.build.directory}/${project.artifactId}/">
<fileset dir="${project.build.directory}/classes/">
<include name="**/*/JettyBootstrap.class" />
</fileset>
</move>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>jetty-classpath</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty, javax.servlet</includeGroupIds>
<includeScope>provided</includeScope>
<!-- remove some files in order to decrease size -->
<excludes>*, META-INF/*</excludes>
<outputDirectory>
${project.build.directory}/${project.artifactId}
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- to support compilation in linux -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<target>1.7</target>
<source>1.7</source>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
  • maven-war-plugin:负责打包,并设置Main方法实现类为com.jetty.JettyBootstrap
  • maven-antrun-plugin:执行ant的target任务,将com.jetty.JettyBootstrap类转移到war包的根路径下
  • maven-dependency-plugin:负责将jetty相关的jar包进行拆包并重新输出到war包根路径下,以便重新打包
  • maven-compiler-plugin:负责编译web应用

运行mvn打包

1
mvn package -Pstandalone

运行

通过如下命令运行war包

1
nohup java -Xms512m -Xmx512m -XX:MaxPermSize=96m -jar xxx.war &