REST 使用Java SE部署環(huán)境

2018-08-08 14:11 更新

在上述的幾個(gè)例子中,我們使用的是內(nèi)嵌的 Tomcat 或者 Jetty 的服務(wù)器形式,以此來運(yùn)行和測(cè)試項(xiàng)目。這樣,項(xiàng)目最終會(huì)被打包成 WAR 部署在 Tomcat 或者 Jetty 等 Servlet 容器中。這種部署環(huán)境使用廣泛,被稱為基于 Servlet 的部署( Servlet-based Deployment)。

當(dāng) Web 應(yīng)用不是很復(fù)雜,不要求應(yīng)用性能很高的時(shí)候,我們就需要將 Http Server 內(nèi)嵌在我們的 Java 程序中,只要運(yùn)行Java程序,相應(yīng)的 Http Server 就會(huì)跟著快速啟動(dòng)。這就是本文所介紹的基于 Java SE 部署環(huán)境(Java SE Deployment)來提供 REST 服務(wù)。

HTTP 服務(wù)器

基于 Java 的 HTTP 服務(wù)器展現(xiàn)了一種簡(jiǎn)約、靈活的部署 Jersey 應(yīng)用程序的方式。HTTP 服務(wù)器通常是嵌入在應(yīng)用程序中,并通過配置,以編程形式來啟動(dòng)。一般來說,Jersey 容器為特定的 HTTP 服務(wù)器提供了一個(gè)定制化的工廠方法,用來返回一個(gè)正確初始化的 HTTP 服務(wù)器實(shí)例。

下面展示了常見 HTTP 服務(wù)器的內(nèi)嵌在 Jersey 應(yīng)用中的使用方法:

JDK Http Server

從 Java SE 6 開始,Java 運(yùn)行時(shí)附帶一個(gè)內(nèi)置的輕量級(jí)的 HTTP 服務(wù)器。Jersey 通過 jersey-container-jdk-http 容器擴(kuò)展模塊,提供集成這個(gè) Java SE HTTP 服務(wù)器。此時(shí),不是直接創(chuàng)建 HttpServer 實(shí)例,而是使用 JdkHttpServerFactory 的 createHttpServer()方法,它根據(jù) Jersey 容器配置和 Application 子類提供的初始化來創(chuàng)建 HttpServer 實(shí)例 。

創(chuàng)建一個(gè) 內(nèi)嵌 Jersey 的jdk http server 非常簡(jiǎn)單:

Jersey 和 JDK HTTP Server 用法:

URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig config = new ResourceConfig(MyResource.class);
HttpServer server = JdkHttpServerFactory.createHttpServer(baseUri, config);

JDK HTTP 容器依賴:

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-jdk-http</artifactId>
    <version>2.21</version>
</dependency>

Grizzly HTTP Server

Grizzly 是一個(gè)建立在 Java NIO 之上的支持多協(xié)議的框架。Grizzly 旨在簡(jiǎn)化強(qiáng)大的和可擴(kuò)展的服務(wù)器開發(fā)。Jersey 提供了一個(gè)容器的擴(kuò)展模塊,可以使用 Grizzly 作為運(yùn)行 JAX-RS 應(yīng)用普通的 HTTP 容器支持。從 Grizzly 服務(wù)器運(yùn)行 JAX-RS 或 Jersey 的應(yīng)用是一種最輕量和最容易的方法,用來展現(xiàn) RESTful 服務(wù)。

Grizzly 容器支持 HTTP 注射 Grizzly 的特性 org.glassfish.grizzly.http.server.Request 和org.glassfish.grizzly.http.server.Response 實(shí)例到 JAX-RS 和Jersey 應(yīng)用資源和供應(yīng)者。然而,由于 Grizzly 的 Request 是非代理性的,Grizzly Request的注入到單例(默認(rèn))的JAX-RS /和Jersey 提供者只可能通過 javax.inject.Provider 實(shí)例。(Grizzly Response會(huì)遭受同樣的限制。)

Jersey 和 Grizzly HTTP Server 用法:

URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig config = new ResourceConfig(MyResource.class);
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, config);

容器擴(kuò)展模塊依賴要加入:

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-grizzly2-http</artifactId>
    <version>2.21</version>
</dependency>

注意:通過測(cè)試框架, Jersey 使用 Grizzly 已經(jīng)廣泛的在項(xiàng)目單元和端到端進(jìn)行了測(cè)試。

Simple 服務(wù)器

Simple 是一個(gè)框架允許開發(fā)者創(chuàng)建 HTTP 服務(wù)器,并嵌入到應(yīng)用中。同樣的,通過從 jersey-container-simple-http 容器擴(kuò)展模塊調(diào)用工廠方法實(shí)現(xiàn)創(chuàng)建服務(wù)器實(shí)例。

Simple 的框架支持 HTTP 容器注入 Simple 框架特性 的org.simpleframework.http.Request 和 org.simpleframework.http.Response 實(shí)例到 JAX-RS 和 Jersey 應(yīng)用資源和供應(yīng)者。

Jersey 和 Simple 框架用法:

URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig config = new ResourceConfig(MyResource.class);
SimpleContainer server = SimpleContainerFactory.create(baseUri, config);

