一啊终、簡要介紹
最近做的項目用到了嵌入式Jetty當服務(wù)器疑苔,并用Jersey來構(gòu)建Restful api甫匹,看了老師的項目文件發(fā)現(xiàn)還有pom.xml文件,才知道Maven。但因為不是一個組的老師兵迅,而且那個老師貌似前端精通的多一點抢韭,Maven什么的也不是很了解,從老師那里學(xué)的東西也不是很多恍箭。因為項目相關(guān)刻恭,最后還是自己Google各種資料,一點一滴從零開始學(xué)習(xí)扯夭。國內(nèi)關(guān)于嵌入式Jetty的資料真的少鳍贾,大部分都是翻譯官方文檔,很難找到完整的案例交洗。因此骑科,想在這里把自己學(xué)到的關(guān)于Embedded Jetty、Jersy的知識記錄下來构拳,希望提能給想入坑的提供點經(jīng)驗咆爽,少走點彎路。
二置森、環(huán)境需求
文中介紹的東西都是基于JDK1.8伍掀、Maven3、IDEA2017.2暇藏,Jetty版本為9.4.3.v20170317蜜笤,Jersey版本為2.25.1。
三盐碱、具體步驟
1把兔、新建maven空項目
打開IDEA,新建一個Project瓮顽,選擇Maven項目县好,然后填寫一些基本信息,最后新建的項目如下圖所示
可以看到新建的項目除了
/src/main/java
代碼包和/src/main/resources
資源包之外暖混,還多了一個pom.xml
的文件缕贡,Maven項目中對項目的管理配置都在pom.xml
文件中進行,主要包括添加jar包依賴拣播,對項目進行清理打包構(gòu)建等等晾咪。
2、添加輔助框架
右鍵項目名稱贮配,然后點擊Add Framework Support
谍倦。
左側(cè)選中
WebService
,右側(cè)選中Set up library later
泪勒,然后點擊OK
昼蛀。添加完成后宴猾,會在項目的結(jié)構(gòu)樹中看到多出
/web
目錄,并在/src/main/java
包中多出一個example
叼旋,紅色的/target
目錄是編譯文件夾仇哆,編譯后的class文件都在里面。3夫植、添加jar包依賴
我們將example
包整個刪除讹剔,然后打開pom.xml
,添加Rest項目需要的jar包依賴偷崩,在Maven項目中辟拷,當你需要引入jar包時撞羽,只需要在pom.xml
文件中填上所需jar包的Maven坐標即可阐斜,Maven坐標由三部分組成,分別是groupId
,artifactId
,version
诀紊,形式如下:
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.25.1</version>
當在Maven項目中引入jar包依賴時谒出,只需要按照如下形式,把坐標放在一個<dependency></dependency>
標簽中即可邻奠,多個依賴放在一個<dependencys></dependencys>
標簽中笤喳。
本項目中所用到的所有依賴關(guān)系如下所示:
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<version>2.25.1</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.3.v20170317</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.4.3.v20170317</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.4.3.v20170317</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
</dependency>
</dependencies>
4、搭建Embedded Jetty服務(wù)器
在/src/main/java
中新建包com.heu.cs.jettyserver
碌宴,在包中新建類JettyServer
杀狡,寫入代碼
package com.heu.cs.jettyserver;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class JettyServer {
public static void main(String[] args) throws Exception {
Server jettyServer = new Server();
HttpConfiguration http_config = new HttpConfiguration();
/**
*http_config可以對服務(wù)器進行配置,比如設(shè)置https,BufferSize等等
* http_config.setSecureScheme("https");
* http_config.setSecurePort(8443);
* http_config.setOutputBufferSize(32768);
* http_config.setRequestHeaderSize(8192);
* http_config.setResponseHeaderSize(8192);
*/
http_config.setSendServerVersion(true);
http_config.setSendDateHeader(false);
/**
* 新建http連接來設(shè)置訪問端口贰镣,超時時間等等呜象。
*/
ServerConnector httpServer = new ServerConnector(jettyServer,
new HttpConnectionFactory(http_config));
httpServer.setPort(7012);
httpServer.setIdleTimeout(120000);
jettyServer.addConnector(httpServer);
/**
* 設(shè)置整個web服務(wù)的根url,/ 表示 localhost:7012/ 之后地址的是可訪問的
*/
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
/**
* 添加動態(tài)servlet路徑碑隆,處理我們自己寫的動態(tài)的servlet
*/
ServletHolder jerseyServlet = context.addServlet(
org.glassfish.jersey.servlet.ServletContainer.class, "/webapi/*");
jerseyServlet.setInitOrder(1);
// Tells the Jersey Servlet which REST api/class to load.設(shè)置動態(tài)servlt加載的包
jerseyServlet.setInitParameter("jersey.config.server.provider.packages", "com.heu.cs.api");
//也可單獨設(shè)置加載某個類恭陡,
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames",
"UploadFileService;org.glassfish.jersey.media.multipart.MultiPartFeature");
/**
* 添加默認的servlet路徑,處理不在動態(tài)servlet路徑中的地址上煤,一般都是一些可供訪問的靜態(tài)html,css,js資源文件
*/
ServletHolder staticServlet = context.addServlet(DefaultServlet.class, "/static/*");
staticServlet.setInitParameter("resourceBase", "src/main/resources");
staticServlet.setInitParameter("pathInfoOnly", "true");
/**
* Embedded Jetty還可以直接當作服務(wù)器休玩,在上面部署已經(jīng)發(fā)布的war包,這方面的資料國內(nèi)挺多的劫狠,就不累述
*
* 其次拴疤,在我們的項目中是沒有用到web.xml文件來進行webappde的配置,因為上面的設(shè)置并不能使得服務(wù)器訪問web.xml独泞,
* 如果需要用到web.xml遥赚,則需要new一個WebAppContext,并對其進行配置,同時在下面的handlers中加上webAppContext
* WebAppContext webAppContext = new WebAppContext();
* 設(shè)置描述符位置
* webAppContext.setDescriptor("./web/WEB-INF/web.xml");
* 設(shè)置Web內(nèi)容上下文路徑
* webAppContext.setResourceBase("./web");
* 設(shè)置上下文路徑
* webAppContext.setContextPath("/");
* webAppContext.setParentLoaderPriority(true);
*/
HandlerCollection handlers = new HandlerCollection();
// handlers.setHandlers(new Handler[]{context,webAppContext});
handlers.setHandlers(new Handler[]{context});
jettyServer.setHandler(handlers);
try {
jettyServer.start();
jettyServer.join();
} finally {
jettyServer.destroy();
}
}
}
5阐肤、訪問靜態(tài)資源
至此凫佛,一個簡單的Embedded Jetty服務(wù)器已經(jīng)搭建完成讲坎,當我們需要啟動服務(wù)器時,只需秩序JettyServer
中的main
方法即可愧薛。
項目中靜態(tài)資源的訪問根URL是http://localhost:7012/static/
晨炕,我們在/src/main/resources
目錄下新建一些js、css毫炉、html文件瓮栗,然后啟動服務(wù)器
然后在瀏覽器中輸入
http://localhost:7012/static/
即可訪問到這些文件
6、訪問動態(tài)Api
我們在前面實現(xiàn)了訪問靜態(tài)資源瞄勾,如果說想實現(xiàn)訪問動態(tài)資源费奸,譬如我想訪問動態(tài)URL路徑下的某個Apihttp://localhost:7012/webapi/demo
,該如何實現(xiàn)呢进陡?
在JettyServer
中我們已經(jīng)設(shè)置了動態(tài)資源的訪問根URLhttp://localhost:7012/webapi
愿阐,并設(shè)置了訪問動態(tài)資源時加載的包為com.heu.cs.api
,也就是說趾疚,當我們訪問動態(tài)資源時缨历,服務(wù)器會向這個包里尋找我們要訪問的路徑及其響應(yīng)。
下面我們在這個包里新建一個類名為Demo
糙麦,其中代碼如下
package com.heu.cs.api;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
/**
* Created by memgq on 2017/8/5.
*/
@Path("demo")
public class Demo {
@Context
UriInfo uriInfo;
@Context
HttpServletRequest request;
@GET
@Produces("text/plain;charset=utf-8")
public String index() {
return "這是通過動態(tài)servlet生成的內(nèi)容";
}
@GET
@Path("secondlevel")
@Produces("text/plain;charset=utf-8")
public String second() {
return "rest多級路由";
}
}
在Demo
這個類中辛孵,我們使用到了Jersey注解開發(fā),其中@Path
代表訪問路徑赡磅,class
上為一級路徑魄缚,里面可以設(shè)置二級路徑,@GET焚廊、@POST
為訪問方法冶匹,@Produces
表示響應(yīng)響應(yīng)回去的類型,關(guān)于Jersey常用的注解開發(fā)及注解類型节值,網(wǎng)上資料多爾全面徙硅,這里也不累述。
在Demo
中搞疗,我們添加了一個一級URL/demo
和一個二級URL/demo/secounlevel
嗓蘑,在前面加上根URLhttp://localhost:7012/webapi
,我們即可訪問到自己用生成的動態(tài)資源
四匿乃、Embedded Jetty項目打包
當我們完成webapp開發(fā)后桩皿,想要將這個項目發(fā)布出去,該怎么辦幢炸?在這里Maven給我們提供了打包插件maven-shade-plugin
泄隔,通過在pom.xml
文件中對項目進行配置,即可完成打包工作宛徊,將項目打包成可執(zhí)行的jar包發(fā)布出去佛嬉。pom.xml
中的配置如下
<build>
<finalName>RestDemo</finalName><!-- 打包后的名字-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.heu.cs.jettyserver.JettyServer</Main-Class><!-- 執(zhí)行主函數(shù)-->
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
打包時逻澳,鼠標放在IDEA左下角的正方形圖標,然后點擊Maven Projects
在IDEA右側(cè)彈出Maven窗口
關(guān)閉
JettyServer.main
暖呕,然后依次點擊Maven中的clean->install
斜做,最后打包完成的jar包會放在/target
目錄下然后打開CMD,進入次目錄下湾揽,鍵入
java -jar RestDemo.jar
即可執(zhí)行程序瓤逼。- 注意事項
- 通過這種方法打包的jar包并不包括Resources中的靜態(tài)資源文件,靜態(tài)資源文件需要提取出來放到與jar包相同的目錄中库物,打包后僅包含
/src/main/java
中的編譯文件霸旗。因此在復(fù)制靜態(tài)資源文件時需要按照/src/main/resources
這樣的路徑拷貝過來。
五戚揭、總結(jié)
我用這個嵌入式Jetty當服務(wù)器開發(fā)有半年左右诱告,因為基礎(chǔ)差,學(xué)到的東西不是很多毫目,前期什么都不懂蔬啡,好多簡單的東西都要琢磨很久诲侮,走了很多彎路镀虐,尤其是打包那一塊,對Maven也不熟悉沟绪,所以折騰了很久刮便,才找到這個簡陋的方法。希望記錄下來自己用到的東西绽慈,能夠幫助到其他人恨旱。