IDEA+Maven+Embedded Jetty+Jersey構(gòu)建Restful服務(wù)并打包成jar包發(fā)布

一啊终、簡要介紹


最近做的項目用到了嵌入式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伍掀、Maven3IDEA2017.2暇藏,Jetty版本為9.4.3.v20170317蜜笤,Jersey版本為2.25.1

三盐碱、具體步驟


1把兔、新建maven空項目

打開IDEA,新建一個Project瓮顽,選擇Maven項目县好,然后填寫一些基本信息,最后新建的項目如下圖所示

新建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昼蛀。
添加網(wǎng)絡(luò)服務(wù)框架

添加完成后宴猾,會在項目的結(jié)構(gòu)樹中看到多出/web目錄,并在/src/main/java包中多出一個example叼旋,紅色的/target目錄是編譯文件夾仇哆,編譯后的class文件都在里面。
項目結(jié)構(gòu)樹

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ù)器

靜態(tài)資源文件

然后在瀏覽器中輸入http://localhost:7012/static/即可訪問到這些文件

訪問靜態(tài)資源

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)資源

訪問動態(tài)資源
訪問多級URL

四匿乃、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

打開Maven

在IDEA右側(cè)彈出Maven窗口

Maven

關(guān)閉JettyServer.main暖呕,然后依次點擊Maven中的clean->install斜做,最后打包完成的jar包會放在/target目錄下
打包后的jar包

然后打開CMD,進入次目錄下湾揽,鍵入java -jar RestDemo.jar即可執(zhí)行程序瓤逼。
執(zhí)行jar程序

  • 注意事項
  • 通過這種方法打包的jar包并不包括Resources中的靜態(tài)資源文件,靜態(tài)資源文件需要提取出來放到與jar包相同的目錄中库物,打包后僅包含/src/main/java中的編譯文件霸旗。因此在復(fù)制靜態(tài)資源文件時需要按照/src/main/resources這樣的路徑拷貝過來。

五戚揭、總結(jié)


我用這個嵌入式Jetty當服務(wù)器開發(fā)有半年左右诱告,因為基礎(chǔ)差,學(xué)到的東西不是很多毫目,前期什么都不懂蔬啡,好多簡單的東西都要琢磨很久诲侮,走了很多彎路镀虐,尤其是打包那一塊,對Maven也不熟悉沟绪,所以折騰了很久刮便,才找到這個簡陋的方法。希望記錄下來自己用到的東西绽慈,能夠幫助到其他人恨旱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坝疼,隨后出現(xiàn)的幾起案子搜贤,更是在濱河造成了極大的恐慌,老刑警劉巖钝凶,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仪芒,死亡現(xiàn)場離奇詭異,居然都是意外死亡耕陷,警方通過查閱死者的電腦和手機掂名,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哟沫,“玉大人饺蔑,你說我怎么就攤上這事∈染鳎” “怎么了猾警?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵孔祸,是天一觀的道長。 經(jīng)常有香客問我发皿,道長融击,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任雳窟,我火速辦了婚禮尊浪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘封救。我一直安慰自己拇涤,他們只是感情好,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布誉结。 她就那樣靜靜地躺著鹅士,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惩坑。 梳的紋絲不亂的頭發(fā)上掉盅,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天,我揣著相機與錄音以舒,去河邊找鬼仅父。 笑死,一個胖子當著我的面吹牛绊汹,可吹牛的內(nèi)容都是我干的搂捧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼滥沫,長吁一口氣:“原來是場噩夢啊……” “哼侣集!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起兰绣,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤世分,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后缀辩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體臭埋,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年雌澄,在試婚紗的時候發(fā)現(xiàn)自己被綠了斋泄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡镐牺,死狀恐怖炫掐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情睬涧,我是刑警寧澤募胃,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布旗唁,位于F島的核電站,受9級特大地震影響痹束,放射性物質(zhì)發(fā)生泄漏检疫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一祷嘶、第九天 我趴在偏房一處隱蔽的房頂上張望屎媳。 院中可真熱鬧,春花似錦论巍、人聲如沸烛谊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丹禀。三九已至,卻和暖如春鞋怀,著一層夾襖步出監(jiān)牢的瞬間双泪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工密似, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留焙矛,地道東北人。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓辛友,卻偏偏與公主長得像薄扁,于是被迫代替她去往敵國和親剪返。 傳聞我的和親對象是個殘疾皇子废累,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,806評論 6 342
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)脱盲,斷路器邑滨,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • 1.簡介 之前的maven項目打包類型都為pom或者POM,今天講一下用maven構(gòu)建web應(yīng)用,web應(yīng)用的打包...
    zlcook閱讀 3,382評論 0 12
  • 原文鏈接:http://www.dropwizard.io/1.2.0/docs/getting-started....
    Lance_Xu閱讀 902評論 0 0
  • 我開始寫日記钱反,是在我1997年上初中的時候掖看,那時所有同學(xué)都被老師要求每周要寫一篇日記,于是懵懵懂懂就開始接觸了寫日...
    喚醒沉睡的豬閱讀 1,510評論 20 26