容器擴(kuò)展模塊依賴要加入:

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-simple-http</artifactId>
    <version>2.21</version>
</dependency>

注意:Simple HTTP 容器不支持部署在除了根路徑是 ("/")以外的上下文路徑。非根路徑的上下文路徑在部署中是被忽略的。

Jetty HTTP Server

Jetty 是流行的 Servlet 容器和 HTTP 服務(wù)器。在此我們不深究 Jetty 作為 Servlet 容器的能力(盡管我們?cè)谖覀兊臏y(cè)試和實(shí)例使用它),因?yàn)樽鳛榛?Servlet 部署模型并沒有什么特別,具體會(huì)在 第4.7節(jié),“基于 Servlet 部署”部分進(jìn)行描述。我們將在這里只重點(diǎn)描述如何使用 Jetty 的 HTTP 服務(wù)器。

Jetty HTTP 容器支持注入 Jetty 特性的org.eclipse.jetty.server.Request 和 org.eclipse.jetty.server.Response 實(shí)例到 JAX-RS 和 Jersey 應(yīng)用資源和供應(yīng)者。然而,由于 Jetty HTTP Request 是非代理性的,Jetty Request 的注入到單例(默認(rèn))的JAX-RS /和Jersey 提供者只可能通過 javax.inject.Provider 實(shí)例。(Jetty Response 會(huì)遭受同樣的限制。)

Jersey 和 Jetty HTTP Server 用法:

URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig config = new ResourceConfig(MyResource.class);
Server server = JettyHttpContainerFactory.createServer(baseUri, config);

容器擴(kuò)展模塊依賴要加入(譯者注:原文中依賴包有誤,這里做了更正):

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-jetty-http</artifactId>
    <version>2.21</version>
</dependency>

注意:Jetty HTTP 容器不支持部署在除了根路徑是 ("/")以外的上下文路徑。非根路徑的上下文路徑在部署中是被忽略的。

構(gòu)建 REST 程序

回顧之前的內(nèi)容,從《處理 JSON 和 XML》的源代碼,我們進(jìn)行了修改:

實(shí)體

MyBean.java

@XmlRootElement
public class MyBean {

    private String name;
    private int age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

MyBean 作為我們數(shù)據(jù)相應(yīng)的實(shí)體。

資源

MyResource.java

@Path("myresource")
public class MyResource {

    /**
     * 方法處理 HTTP GET 請(qǐng)求。返回的對(duì)象以"text/plain"媒體類型
     * 給客戶端
     *
     * @return String 以 text/plain 形式響應(yīng)
     */
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getIt() {
        return "Got it!";
    }


    /**
     * 方法處理 HTTP GET 請(qǐng)求。返回的對(duì)象以"application/xml"媒體類型
     * 給客戶端
     *
     * @return MyPojo 以 application/xml 形式響應(yīng)
     */
    @GET
    @Path("pojoxml")
    @Produces(MediaType.APPLICATION_XML)
    public MyBean getPojoXml() {
        MyBean pojo = new MyBean();
        pojo.setName("waylau.com");
        pojo.setAge(28);
        return pojo;
    }

    /**
     * 方法處理 HTTP GET 請(qǐng)求。返回的對(duì)象以"application/json"媒體類型
     * 給客戶端
     *
     * @return MyPojo 以 application/json 形式響應(yīng)
     */
    @GET
    @Path("pojojson")
    @Produces(MediaType.APPLICATION_JSON)
    public MyBean getPojoJson() {
        MyBean pojo = new MyBean();
        pojo.setName("waylau.com");
        pojo.setAge(28);
        return pojo;
    }
}

分別向外暴露各種類型資源,包括:本文、XML、JSON

應(yīng)用配置

RestApplication.java

public class RestApplication extends ResourceConfig {

    public RestApplication() {
        // 資源類所在的包路徑  
        packages("com.waylau.rest.resource");

        // 注冊(cè) MultiPart
        register(MultiPartFeature.class);
    }
}

該配置說明了要掃描的資源包的路徑com.waylau.rest.resource,以及支持 JSON 轉(zhuǎn)換 MultiPartFeature

主應(yīng)用

App.java

public class App {
    // HTTP server 所要監(jiān)聽的 uri
    public static final String BASE_URI = "http://192.168.11.125:8081/";

    /**
     * Main method.
     * 
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {

        // 若使用 Jdk Http Server請(qǐng)去掉下面的注釋
        // JdkHttpServerFactory.createHttpServer(URI.create(BASE_URI), new
        // RestApplication());

        // 若使用 Grizzly Http Server請(qǐng)去掉下面的注釋
        // GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), new
        // RestApplication());

        // 若使用 Simple Http Server請(qǐng)去掉下面的注釋
        // SimpleContainerFactory.create(URI.create(BASE_URI), new
        // RestApplication());
        // 若使用 Jetty Http Server請(qǐng)去掉下面的注釋
        JettyHttpContainerFactory.createServer(URI.create(BASE_URI),
                new RestApplication());
    }
}

各種服務(wù)器的用法在上面已經(jīng)說了,這里就不再解析。

源碼

見 javase-rest 項(xiàng)目

參考:


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)