• 使用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类

    Java代码  
    1. package demo.restful;  
    2.   
    3. import javax.xml.bind.annotation.XmlRootElement;  
    4.   
    5. @XmlRootElement(name = "Book")  
    6. public class Book {  
    7.   
    8.     private String bookId;  
    9.       
    10.     private String bookISBNnumber;  
    11.       
    12.     private String bookName;  
    13.       
    14.     //Let assume one author only  
    15.     private String author;  
    16.   
    17.     public String getBookId() {  
    18.         return bookId;  
    19.     }  
    20.   
    21.     public void setBookId(String bookId) {  
    22.         this.bookId = bookId;  
    23.     }  
    24.   
    25.     public String getBookISBNnumber() {  
    26.         return bookISBNnumber;  
    27.     }  
    28.   
    29.     public void setBookISBNnumber(String bookISBNnumber) {  
    30.         this.bookISBNnumber = bookISBNnumber;  
    31.     }  
    32.   
    33.     public String getBookName() {  
    34.         return bookName;  
    35.     }  
    36.   
    37.     public void setBookName(String bookName) {  
    38.         this.bookName = bookName;  
    39.     }  
    40.   
    41.     public String getAuthor() {  
    42.         return author;  
    43.     }  
    44.   
    45.     public void setAuthor(String author) {  
    46.         this.author = author;  
    47.     }  
    48.       
    49. }  
    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;
    	}
    	
    }
    
    Java代码  
    1. package demo.restful;  
    2.   
    3. import java.util.Collection;  
    4.   
    5. import javax.xml.bind.annotation.XmlRootElement;  
    6.   
    7. @XmlRootElement(name = "Category")  
    8. public class Category {  
    9.   
    10.     private String categoryId;  
    11.   
    12.     private String categoryName;  
    13.   
    14.     private Collection<Book> books;  
    15.   
    16.     public String getCategoryId() {  
    17.         return categoryId;  
    18.     }  
    19.   
    20.     public void setCategoryId(String categoryId) {  
    21.         this.categoryId = categoryId;  
    22.     }  
    23.   
    24.     public String getCategoryName() {  
    25.         return categoryName;  
    26.     }  
    27.   
    28.     public void setCategoryName(String categoryName) {  
    29.         this.categoryName = categoryName;  
    30.     }  
    31.   
    32.     public Collection<Book> getBooks() {  
    33.         return books;  
    34.     }  
    35.   
    36.     public void setBooks(Collection<Book> books) {  
    37.         this.books = books;  
    38.     }  
    39.   
    40. }  
    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响应的映射。

    Java代码  
    1. package demo.restful;  
    2.   
    3. //JAX-RS Imports  
    4. import javax.ws.rs.Consumes;  
    5. import javax.ws.rs.DELETE;  
    6. import javax.ws.rs.GET;  
    7. import javax.ws.rs.POST;  
    8. import javax.ws.rs.PUT;  
    9. import javax.ws.rs.Path;  
    10. import javax.ws.rs.PathParam;  
    11. import javax.ws.rs.Produces;  
    12. import javax.ws.rs.WebApplicationException;  
    13. import javax.ws.rs.core.Response;  
    14. import javax.ws.rs.core.Response.ResponseBuilder;  
    15. import javax.ws.rs.core.Response.Status;  
    16.   
    17. /* 
    18.  * CategoryService class - Add/Removes category for books  
    19.  */  
    20.   
    21. @Path("/categoryservice")  
    22. @Produces({"application/json","application/xml"})  
    23. public class CategoryService {  
    24.   
    25.     private CategoryDAO categoryDAO = new CategoryDAO();  
    26.   
    27.     public CategoryDAO getCategoryDAO() {  
    28.         return categoryDAO;  
    29.     }  
    30.   
    31.     public void setCategoryDAO(CategoryDAO categoryDAO) {  
    32.         this.categoryDAO = categoryDAO;  
    33.     }  
    34.   
    35.     @GET  
    36.     @Path("/category/{id}")  
    37.     @Produces({"application/json","application/xml"})  
    38.     public Category getCategory(@PathParam("id") String id) {  
    39.   
    40.         System.out.println("getCategory called with category id: " + id);  
    41.   
    42.         Category cat = (Category) getCategoryDAO().getCategory(id);  
    43.         if (cat == null) {  
    44.             ResponseBuilder builder = Response.status(Status.BAD_REQUEST);  
    45.             builder.type("application/xml");  
    46.             builder.entity("<error>Category Not Found</error>");  
    47.             throw new WebApplicationException(builder.build());  
    48.         } else {  
    49.             return cat;  
    50.         }  
    51.     }  
    52.   
    53.     @POST  
    54.     @Path("/category")  
    55.     @Consumes({"application/json","application/xml"})  
    56.     public Response addCategory(Category category) {  
    57.   
    58.         System.out.println("addCategory called");  
    59.   
    60.         Category cat = (Category) getCategoryDAO().getCategory(  
    61.                 category.getCategoryId());  
    62.   
    63.         if (cat != null) {  
    64.             return Response.status(Status.BAD_REQUEST).build();  
    65.         } else {  
    66.             getCategoryDAO().addCategory(category);  
    67.             return Response.ok(category).build();  
    68.         }  
    69.   
    70.     }  
    71.   
    72.     @DELETE  
    73.     @Path("/category/{id}")  
    74.     @Consumes({"application/json","application/xml"})  
    75.     public Response deleteCategory(@PathParam("id") String id) {  
    76.   
    77.         System.out.println("deleteCategory with category id : " + id);  
    78.   
    79.         Category cat = (Category) getCategoryDAO().getCategory(id);  
    80.         if (cat == null) {  
    81.             return Response.status(Status.BAD_REQUEST).build();  
    82.         } else {  
    83.             getCategoryDAO().deleteCategory(id);  
    84.             return Response.ok().build();  
    85.         }  
    86.     }  
    87.   
    88.     @PUT  
    89.     @Path("/category")  
    90.     @Consumes({"application/json","application/xml"})  
    91.     public Response updateCategory(Category category) {  
    92.   
    93.         System.out.println("updateCategory with category id : "  
    94.                 + category.getCategoryId());  
    95.   
    96.         Category cat = (Category) getCategoryDAO().getCategory(  
    97.                 category.getCategoryId());  
    98.         if (cat == null) {  
    99.             return Response.status(Status.BAD_REQUEST).build();  
    100.         } else {  
    101.             getCategoryDAO().updateCategory(category);  
    102.             return Response.ok(category).build();  
    103.         }  
    104.     }  
    105.   
    106.     @POST  
    107.     @Path("/category/book")  
    108.     @Consumes({"application/json","application/xml"})  
    109.     public Response addBooks(Category category) {  
    110.   
    111.         System.out.println("addBooks with category id : "  
    112.                 + category.getCategoryId());  
    113.   
    114.         Category cat = (Category) getCategoryDAO().getCategory(  
    115.                 category.getCategoryId());  
    116.         if (cat == null) {  
    117.             return Response.status(Status.NOT_FOUND).build();  
    118.         } else {  
    119.             getCategoryDAO().addBook(category);  
    120.             return Response.ok(category).build();  
    121.         }  
    122.     }  
    123.   
    124.     @GET  
    125.     @Path("/category/{id}/books")  
    126.     @Consumes("application/xml,application/json")  
    127.     public Response getBooks(@PathParam("id") String id) {  
    128.   
    129.         System.out.println("getBooks called with category id : " + id);  
    130.   
    131.         Category cat = (Category) getCategoryDAO().getCategory(id);  
    132.   
    133.         if (cat == null) {  
    134.             return Response.status(Status.NOT_FOUND).build();  
    135.         } else {  
    136.             cat.setBooks(getCategoryDAO().getBooks(id));  
    137.             return Response.ok(cat).build();  
    138.   
    139.         }  
    140.     }  
    141.   
    142. }  
    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

    Java代码  
    1. package demo.restful;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.Collection;  
    5. import java.util.HashMap;  
    6. import java.util.Map;  
    7.   
    8. /* 
    9.  * DataAcess object for performing CRUD operations. 
    10.  * Dummy implementation. 
    11.  */  
    12. public class CategoryDAO {  
    13.   
    14.     private static Map<String, Category> categoryMap = new HashMap<String, Category>();  
    15.     private static Map<String, Collection<Book>> bookMap = new HashMap<String, Collection<Book>>();  
    16.   
    17.     static {  
    18.   
    19.         Category category1 = new Category();  
    20.         category1.setCategoryId("001");  
    21.         category1.setCategoryName("Java");  
    22.         categoryMap.put(category1.getCategoryId(), category1);  
    23.   
    24.         Book book1 = new Book();  
    25.         book1.setAuthor("Naveen Balani");  
    26.         book1.setBookName("Spring Series");  
    27.         book1.setBookId("001");  
    28.         book1.setBookISBNnumber("ISB001");  
    29.   
    30.         Book book2 = new Book();  
    31.         book2.setAuthor("Rajeev Hathi");  
    32.         book2.setBookName("CXF Series");  
    33.         book2.setBookId("002");  
    34.         book2.setBookISBNnumber("ISB002");  
    35.   
    36.         Collection<Book> booksList = new ArrayList<Book>();  
    37.         booksList.add(book1);  
    38.         booksList.add(book2);  
    39.   
    40.         bookMap.put(category1.getCategoryId(), booksList);  
    41.     }  
    42.   
    43.     public void addCategory(Category category) {  
    44.         categoryMap.put(category.getCategoryId(), category);  
    45.   
    46.     }  
    47.   
    48.     public void addBook(Category category) {  
    49.         bookMap.put(category.getCategoryId(), category.getBooks());  
    50.   
    51.     }  
    52.   
    53.     public Collection<Book> getBooks(String categoryId) {  
    54.         return bookMap.get(categoryId);  
    55.   
    56.     }  
    57.   
    58.     public Category getCategory(String id) {  
    59.         Category cat = null;  
    60.         //Dummy implementation to return a new copy of category to   
    61.       //avoid getting overridden by service  
    62.         if(categoryMap.get(id) != null) {  
    63.         cat = new Category();  
    64.         cat.setCategoryId(categoryMap.get(id).getCategoryId());  
    65.         cat.setCategoryName(categoryMap.get(id).getCategoryName());  
    66.         }  
    67.         return cat;  
    68.     }  
    69.   
    70.     public void deleteCategory(String id) {  
    71.         categoryMap.remove(id);  
    72.         // Remove association of books  
    73.         bookMap.remove(id);  
    74.     }  
    75.   
    76.     public void updateCategory(Category category) {  
    77.         categoryMap.put(category.getCategoryId(), category);  
    78.   
    79.     }  
    80.   
    81. }  
    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客户端。

    Java代码  
    1. package demo.restful.client;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.Collection;  
    5. import java.util.Iterator;  
    6.   
    7. import javax.ws.rs.core.Response;  
    8.   
    9. import org.apache.cxf.jaxrs.client.WebClient;  
    10.   
    11. import demo.restful.Book;  
    12. import demo.restful.Category;  
    13.   
    14. public class CategoryServiceRESTClient {  
    15.   
    16.     //Put some static value  
    17.     private static final String CATEGORY_URL = "http://localhost:9000/";  
    18.     private static final String CATEGORY_ID = "005";  
    19.     private static final String TYPE_XML = "application/xml";  
    20.     private static final String TYPE_JSON = "application/json";  
    21.   
    22.     public static void main(String[] args) {  
    23.   
    24.         //System.out.println("Format is " + args[0]);  
    25.   
    26.         testAddCategory(TYPE_XML);  
    27.         testUpdateCategory(TYPE_XML);  
    28.         testGetCategory(TYPE_XML);  
    29.         testAddBooksForCategory(TYPE_XML);  
    30.         testGetBooksForCategory(TYPE_XML);  
    31.         testDeleteCategory(TYPE_XML);  
    32.   
    33.         testAddCategory(TYPE_JSON);  
    34.         testUpdateCategory(TYPE_JSON);  
    35.         testGetCategory(TYPE_JSON);  
    36.         testAddBooksForCategory(TYPE_JSON);  
    37.         testGetBooksForCategory(TYPE_JSON);  
    38.         testDeleteCategory(TYPE_JSON);  
    39.   
    40. //      if(args[0] !=null && args[0].equalsIgnoreCase(TYPE_XML)){  
    41. //          //Content type- XML  
    42. //          testAddCategory(TYPE_XML);  
    43. //          testUpdateCategory(TYPE_XML);  
    44. //          testGetCategory(TYPE_XML);  
    45. //          testAddBooksForCategory(TYPE_XML);  
    46. //          testGetBooksForCategory(TYPE_XML);  
    47. //          testDeleteCategory(TYPE_XML);  
    48. //      }  
    49. //        
    50. //      if(args[0] !=null && args[0].equalsIgnoreCase(TYPE_JSON)){  
    51. //          //ContentType- JSON  
    52. //          testAddCategory(TYPE_JSON);  
    53. //          testUpdateCategory(TYPE_JSON);  
    54. //          testGetCategory(TYPE_JSON);  
    55. //          testAddBooksForCategory(TYPE_JSON);  
    56. //          testGetBooksForCategory(TYPE_JSON);  
    57. //          testDeleteCategory(TYPE_JSON);  
    58. //      }  
    59.   
    60.   
    61.     }  
    62.   
    63.     private static void testAddCategory(final String format) {  
    64.   
    65.         System.out.println("testAddCategory called with format " + format);  
    66.         WebClient client = WebClient.create(CATEGORY_URL);  
    67.         client.path("/categoryservice/category").accept(  
    68.                 format).type(format);  
    69.         Category cat = new Category();  
    70.         cat.setCategoryId(CATEGORY_ID);  
    71.         cat.setCategoryName("Fiction");  
    72.         Category catResponse = client.post(cat, Category.class);  
    73.         System.out.println("Category Id retreived for format " + format + " is " + catResponse.getCategoryId());  
    74.         assertEquals(catResponse.getCategoryId(), CATEGORY_ID);  
    75.   
    76.   
    77.     }  
    78.   
    79.     private static void testUpdateCategory(final String format) {  
    80.   
    81.         System.out.println("testUpdateCategory called with format " + format);  
    82.         WebClient client = WebClient.create(CATEGORY_URL);  
    83.         client.path("/categoryservice/category").accept(  
    84.                 format).type(format);  
    85.         Category cat = new Category();  
    86.         cat.setCategoryId(CATEGORY_ID);  
    87.         cat.setCategoryName("Fiction Series");  
    88.         Response response = client.put(cat);  
    89.         System.out.println("Status retreived for update category for format " + format + " is " + response.getStatus());  
    90.         assertEquals("200", String.valueOf(response.getStatus()));  
    91.   
    92.   
    93.     }  
    94.   
    95.     private static void testGetCategory(final String format) {  
    96.   
    97.         System.out.println("testGetCategory called with format " + format);  
    98.         WebClient client = WebClient.create(CATEGORY_URL);  
    99.         Category category = client.path("/categoryservice/category/" + CATEGORY_ID).accept(  
    100.                 format).type(format).get(Category.class);  
    101.         System.out.println("Category details retreived from service with format " + format);  
    102.         System.out.println("Category Name " + category.getCategoryName());  
    103.         System.out.println("Category Id " + category.getCategoryId());  
    104.         assertEquals(CATEGORY_ID, category.getCategoryId());  
    105.   
    106.   
    107.     }  
    108.   
    109.     private static void testAddBooksForCategory(final String format) {  
    110.   
    111.         System.out.println("testAddBooksForCategory called with format " + format);  
    112.         WebClient client = WebClient.create(CATEGORY_URL);  
    113.         client.path("/categoryservice/category/book").type(format).  
    114.                 accept(format);  
    115.         Category cat = new Category();  
    116.         cat.setCategoryId(CATEGORY_ID);  
    117.         cat.setCategoryName("Fiction Series");  
    118.         Book book1 = new Book();  
    119.         book1.setAuthor("Naveen Balani");  
    120.         book1.setBookId("NB001");  
    121.         book1.setBookISBNnumber("ISBNB001");  
    122.         book1.setBookName("Fiction Book1");  
    123.   
    124.         Collection<Book> booksList = new ArrayList<Book>();  
    125.         booksList.add(book1);  
    126.         cat.setBooks(booksList);  
    127.         client.post(cat, Category.class);  
    128.   
    129.   
    130.   
    131.     }  
    132.   
    133.     private static void testGetBooksForCategory(final String format) {  
    134.   
    135.         System.out.println("testGetBooksForCategory called with format " + format);  
    136.         WebClient clientBook = WebClient.create(CATEGORY_URL);  
    137.         Category categoryBooks = clientBook.path(  
    138.                 "/categoryservice/category/" + CATEGORY_ID + "/books").type(format).accept(format).get(Category.class);  
    139.         System.out.println("Book details retreived from service with format " + format);  
    140.   
    141.         assertEquals(String.valueOf(categoryBooks.getBooks().size()), "1");  
    142.   
    143.         Iterator<Book> iterator = categoryBooks.getBooks().iterator();  
    144.         while (iterator.hasNext()) {  
    145.             Book book = iterator.next();  
    146.             System.out.println("Book Name " + book.getBookName());  
    147.             System.out.println("Book ISBN " + book.getBookISBNnumber());  
    148.             System.out.println("Book ID " + book.getBookId());  
    149.             System.out.println("Book Author " + book.getAuthor());  
    150.   
    151.         }  
    152.   
    153.   
    154.     }  
    155.   
    156.     private static void testDeleteCategory(final String format) {  
    157.   
    158.         System.out.println("testDeleteCategory called with format " + format);  
    159.         WebClient client = WebClient.create(CATEGORY_URL);  
    160.         client.path("/categoryservice/category/" + CATEGORY_ID).type(format).  
    161.                 accept(format);  
    162.         Response response = client.delete();  
    163.         System.out.println("Status retreived for delete category for format " + format + " is " + response.getStatus());  
    164.         assertEquals("200", String.valueOf(response.getStatus()));  
    165.   
    166.   
    167.     }  
    168.   
    169.     private static void assertEquals(String expected, String result) {  
    170.         if (!expected.equalsIgnoreCase(result)) {  
    171.             throw new RuntimeException("Expecte value " + expected + ", Got value" + result);  
    172.         }  
    173.     }  
    174. }  

    http://reymont.iteye.com/blog/1523822

  • 相关阅读:
    体检套餐管理系统
    在这个与金沂同桌的日子里,我在北大青鸟学习了 第四章 深入类的方法 下面是我的上机3
    总结
    今天晚上雨夹雪,爱人狠心把我撇。今夜孤独一个人,只好来把代码写。 欢迎阅读我的第四章笔记 深入类的方法
    我在北京写代码 写出心中悲与喜 写出人间的悲欢离合 欢迎阅读 我的第三章 使用集合组织相关数据(泛型集合)
    在那个春暖花开的季节 今天微微的小雨 伴着轻轻的晚风我们一起来编写 员工考勤信息管理
    非泛型集合
    经理评分系统
    模仿魔兽登录界面 编程小练习
    【BZOJ 3524】【Poi2014】Couriers 可持久化线段树
  • 原文地址:https://www.cnblogs.com/heartstage/p/3409640.html
Copyright © 2020-2023  润新知