RESTful實戰筆記一——REST介紹及JERSEY快速體驗

JAX-RS2入門

解讀REST

    (Representation State Transfer)表屬性狀態轉移,六個特點:客戶端-服務器的、無狀態的、可緩存的、統一接口的、分層系統和按需編碼。優勢:跨平臺、跨語言。

     REST風格將對象視爲一種資源(resource)。

     REST資源可尋址:

          HTTP協議定義通用動詞方法(GET、POST、DELETE、PUT);

          URI協議唯一標識資源公佈的接口。

標準:HTTP+URL+XML(XML借指數據格式),標準是基本實現格式,但是不是唯一實現形式。滿足基本實現格式的不一定就是REST服務。

REST對比RPC風格對比MVC風格

    REST風格更輕量和快捷。從方法角度看,REST採用標準的HTTP方法,而RPC請求都是採用POST方法,其方法信息包含於SOAP協議包或HTTP協議包中,方法名稱不具有通用性。從作用於的角度來看,REST採用URI顯示定義作用域,而RPC的這一信息包含於協議包中,不能直觀呈現。

    RPC是面向方法調用的過程,相對而言,REST是面向資源狀態的。

    MVC風格將模型、視圖、控制解耦,從前到後的一致性,結構整潔邏輯清晰易於擴展和增強,REST風格偏重統一接口,可實現跨語言、跨平臺解耦,推進了前後端分離。MVC和REST並不互斥

RESTful Web Service(REST式Web服務)

REST服務是一種面向資源你的架構(ROA)應用,特點是方法信息存在於HTTP協議中,作用域存在於URI中。(區別RPC風格:RPC將請求方式放在信封中全部採用POST方法傳送,沒有體現HTTP協議的優勢),所以REST風格更輕量和快速。

JAX-RS2的目標

要掌握一門技術,先要掌握其背後標準的定義。(我不想掌握jesery~)

1)基於POJO;

2)以HTTP爲中心;

3)格式獨立性;

4)容器獨立性;

5)內置於javaEE;

爲什麼是JERSEY?

 JERSEY框架從2019年起在github上不再更新?https://github.com/jersey 但是JERSEY是JAVA領域中最純正的REST服務開發框架。來自GlassFish項目的子項目。

JERSEY的模塊

容器提供三種HTTP容器:Grizzly2、JDK-HTTP、SIMPLE-HTTP,Grizzly2同時提供Servlet容器。

快速實現Java REST服務

創建服務可以使用Jersey提供的Maven模型創建,使用IDEA創建快速啓動的Jersey項目步驟如下:

GroupId:org.glassfish.jersey.archetypes

ArtifactId:jersey-quickstart-grizzly2

Version:2.22.1

創建完成後會生成如下的工程目錄結構:

我們啓動main方法,Jersey會啓動web容器,我們根據uri訪問便可完成簡單的Jersey體驗。

主類:

package my.restful;

import java.io.IOException;
import java.net.URI;

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;

/**
 * Main class.
 */
public class Main {
    // Base URI the Grizzly HTTP server will listen on
    public static final String BASE_URI = "http://localhost:8080/myapp/";

    /**
     * Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
     *
     * @return Grizzly HTTP server.
     */
    public static HttpServer startServer() {
        // create a resource config that scans for JAX-RS resources and providers
        // in my.restful package
        final ResourceConfig rc = new ResourceConfig().packages("my.restful");

        // create and start a new instance of grizzly http server
        // exposing the Jersey application at BASE_URI
        return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
    }

    /**
     * Main method.
     *
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        final HttpServer server = startServer();
        System.out.println(String.format("Jersey app started with WADL available at "
            + "%sapplication.wadl\nHit enter to stop it...", BASE_URI));
        System.in.read();
        server.shutdown();
    }
}

資源類:

package my.restful;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 * Root resource (exposed at "myresource" path)
 */
@Path("myresource")
public class MyResource {

    /**
     * Method handling HTTP GET requests. The returned object will be sent
     * to the client as "text/plain" media type.
     *
     * @return String that will be returned as a text/plain response.
     */
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getIt() {
        return "Got it!";
    }
}

請求uri:http://localhost:8080/myapp/myresource

結果:

擴展——webapp

webapp在jetty容器上提供rest服務:

pom.xml

<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">

    <modelVersion>4.0.0</modelVersion>

    <groupId>my.restful</groupId>
    <artifactId>my-first-webapp</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>my-first-webapp</name>

    <build>
        <finalName>my-first-webapp</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <inherited>true</inherited>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.3.5.v20151012</version>
            </plugin>
        </plugins>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey</groupId>
                <artifactId>jersey-bom</artifactId>
                <version>${jersey.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <!-- use the following artifactId if you don't need servlet 2.x compatibility -->
            <!-- artifactId>jersey-container-servlet</artifactId -->
        </dependency>
        <!-- uncomment this to get JSON support
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
        </dependency>
        -->
        <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.containers/jersey-container-servlet -->
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>2.22.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>2.19</version>
        </dependency>
    </dependencies>
    <properties>
        <jersey.version>2.22.1</jersey.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

index.jsp

<html>
<body>
    <h2>Jersey RESTful Web Application!</h2>
    <p><a href="webapi/myresource">Jersey resource</a>
    <p>Visit <a href="http://jersey.java.net">Project Jersey website</a>
    for more information on Jersey!
</body>
</html>

myResource.java

package my.restful;

import java.util.concurrent.ConcurrentHashMap;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 * Root resource (exposed at "myresource" path)
 */
@Path("myresource")
public class MyResource {

    private static ConcurrentHashMap<String, MyDomain> map = new ConcurrentHashMap<>();

    /**
     * Method handling HTTP GET requests. The returned object will be sent
     * to the client as "text/plain" media type.
     *
     * @return String that will be returned as a text/plain response.
     */
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getIt() {
        return "Got it!";
    }

    @GET
    @Path("{key}")
    @Produces(MediaType.APPLICATION_XML)
    public MyDomain getMy(@PathParam("key") final String key) {
        final MyDomain myDomain = map.get(key);
        if (myDomain == null) {
            return new MyDomain();
        }
        return myDomain;
    }

    @POST
    @Consumes(MediaType.APPLICATION_XML)//POST傳輸application/xml
    public void addMy(final MyDomain myDomain) {
        map.put(myDomain.getName(), myDomain);
    }
}
MyDomain.java
package my.restful;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement//對象轉xml
public class MyDomain {
    private String name;
    private String value;

    public MyDomain() {
    }

    public MyDomain(String name, String value) {
        this.name = name;
        this.value = value;
    }

    @XmlAttribute
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @XmlAttribute
    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

測試:

無參訪問:

帶請求實體POST:

GET方法訪問eric:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章