一、簡介
傳統的Web開發大部分是開發好web程序,通過打成war等程序包發佈到web容器中部署。Jetty其實也可以像tomcat那樣作爲容器,將程序打包放在其中進行啓動,但是我們這裏主要是爲了簡化開發的操作,直接嵌入jetty
啓動項目。
二、開發環境
1、由於分佈式的興起,代碼複用變得很重要,我這邊會把Jetty啓動項目的代碼做一個module,最後打包成jar包,方便其他使用它的項目依賴使用。
2、 項目結構,該結構是項目的模塊化,可以參考一下http://juvenshun.iteye.com/blog/305865
我也正在學習分佈式的項目,還沒開始多久,項目的地址https://github.com/lili1990/learning.git
3、learning-common-jetty的依賴pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>learning-common</artifactId>
<groupId>com.app</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>learning-common-jetty</name>
<groupId>com.app</groupId>
<artifactId>learning-common-jetty</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.app</groupId>
<artifactId>learning-common-main</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp</artifactId>
<version>9.2.9.v20150224</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.2.9.v20150224</version>
</dependency>
<!-- 使用jstp 不知道jetty爲啥非得和這個一起纔不會報錯-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
</dependencies>
</project>
4、JettyServer的具體代碼
package app.server;
import app.utils.ServerProperties;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
/**
* Created by lili19289 on 2016/8/4.
*/
public class JettyServer {
private static final Logger LOGGER = Logger.getLogger(JettyServer.class);
private static final String PROP_NAME__PREFIX = "jetty.";
private static final String PROP_NAME_CONTEXT_PATH = PROP_NAME__PREFIX + "contextPath";
private static final String PROP_NAME_WEBAPP_PATH = PROP_NAME__PREFIX + "webappPath";
private static final String PROP_NAME_HOST = PROP_NAME__PREFIX + "host";
private static final String PROP_NAME_PORT = PROP_NAME__PREFIX + "port";
private static int port;
private String contextPath;
private String webappPath;
private Server server;
private WebAppContext webapp;
/**
* 創建用於開發運行調試的Jetty Server, 以src/main/webapp爲Web應用目錄.
*/
public static void main(String[] args) {
String contextPath = System.getProperty(PROP_NAME_CONTEXT_PATH);
if (StringUtils.isBlank(contextPath)) {//項目啓動後 直接IP:port/就可以訪問,因此在這裏不進行配置
contextPath = ServerProperties.getProperty(PROP_NAME_CONTEXT_PATH);
}
String webappPath = System.getProperty(PROP_NAME_WEBAPP_PATH);
if (StringUtils.isBlank(webappPath)) {//web.xml的路徑,在idea中設置
webappPath = ServerProperties.getProperty(PROP_NAME_WEBAPP_PATH);
}
String portString = System.getProperty(PROP_NAME_PORT);
if (StringUtils.isBlank(portString)) {//項目的端口,在每個項目的conf文件夾下的配置文件中設置
portString = ServerProperties.getProperty(PROP_NAME_PORT);
}
int port = 0;
try {
port = Integer.parseInt(portString);
} catch (Exception e) {
e.printStackTrace();
throw new IllegalArgumentException(PROP_NAME_PORT + " should be an integer between 1 and 65535");
}
JettyServer jettyServer = new JettyServer(contextPath, webappPath, port);
jettyServer.start();
}
public JettyServer(String contextPath, String webappPath, int port) {
if (StringUtils.isBlank(contextPath)) {
this.contextPath = "";
}else{
this.contextPath = contextPath;
}
if (StringUtils.isBlank(webappPath)) {
throw new IllegalArgumentException("webappPath is required");
}else{
this.webappPath = webappPath;
}
this.port = port;
}
public void start() {
if (null == server || server.isStopped()) {
doStart();
} else {
throw new IllegalStateException("JettyServer already started.");
}
}
private void doStart() {
if (!checkServerPortAvailable()) {
throw new IllegalStateException("Server port already in use: " + port);
}
webapp = new WebAppContext(webappPath, contextPath);
server = new Server(port);
server.setHandler(webapp);
try {
long st = System.currentTimeMillis();
server.start();
long sp = System.currentTimeMillis() - st;
System.out.println("JettyServer started: " + String.format("%.2f sec", sp / 1000D)+",the port is ==="+port+"");
server.join();
}catch (Exception e){
e.printStackTrace();
LOGGER.error("JettyServer started failed!");
}
}
private boolean checkServerPortAvailable() {
if (0 < port) {
ServerSocket ss = null;
try {
ss = new ServerSocket(port, 0, null);
} catch (Exception e) {
LOGGER.error("check serverPort failed", e);
return false;
} finally {
if (null != ss) {
try {
ss.close();
} catch (IOException e) {
LOGGER.error("close ServerSocket failed", e);
}
}
}
} else {
throw new IllegalArgumentException("Invalid port " + port);
}
return true;
}
}
package app.utils;
import app.utils.EnvivironmentUtil;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//讀取配置文件
public class ServerProperties {
private static final Logger LOGGER = LoggerFactory.getLogger(ServerProperties.class);
private static final String FILE_NAME = "/conf/server.properties";
private static Properties prop;
public ServerProperties() {
}
private static void init() {
String filePath = EnvivironmentUtil.getClassPath() + "/conf/server.properties";
FileInputStream ins = null;
try {
ins = new FileInputStream(filePath);
prop = new Properties();
prop.load(ins);
} catch (FileNotFoundException var7) {
LOGGER.error("Can not find server properties, it may result working problem. path: " + filePath, var7);
} catch (Exception var8) {
LOGGER.error("init server properties failed", var8);
} finally {
IOUtils.closeQuietly(ins);
}
}
public static String getProperty(String key) {
return null != prop?prop.getProperty(key):null;
}
static {
init();
}
}
5、在項目中使用該Server,下面以spring這個項目爲例子
其他的配置與正常的spring項目一樣,只是需要在idea中配置才能正常啓動
配置文件 conf/server.properties 中配置
jetty.port=9001,這個端口你可以隨意修改
在idea中配置,
創建一個Application後進行配置
直接運行該項目即可了,由於目前還處於自己學習的階段,沒有部署到服務器上,具體服務器怎麼啓動還沒有去研究,等之後會繼續完善。