1. 说明:依旧使用tomcat作为容器,Jetty在这里只作为开发时测试方便,所以采取工具类形式,而非下载Jetty容器包配置方式。
2. 为什么要用Jetty?
此处用Jetty只是方便测试,运行个main方法即可启动Jetty容器,然后就可以调用接口和访问jsp等页面。无需启动tomcat,个人认为Jetty启动速度远快于tomcat。所以方便测试,更改代码只需要重新运行main方法即可。(Jetty自带热部署)
3. 如何使用?
-
pom.xml定义如下
org.eclipse.jetty.aggregate
jetty-all-server
8.1.18.v20150929
org.eclipse.jetty
jetty-jsp
8.1.18.v20150929
-
工具类
package test.bshf.clinic.util;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Scanner;
import org.eclipse.jetty.webapp.WebAppContext;
import javax.management.MBeanServer;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.List;
public class JettyServerStarter {
private int port;
private String context;
private String webappPath;
private int scanIntervalSeconds;
private boolean jmxEnabled;
private Server server;
private WebAppContext webapp;
public JettyServerStarter(String webappPath, int port, String context) {
this(webappPath, port, context, 0, false);
}
public JettyServerStarter(String webappPath, int port, String context, int scanIntervalSeconds, boolean jmxEnabled) {
this.webappPath = webappPath;
this.port = port;
this.context = context;
this.scanIntervalSeconds = scanIntervalSeconds;
this.jmxEnabled = jmxEnabled;
validateConfig();
}
private void validateConfig() {
if (port < 0 || port > 65536) {
throw new IllegalArgumentException("Invalid port of web server: " + port);
}
if (context == null) {
throw new IllegalStateException("Invalid context of web server: " + context);
}
if (webappPath == null) {
throw new IllegalStateException("Invalid context of web server: " + webappPath);
}
}
public void start() {
if (server == null || server.isStopped()) {
try {
doStart();
} catch (Throwable e) {
e.printStackTrace();
System.err.println("System.exit() ......");
System.exit(1);
}
} else {
throw new RuntimeException("Jetty Server already started.");
}
}
private void doStart() throws Throwable {
if (!portAvailable(port)) {
throw new IllegalStateException("port: " + port + " already in use!");
}
System.setProperty("org.eclipse.jetty.util.URI.charset", "UTF-8");
System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.Slf4jLog");
System.setProperty("org.eclipse.jetty.server.Request.maxFormContentSize", "20000000");
server = new Server(port);
server.setHandler(getHandler());
if (jmxEnabled) {
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
MBeanContainer mBeanContainer = new MBeanContainer(mBeanServer);
server.addBean(mBeanContainer);
}
if (scanIntervalSeconds > 0) {
startFileWatchScanner();
}
long ts = System.currentTimeMillis();
server.start();
ts = System.currentTimeMillis() - ts;
System.err.println("Jetty Server started: " + String.format("%.2f sec", ts / 1000d));
server.join();
}
protected Handler getHandler(){
webapp = new WebAppContext(webappPath, context);
return webapp;
}
private void startFileWatchScanner() throws Exception {
List scanList = new ArrayList();
scanList.add(new File(webappPath, "WEB-INF"));
Scanner scanner = new Scanner();
scanner.setReportExistingFilesOnStartup(false);
scanner.setScanInterval(scanIntervalSeconds);
scanner.setScanDirs(scanList);
scanner.addListener(new Scanner.BulkListener() {
@SuppressWarnings("rawtypes")
public void filesChanged(List changes) {
try {
System.err.println("Loading changes ......");
webapp.stop();
webapp.start();
System.err.println("Loading complete.\n");
} catch (Exception e) {
System.err.println("Error reconfiguring/restarting webapp after change in watched files");
e.printStackTrace();
}
}
});
System.err.println("Starting scanner at interval of " + scanIntervalSeconds + " seconds.");
scanner.start();
}
private static boolean portAvailable(int port) {
if (port <= 0) {
throw new IllegalArgumentException("Invalid start port: " + port);
}
ServerSocket ss = null;
DatagramSocket ds = null;
try {
ss = new ServerSocket(port);
ss.setReuseAddress(true);
ds = new DatagramSocket(port);
ds.setReuseAddress(true);
return true;
} catch (IOException e) {
} finally {
if (ds != null) {
ds.close();
}
if (ss != null) try {
ss.close();
} catch (IOException e) {
}
}
return false;
}
}
-
主方法
package test.bshf.clinic.demo;
import test.bshf.clinic.util.JettyServerStarter;
/**
* 启动jetty容器
*
*/
public class JettyStarterTest {
public static void main(String[] args) {
String webapp = "src/main/webapp";
new JettyServerStarter(webapp, 8012, "/clinic-demo").start();
}
}
解释说明:
pom和工具类直接复制粘贴
主方法
-
String webapp = "src/main/webapp";
: 是当前web项目的webapp这层目录结构(因为里面包含了class和页面等) -
new JettyServerStarter(webapp, 8012, "/clinic-demo").start();
new 一个Jetty容器,第一个参数是webapp地址,第二个参数是端口号(自定义),第三个参数是当前web项目名称。 -
访问路径:http://localhost:8012(自定义Jetty的端口)/clinic-demo
若有兴趣,欢迎来加入群,【Java初学者学习交流群】:458430385,此群有Java开发人员、UI设计人员和前端工程师。有问必答,共同探讨学习,一起进步!
欢迎关注我的微信公众号【Java码农社区】,会定时推送各种干货: