使用CXF開發RESTFul服務
相信大家在閱讀
CXF官方文件(http://cxf.apache.org/docs/index.html)時,總是一知半解。這裡向大家推薦一本PacktPub.Apache.CXF.Web.Service.Development。目前,這本書是沒有中文版的,為此筆者簡單的寫了一些經驗總結。CXF官方文件(http://cxf.apache.org/docs/index.html)時,總是一知半解。這裡向大家推薦一本PacktPub.Apache.CXF.Web.Service.Development。目前,這本書是沒有中文版的,為此筆者簡單的寫了一些經驗總結。
這本書內容上安排的比較淺顯,語言上也沒有什麼深奧的,值得一讀。另外值得一提的是,這本書比官方文件高明之處是每個概念就介紹得很清楚,像第二章的Code-first和Contract-first,第5章的Feature和Interceptor概念的介紹,還有第6章的REST概念簡介,內容上都比官方文件詳細很多。缺點就是並沒有將CXF所有的特性都寫下來,這就需要將samples中的內容好好消化一下了。
程式碼使用Maven組織
http://dl.iteye.com/topics/download/fbbf344b-2357-33fe-86d7-a44116e6de85
使用CXF開發RESTFul服務
在各個系統互動領域,Web services逐漸成為主流。有兩種主要方式來開發Web Services:Simple Object Access Protocol (SOAP)和Representational State Transfer (REST)
開發基於SOAP的Web Services需要很多的約束, 以便客戶端和服務端互動資訊,例如,使用Web Service Description Language (WSDL)來描述資訊。還有很多WS的標準如WS-Security。
使用REST構架的服務被稱為RESTful服務。這種架構利用簡單的XML在HTTP協議上,就像網頁一樣傳送請求,簡化了基於SOAP架構開發。RESTful Web Services尤其適用於只需要提交和接受簡單的XML資訊。
接下來會介紹使用CXF框架來開發RESTful風格的Web Services。
簡介
Java API for RESTful services
CXF JAX-RS實現
開發RESTful服務
簡介
REST也就是Representational State Transfer。REST並不特指一種技術,也不是一個標準,它僅僅是一個構架風格。REST 指的是一組架構約束條件和原則。滿足這些約束條件和原則通過網路暴露資源給使用者。事實上,WWW就是經典的REST架構風格。在伺服器端,應用程式狀態和功能可以分為各種資源。它向客戶端公開。每個資源都使用 URI (Universal Resource Identifier)得到一個惟一的地址。所有資源都共享統一的介面,以便在客戶端和伺服器之間傳輸狀態。使用的是標準的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。客戶端通過交換各種資源的表現體來查詢或更新資源。資源的表現體包括HTML,XML,JSON等。客戶端需要解析響應伺服器的表現體。客戶端和伺服器之間的互動在請求之間是無狀態的,無狀態請求可以由任何可用伺服器應答。
下面是一些RESTfu例子,提供僱員和部門的資訊,並介紹客戶端怎樣訪問這些服務
URI for the RESTful service—http://<host>/department/deptname/employee:
• GET—獲得deptname部門的所有員工資訊
• POST—為deptname部門建立員工資訊。
• DELETE—刪除 deptname部門一名員工資訊
URI for the RESTful service—http://<host>/department/deptname/employee/naveen:
• GET—獲得deptname部門名叫naveen的員工資訊
• PUT—為deptname部門建立名叫naveen的員工資訊
• DELETE—刪除deptname部門名叫naveen的員工資訊
下面是POST請求的例子http://<host>/department/deptname/employee
POST /department/deptname/employee HTTP/1.1
Content-Type: */*
Accept: application/xml
User-Agent: Apache CXF 2.2.2
Cache-Control: no-cache
Pragma: no-cache
Host: 127.0.0.1:9001
<employee><firstname>rajeev</firstname><lastname>hathi</lastname>
<dob>10/26/78</dob></employee>
Java API for RESTful services
上一節,我們瞭解僱員POST請求。如果需要提供一種實現去識別僱員POST請求,我們應該做如下工作:
識別這是否一個HTTP POST請求。
將HTTP POST請求中的XML的內容轉換為實現端所需要的格式,例如JAVA物件。
執行指定的操作,例如插入僱員資訊到資料庫。
以HTTP形式響應客戶端,例如設定標誌響應成功的HTTP狀態200 ,並將響應轉換到指定格式(XML或JSON),最後將其設定到HTTP Body。
依據需求,可能你要實現所有的HTTP方法,如GET,PUT,DELETE等。這不就是標準的RESTful JAVA開發模式嗎?接著,Java API for RESTful Web services (JAX-RS)規範制定了開發RESTful的標準。
JAX-RS規範定義了建立RESTful服務的語法。JAX-RS使用annotations註解在實現RESTful的服務,使用annotations註解POJO將它暴露為RESTful資源。RESTful服務類中,通過URI(/category)和HTTP(GET, POST)方法註解方法。
@GET
@Path("/category/{id}")
public Category getCategory(@PathParam("id") String id)
實現JAX-RS的框架在執行的時候,通過對映HTTP請求到RESTful方法,負責呼叫正確的JAVA實現方法。JAX-RS規範提供這種對映的方法的演算法。基礎演算法包括,判斷JAVA資源類,判斷HTTP URI請求,判斷內容格式(例如application/xml),還有HTTP方法(例如GET)
JAX-RS規範提出如下要點:
POJO依賴性
為了暴露為資源,使用annotations註解POJO,
HTTP依賴性
RESTful資源暴露在HTTP中,規範中將HTTP 協議和JAX-RS API相對應對映。
格式獨立性
API中提供嵌入式的方法,標準化新增HTTP內容的型別。例如,application/xml就是HTTP內容的型別中的一種。
容器獨立性
可以在任何一種容器中部署實現JAX-RS規範的應用程式。
CXF JAX-RS實現
CXF實現了JAX-RS1.0規範,並提供了很多特性幫助開發者搭建企業級的RESTful服務。
下面是CXF框架提供建立RESTful服務的各種特性。
整合Spring
Spring框架已經變成事實上的構建企業級JAVA應用程式整合框架。CXF提供與Spring整合,簡化了配置和部署RESTful應用程式。Spring提供依賴注入促進鬆散耦合,提供各種服務,像宣告式事務管理。所有這些Spring提供的特性都可以被開發RESTful服務的CXF框架使用。
插入式資料繫結
資料庫繫結就是對映HTTP請求,例如JSON或XML,到對應的JAVA物件。同樣的,在傳送HTTP響應之前,服務端的JAVA實現需要對映為客戶端所需要的格式。通過提供資料庫繫結元件,CXF在後臺透明的處理對映。CXF支援各種資料繫結機制,如JAXB,JSON,XMLBean和Aegis。CXF允許指定特定的繫結機制。
客戶端API
JAX-RS規範並沒有提供客戶端呼叫REST服務的API。CXF提供了這種API直接呼叫RESTful服務,也可以使用Spring框架配置到應用程式中。
安全
CXF可以使用Spring框架整合的宣告式安全元件,按照應用程式的需要限制資源類和方法,而不必使用程式碼處理安全性問題。
過濾器
過濾器用來預處理或後處理資訊。CXF可以建立和配置過濾器來稽核資訊,記錄資訊的日誌,還有基於應用要求修改請求或響應。
CXF也執行開發者使用JAX-WS Provider和Dispatch API來建立RESTful服務。
開發RESTful服務
本節將介紹使用JAX-RS實現的方法來開發RESTful服務,並執行CRUD操作。首先看一下Book Shop應用。
Book Shop應用是一款網路應用,提供技術書籍(JAVA或.NET)的分類。Book Shop讓管理員為新的書籍建立分類,修改分類等。一旦這個分類存在,應用可以為這個分類新增新的書籍。
這個應用將提供如下方法:
建立分類
更新分類
刪除分類
獲取分類列表
獲取特定分類
為特定分類新增書籍
獲取特定分類中所有書籍
為了開發RESTful服務,需要做如下工作:
建立POJO類
為POJO類提供資料繫結
建立實現RESTful功能的服務類
建立呼叫RESTful服務的客戶端
建立POJO類
- package demo.restful;
- import javax.xml.bind.annotation.XmlRootElement;
- @XmlRootElement(name = "Book")
- public class Book {
- private String bookId;
- private String bookISBNnumber;
- private String bookName;
- //Let assume one author only
- private String author;
- public String getBookId() {
- return bookId;
- }
- public void setBookId(String bookId) {
- this.bookId = bookId;
- }
- public String getBookISBNnumber() {
- return bookISBNnumber;
- }
- public void setBookISBNnumber(String bookISBNnumber) {
- this.bookISBNnumber = bookISBNnumber;
- }
- public String getBookName() {
- return bookName;
- }
- public void setBookName(String bookName) {
- this.bookName = bookName;
- }
- public String getAuthor() {
- return author;
- }
- public void setAuthor(String author) {
- this.author = author;
- }
- }
- package demo.restful;
- import java.util.Collection;
- import javax.xml.bind.annotation.XmlRootElement;
- @XmlRootElement(name = "Category")
- public class Category {
- private String categoryId;
- private String categoryName;
- private Collection<Book> books;
- public String getCategoryId() {
- return categoryId;
- }
- public void setCategoryId(String categoryId) {
- this.categoryId = categoryId;
- }
- public String getCategoryName() {
- return categoryName;
- }
- public void setCategoryName(String categoryName) {
- this.categoryName = categoryName;
- }
- public Collection<Book> getBooks() {
- return books;
- }
- public void setBooks(Collection<Book> books) {
- this.books = books;
- }
- }
為POJO類提供資料繫結
為了提供RESTful服務端和客戶端通訊,POJO需要轉換為特定的格式,例如XML或JSON。為了實現這部分功能,需要一個資料繫結的元件來對映JAVA物件和XML(或者指定的格式)。
CXF使用JAXB作為預設的資料繫結元件。JAXB使用註解來定義JAVA物件和XML之間對映的關係。
在POJO類Category中,註解@XmlRootElement指定Category為XML的根元素。Category類的屬性預設指定對映為@XmlElement。@XmlElement用來定義XML中的子元素。@XmlRootElement和@XmlElement允許自定義名稱空間和XML中元素的名稱。如果沒有定義的話,JAXB在執行的時候預設的使用同樣的屬性名和類名來定義XML元素。
下面的XML請求表示了Category資料物件。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Category>
<books>
<author>Naveen Balani</author>
<bookISBNnumber>ISBNB001</bookISBNnumber>
<bookId>NB001</bookId>
<bookName>Fiction Book1</bookName>
</books>
<categoryId>005</categoryId>
<categoryName>Fiction Series</categoryName>
</Category>
建立實現RESTful功能的服務類
類註解
CategoryService的類宣告上定義了@Path 和@Produces註解。@Path定義了URI路徑,客戶端可以通過這個路徑訪問到CategoryService物件。如@Path("/categoryservice"),那麼URI請求,就可以是http://localhost:9000/categoryservice/。@Produces定義了服務類和方法生產內容的型別。如@Produces("application/xml"),那麼CategoryService只會生產application/xml。
方法註解
每個方法都和@Produces相關,它決定了這個方法生產什麼樣的響應。每個方法都有和HTTP方法對映的的註解,例如@GET和@POST。方法中的@Path註解指定了該方法的URI。例如getCategory()方法上的@Path("/category/{id}"),可以使用http://localhost:9000/categoryservice/category/001,訪問到category id 為001的分類。{id}就好比引數。接著,讓我們看看@PathParam註解。@PathParam註解是用來給URI 路徑一個模板變數,方法的輸入引數。@PathParam("id") 就是URI中的@Path ("/category/{id}")。
@GET
@Path("/category/{id}")
public Category getCategory(@PathParam("id") String id)
異常處理
讓我們看一種情況,客戶端傳送一個請求刪除或者更新一個分類,但是這個分類並不存在,那麼服務端需要返回正確的錯誤資訊給客戶端。
為了處理異常,JAX-RS提供了WebApplicationException,它繼承自RuntimeException類。WebApplicationException可以使用HTTP狀態程式碼或者javax.ws.rs.core.Response物件作為構造器。Response物件除了提供HTTP狀態程式碼外,還可以提供使用者容易識別的錯誤資訊。
RESTful服務的異常處理可以分為如下幾類:
實現類丟擲帶有HTTP錯誤程式碼的WebApplicationException異常。一般的,4XX定義了客戶端錯誤,如錯誤請求;5XX定義了服務端錯誤,如伺服器沒有完成請求。
直接發回javax.ws.rs.core.Response物件,Response物件中包含了HTTP錯誤程式碼。
為了測試異常處理程式碼,啟動CategoryServerStart類。在IE瀏覽器中輸入
http://localhost:9000/categoryservice/category/011
由於IE不會顯示自定義的錯誤資訊,我們會看到HTTP 400 BAD Request。
如果你在Firefox或者Chrome,就會返回
<error>Category Not Found</error>
新增JSON支援
在@Produces 和 @Consumes註解中新增application/json,指定CategoryService除了application/xml外,還接收和產生application/json。CXF執行時會處理HTTP JSON請求到JAVA物件的轉換,還有JAVA物件到HTTP JSON響應的對映。
- package demo.restful;
- //JAX-RS Imports
- import javax.ws.rs.Consumes;
- import javax.ws.rs.DELETE;
- import javax.ws.rs.GET;
- import javax.ws.rs.POST;
- import javax.ws.rs.PUT;
- import javax.ws.rs.Path;
- import javax.ws.rs.PathParam;
- import javax.ws.rs.Produces;
- import javax.ws.rs.WebApplicationException;
- import javax.ws.rs.core.Response;
- import javax.ws.rs.core.Response.ResponseBuilder;
- import javax.ws.rs.core.Response.Status;
- /*
- * CategoryService class - Add/Removes category for books
- */
- @Path("/categoryservice")
- @Produces({"application/json","application/xml"})
- public class CategoryService {
- private CategoryDAO categoryDAO = new CategoryDAO();
- public CategoryDAO getCategoryDAO() {
- return categoryDAO;
- }
- public void setCategoryDAO(CategoryDAO categoryDAO) {
- this.categoryDAO = categoryDAO;
- }
- @GET
- @Path("/category/{id}")
- @Produces({"application/json","application/xml"})
- public Category getCategory(@PathParam("id") String id) {
- System.out.println("getCategory called with category id: " + id);
- Category cat = (Category) getCategoryDAO().getCategory(id);
- if (cat == null) {
- ResponseBuilder builder = Response.status(Status.BAD_REQUEST);
- builder.type("application/xml");
- builder.entity("<error>Category Not Found</error>");
- throw new WebApplicationException(builder.build());
- } else {
- return cat;
- }
- }
- @POST
- @Path("/category")
- @Consumes({"application/json","application/xml"})
- public Response addCategory(Category category) {
- System.out.println("addCategory called");
- Category cat = (Category) getCategoryDAO().getCategory(
- category.getCategoryId());
- if (cat != null) {
- return Response.status(Status.BAD_REQUEST).build();
- } else {
- getCategoryDAO().addCategory(category);
- return Response.ok(category).build();
- }
- }
- @DELETE
- @Path("/category/{id}")
- @Consumes({"application/json","application/xml"})
- public Response deleteCategory(@PathParam("id") String id) {
- System.out.println("deleteCategory with category id : " + id);
- Category cat = (Category) getCategoryDAO().getCategory(id);
- if (cat == null) {
- return Response.status(Status.BAD_REQUEST).build();
- } else {
- getCategoryDAO().deleteCategory(id);
- return Response.ok().build();
- }
- }
- @PUT
- @Path("/category")
- @Consumes({"application/json","application/xml"})
- public Response updateCategory(Category category) {
- System.out.println("updateCategory with category id : "
- + category.getCategoryId());
- Category cat = (Category) getCategoryDAO().getCategory(
- category.getCategoryId());
- if (cat == null) {
- return Response.status(Status.BAD_REQUEST).build();
- } else {
- getCategoryDAO().updateCategory(category);
- return Response.ok(category).build();
- }
- }
- @POST
- @Path("/category/book")
- @Consumes({"application/json","application/xml"})
- public Response addBooks(Category category) {
- System.out.println("addBooks with category id : "
- + category.getCategoryId());
- Category cat = (Category) getCategoryDAO().getCategory(
- category.getCategoryId());
- if (cat == null) {
- return Response.status(Status.NOT_FOUND).build();
- } else {
- getCategoryDAO().addBook(category);
- return Response.ok(category).build();
- }
- }
- @GET
- @Path("/category/{id}/books")
- @Consumes("application/xml,application/json")
- public Response getBooks(@PathParam("id") String id) {
- System.out.println("getBooks called with category id : " + id);
- Category cat = (Category) getCategoryDAO().getCategory(id);
- if (cat == null) {
- return Response.status(Status.NOT_FOUND).build();
- } else {
- cat.setBooks(getCategoryDAO().getBooks(id));
- return Response.ok(cat).build();
- }
- }
- }
DAO
- package demo.restful;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Map;
- /*
- * DataAcess object for performing CRUD operations.
- * Dummy implementation.
- */
- public class CategoryDAO {
- private static Map<String, Category> categoryMap = new HashMap<String, Category>();
- private static Map<String, Collection<Book>> bookMap = new HashMap<String, Collection<Book>>();
- static {
- Category category1 = new Category();
- category1.setCategoryId("001");
- category1.setCategoryName("Java");
- categoryMap.put(category1.getCategoryId(), category1);
- Book book1 = new Book();
- book1.setAuthor("Naveen Balani");
- book1.setBookName("Spring Series");
- book1.setBookId("001");
- book1.setBookISBNnumber("ISB001");
- Book book2 = new Book();
- book2.setAuthor("Rajeev Hathi");
- book2.setBookName("CXF Series");
- book2.setBookId("002");
- book2.setBookISBNnumber("ISB002");
- Collection<Book> booksList = new ArrayList<Book>();
- booksList.add(book1);
- booksList.add(book2);
- bookMap.put(category1.getCategoryId(), booksList);
- }
- public void addCategory(Category category) {
- categoryMap.put(category.getCategoryId(), category);
- }
- public void addBook(Category category) {
- bookMap.put(category.getCategoryId(), category.getBooks());
- }
- public Collection<Book> getBooks(String categoryId) {
- return bookMap.get(categoryId);
- }
- public Category getCategory(String id) {
- Category cat = null;
- //Dummy implementation to return a new copy of category to
- //avoid getting overridden by service
- if(categoryMap.get(id) != null) {
- cat = new Category();
- cat.setCategoryId(categoryMap.get(id).getCategoryId());
- cat.setCategoryName(categoryMap.get(id).getCategoryName());
- }
- return cat;
- }
- public void deleteCategory(String id) {
- categoryMap.remove(id);
- // Remove association of books
- bookMap.remove(id);
- }
- public void updateCategory(Category category) {
- categoryMap.put(category.getCategoryId(), category);
- }
- }
建立呼叫RESTful服務的客戶端
JAX-RS並不提供呼叫RESTful服務客戶端。CXF框架提供了兩種方式來建立客戶端,這兩種都可以使用Spring配置。
代理API
代理API允許你使用RESTful服務的資源類和介面。代理類是客戶端直接呼叫介面方法,使使用者不需要手工建立HTTP請求。將RESTful服務類傳遞給org.apache.cxf.jaxrs.client.JAXRSClientFactory類。一旦代理類建立好了,你可以直接使用RESTful服務介面類的任何方法。
CategoryService store = JAXRSClientFactory.create("http://
localhost:9000", CategoryService.class);
//Makes remote call to Category RESTFul service
store.getBooks("001");
HTTP客戶端
使用org.apache.cxf.jaxrs.client.WebClient呼叫RESTful服務。本例中採用HTTP客戶端。
- package demo.restful.client;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Iterator;
- import javax.ws.rs.core.Response;
- import org.apache.cxf.jaxrs.client.WebClient;
- import demo.restful.Book;
- import demo.restful.Category;
- public class CategoryServiceRESTClient {
- //Put some static value
- private static final String CATEGORY_URL = "http://localhost:9000/";
- private static final String CATEGORY_ID = "005";
- private static final String TYPE_XML = "application/xml";
- private static final String TYPE_JSON = "application/json";
- public static void main(String[] args) {
- //System.out.println("Format is " + args[0]);
- testAddCategory(TYPE_XML);
- testUpdateCategory(TYPE_XML);
- testGetCategory(TYPE_XML);
- testAddBooksForCategory(TYPE_XML);
- testGetBooksForCategory(TYPE_XML);
- testDeleteCategory(TYPE_XML);
- testAddCategory(TYPE_JSON);
- testUpdateCategory(TYPE_JSON);
- testGetCategory(TYPE_JSON);
- testAddBooksForCategory(TYPE_JSON);
- testGetBooksForCategory(TYPE_JSON);
- testDeleteCategory(TYPE_JSON);
- // if(args[0] !=null && args[0].equalsIgnoreCase(TYPE_XML)){
- // //Content type- XML
- // testAddCategory(TYPE_XML);
- // testUpdateCategory(TYPE_XML);
- // testGetCategory(TYPE_XML);
- // testAddBooksForCategory(TYPE_XML);
- // testGetBooksForCategory(TYPE_XML);
- // testDeleteCategory(TYPE_XML);
- // }
- //
- // if(args[0] !=null && args[0].equalsIgnoreCase(TYPE_JSON)){
- // //ContentType- JSON
- // testAddCategory(TYPE_JSON);
- // testUpdateCategory(TYPE_JSON);
- // testGetCategory(TYPE_JSON);
- // testAddBooksForCategory(TYPE_JSON);
- // testGetBooksForCategory(TYPE_JSON);
- // testDeleteCategory(TYPE_JSON);
- // }
- }
- private static void testAddCategory(final String format) {
- System.out.println("testAddCategory called with format " + format);
- WebClient client = WebClient.create(CATEGORY_URL);
- client.path("/categoryservice/category").accept(
- format).type(format);
- Category cat = new Category();
- cat.setCategoryId(CATEGORY_ID);
- cat.setCategoryName("Fiction");
- Category catResponse = client.post(cat, Category.class);
- System.out.println("Category Id retreived for format " + format + " is " + catResponse.getCategoryId());
- assertEquals(catResponse.getCategoryId(), CATEGORY_ID);
- }
- private static void testUpdateCategory(final String format) {
- System.out.println("testUpdateCategory called with format " + format);
- WebClient client = WebClient.create(CATEGORY_URL);
- client.path("/categoryservice/category").accept(
- format).type(format);
- Category cat = new Category();
- cat.setCategoryId(CATEGORY_ID);
- cat.setCategoryName("Fiction Series");
- Response response = client.put(cat);
- System.out.println("Status retreived for update category for format " + format + " is " + response.getStatus());
- assertEquals("200", String.valueOf(response.getStatus()));
- }
- private static void testGetCategory(final String format) {
- System.out.println("testGetCategory called with format " + format);
- WebClient client = WebClient.create(CATEGORY_URL);
- Category category = client.path("/categoryservice/category/" + CATEGORY_ID).accept(
- format).type(format).get(Category.class);
- System.out.println("Category details retreived from service with format " + format);
- System.out.println("Category Name " + category.getCategoryName());
- System.out.println("Category Id " + category.getCategoryId());
- assertEquals(CATEGORY_ID, category.getCategoryId());
- }
- private static void testAddBooksForCategory(final String format) {
- System.out.println("testAddBooksForCategory called with format " + format);
- WebClient client = WebClient.create(CATEGORY_URL);
- client.path("/categoryservice/category/book").type(format).
- accept(format);
- Category cat = new Category();
- cat.setCategoryId(CATEGORY_ID);
- cat.setCategoryName("Fiction Series");
- Book book1 = new Book();
- book1.setAuthor("Naveen Balani");
- book1.setBookId("NB001");
- book1.setBookISBNnumber("ISBNB001");
- book1.setBookName("Fiction Book1");
- Collection<Book> booksList = new ArrayList<Book>();
- booksList.add(book1);
- cat.setBooks(booksList);
- client.post(cat, Category.class);
- }
- private static void testGetBooksForCategory(final String format) {
- System.out.println("testGetBooksForCategory called with format " + format);
- WebClient clientBook = WebClient.create(CATEGORY_URL);
- Category categoryBooks = clientBook.path(
- "/categoryservice/category/" + CATEGORY_ID + "/books").type(format).accept(format).get(Category.class);
- System.out.println("Book details retreived from service with format " + format);
- assertEquals(String.valueOf(categoryBooks.getBooks().size()), "1");
- Iterator<Book> iterator = categoryBooks.getBooks().iterator();
- while (iterator.hasNext()) {
- Book book = iterator.next();
- System.out.println("Book Name " + book.getBookName());
- System.out.println("Book ISBN " + book.getBookISBNnumber());
- System.out.println("Book ID " + book.getBookId());
- System.out.println("Book Author " + book.getAuthor());
- }
- }
- private static void testDeleteCategory(final String format) {
- System.out.println("testDeleteCategory called with format " + format);
- WebClient client = WebClient.create(CATEGORY_URL);
- client.path("/categoryservice/category/" + CATEGORY_ID).type(format).
- accept(format);
- Response response = client.delete();
- System.out.println("Status retreived for delete category for format " + format + " is " + response.getStatus());
- assertEquals("200", String.valueOf(response.getStatus()));
- }
- private static void assertEquals(String expected, String result) {
- if (!expected.equalsIgnoreCase(result)) {
- throw new RuntimeException("Expecte value " + expected + ", Got value" + result);
- }
- }
- }
相關文章
- 使用apache CXF開發第一個Web服務ApacheWeb
- CXF+Spring+JAXB+Json構建Restful服務SpringJSONREST
- java JAX-RS快速開發RESTful服務JavaREST
- Java開發中RestFul服務介面規範JavaREST
- 用 Go 快速開發一個 RESTful API 服務GoRESTAPI
- Flask RESTful Web服務的開發套路總結FlaskRESTWeb
- 如何使用RestTemplate訪問restful服務REST
- CXF實現webService服務(一)Web
- 使用CXF與Spring整合實現RESTFul WebServiceSpringRESTWeb
- 搭建 Restful Web 服務RESTWeb
- 使用SCA和JAX-RS建立RESTful服務REST
- 使用 Hapi 開發 RESTful APIsAPIREST
- 使用 CXF 整合 Spring 開發 Web ServiceSpringWeb
- 使用多種客戶端消費WCF RestFul服務(一)——服務端客戶端REST服務端
- 發表於dW的教程之開放原始碼的服務框架 - Apache CXF 簡介原始碼框架Apache
- RESTFul Web Api 服務框架(一)RESTWebAPI框架
- 使用 Jersey 和 Apache Tomcat 構建 RESTful Web 服務ApacheTomcatRESTWeb
- 實戰CXF呼叫Webxml天氣預報服務WebXML
- spring boot構建restful服務Spring BootREST
- yii2 restful web服務路由RESTWeb路由
- Yii2.0 RESTful Web服務(3)RESTWeb
- Yii2.0 RESTful Web服務(4)RESTWeb
- 第19章 建立RESTful Web服務RESTWeb
- CXF開發及與Spring整合開發Spring
- 使用Go語言開發短地址服務Go
- 介面開發-restfulREST
- 轉享:Ehcache 服務和RESTful Web ServicesRESTWeb
- 使用Docker實現Spring Boot Restful Web服務案例原始碼DockerSpring BootRESTWeb原始碼
- 如何使用Node.js、TypeScript和Express實現RESTful API服務Node.jsTypeScriptExpressRESTAPI
- Android服務端開發之使用Eclipse搭建Java Web服務端Android服務端EclipseJavaWeb
- RESTful API開發實戰 使用REST JSON XML和JAX-RS構建微服務 大資料和Web服務應用RESTAPIJSONXML微服務大資料Web
- 前端開發中使用mac自帶apache服務前端MacApache
- 使用Express開發小說API介面服務1.0(二)ExpressAPI
- 使用Express開發小說API介面服務1.0(三)ExpressAPI
- 使用Express開發小說API介面服務1.0(一)ExpressAPI
- PHP開發Web服務PHPWeb
- 使用 Spring 3 MVC HttpMessageConverter 功能構建 RESTful web 服務SpringMVCHTTPRESTWeb
- 使用多種客戶端消費WCF RestFul服務(四)——Jquery篇客戶端RESTjQuery