首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

使用 Jersey 與 Apache Tomcat 建構 RESTful Web 服務完整指南

     編輯:Java 相關知識

REST(Representational State Transfer)由 Roy Fielding 於 2000 年博士論文提出,核心概念是資源,以 URI 識別,透過 HTTP 方法(GET/POST/PUT/DELETE)操作。RESTful Web 服務即基於 HTTP 與 REST 原理實作的服務。本文以 Jersey(JAX-RS 參考實作)為主,示範從環境建置、Hello World、進階資源設計、多重表現形式(XML/JSON)、JAXB 整合、到客戶端呼叫的完整流程。

一、環境建置

  • IDE:Eclipse IDE for JEE (3.4+) 或 IBM RAD 7.5
  • Java SE 5+
  • Web 容器:Apache Tomcat 6.0(Jetty 等亦可)
  • Jersey 庫(1.0.3):jersey-core.jar、jersey-server.jar、jsr311-api.jar、asm.jar(核心);jersey-client.jar(測試);jaxb-impl.jar 等(JAXB/JSON 進階範例需)

將 JAR 複製至 WEB-INF/lib,於 web.xml 定義 Jersey Servlet:

<servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>sample.hello.resources</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

二、Hello World:第一個 REST 資源

@Path("/hello")
public class HelloResource {
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String sayHello() {
        return "Hello Jersey";
    }
}

瀏覽器訪問 https://localhost:8080/Jersey/rest/hello 即見「Hello Jersey」。關鍵註解:

  • @Path:定義資源基礎 URI。
  • @GET:對應 HTTP GET。
  • @Produces:指定回應 MIME 類型。
  • 資源類為 POJO,無需實作特定介面,極具彈性。

三、進階範例:聯絡人管理(Contacts)

資源階層設計

  • 集合資源:ContactsResource 對應 /contacts,回傳聯絡人清單(XML/JSON)。
  • 成員資源:ContactResource 對應 /contacts/{contactId},處理單一聯絡人 CRUD。

ContactsResource 關鍵程式碼

@Path("/contacts")
public class ContactsResource {
    @Context UriInfo uriInfo;
    @Context Request request;

    @GET
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public List getContacts() {
        List contacts = new ArrayList<>();
        contacts.addAll(ContactStore.getStore().values());
        return contacts;
    }

    @Path("{contact}")
    public ContactResource getContact(@PathParam("contact") String contact) {
        return new ContactResource(uriInfo, request, contact);
    }
}

重點註解:

  • @Context:注入 UriInfo、Request 等上下文物件。
  • @Path("{contact}") + @PathParam("contact"):子資源 URI 參數綁定。
  • @Produces 多重 MIME:APPLICATION_XML 為預設。
  • 回傳 POJO 集合,JAX-RS 自動序列化為 XML/JSON。

ContactResource:單一資源操作

public class ContactResource {
    @Context UriInfo uriInfo;
    @Context Request request;
    String contact;

    public ContactResource(UriInfo uriInfo, Request request, String contact) {
        this.uriInfo = uriInfo; this.request = request; this.contact = contact;
    }

    @GET
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public Contact getContact() {
        Contact cont = ContactStore.getStore().get(contact);
        if (cont == null) throw new NotFoundException("No such Contact.");
        return cont;
    }
}

四、HTTP 方法對應 CRUD

HTTP 方法語意
GET獲取/列出/檢索單一或集合資源
POST建立新資源(ID 自動指派)
PUT更新既有資源或集合(亦可建立)
DELETE刪除資源或集合

POST:表單建立聯絡人

@POST
@Produces(MediaType.TEXT_HTML)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void newContact(
    @FormParam("id") String id,
    @FormParam("name") String name,
    @Context HttpServletResponse servletResponse) throws IOException {
    Contact c = new Contact(id, name, new ArrayList
()); ContactStore.getStore().put(id, c); URI uri = uriInfo.getAbsolutePathBuilder().path(id).build(); Response.created(uri).build(); servletResponse.sendRedirect("../pages/new_contact.html"); }

PUT:XML 輸入建立/更新

@PUT
@Consumes(MediaType.APPLICATION_XML)
public Response putContact(JAXBElement jaxbContact) {
    Contact c = jaxbContact.getValue();
    return putAndGetResponse(c);
}

private Response putAndGetResponse(Contact c) {
    Response res;
    if (ContactStore.getStore().containsKey(c.getId())) {
        res = Response.noContent().build(); // 204
    } else {
        res = Response.created(uriInfo.getAbsolutePath()).build(); // 201
    }
    ContactStore.getStore().put(c.getId(), c);
    return res;
}

DELETE:刪除

@DELETE
public void deleteContact() {
    Contact c = ContactStore.getStore().remove(contact);
    if (c == null) throw new NotFoundException("No such Contact.");
}

五、表現形式與 JAXB 整合

JAX-RS 支援多種回傳型別:String、Response、void(204)、Resource Class、@XmlRootElement 標註的 POJO(JAXB Bean)、集合等。

Contact Bean(JAXB)

@XmlRootElement
public class Contact {
    private String id;
    private String name;
    private List
addresses; // 建構子、getter/setter... @XmlElement(name="address") public List
getAddresses() { return addresses; } }

序列化輸出範例

XML:

  
ShanghaiLong Hua Street
ShanghaiDong Quan Street
huangyim Huang Yi Ming
JSON: {"contact":[{"address":[{"city":"Shanghai","street":"Long Hua Street"}, {"city":"Shanghai","street":"Dong Quan Street"}],"id":"huangyim","name":"Huang Yi Ming"}]}

六、客戶端呼叫:curl 與 Jersey Client API

curl 指令測試

# 取得所有聯絡人(XML)
curl https://localhost:8080/Jersey/rest/contacts

# 取得 JSON
curl -H "Accept:application/json" https://localhost:8080/Jersey/rest/contacts

# PUT 新增聯絡人(XML 輸入)
curl -X PUT -H "Content-type:application/xml" \
  --data "foobar" \
  https://localhost:8080/Jersey/rest/contacts/foo

Jersey Client API 程式碼

Client c = Client.create();
WebResource r = c.resource("https://localhost:8080/Jersey/rest/contacts");

// GET 所有
ClientResponse resp = r.get(ClientResponse.class);
System.out.println(resp.getStatus());
System.out.println(resp.getEntity(String.class));

// PUT 建立
Contact c = new Contact("foo", "Foo Bar", Arrays.asList(new Address("Shanghai", "Ke Yuan Street")));
ClientResponse resp = r.path(c.getId())
    .accept(MediaType.APPLICATION_XML)
    .put(ClientResponse.class, c);

// GET 單一 + DELETE
GenericType> generic = new GenericType>() {};
JAXBElement jaxb = r.path("foo").type(MediaType.APPLICATION_XML).get(generic);
Contact contact = jaxb.getValue();
r.path("foo").delete(ClientResponse.class);

WebResource 以鏈式 API 建構 URI、設定 Header、送出請求,物件自動綁定 XML/JSON。

七、整合與擴展

  • Spring、Guice 整合庫
  • ATOM 表現形式(Apache Abdera)
  • 詳細 API 與入門指南請參考 Jersey 專案首頁

總結

Jersey 以標準 JAX-RS 註解大幅簡化 RESTful 服務開發:POJO 資源類、聲明式 HTTP 方法對應、內建多重表現形式序列化、強大客戶端 API。配合 Tomcat 輕量部署,快速建構企業級 REST 服務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved