前言

续上篇Apache CXF 101,摘抄部分REST概念性知识,以运行实例考察CXF对REST的支持。

目录

1 REST简介

2 工具

3 运行实例

内容

本Spike记录中内容,如无特别指出,均引用[1]。

1 REST简介

有两种实现Web Service的主要方式:SOAP(Simple Object Access Protocl)和REST架构风格(Representational State Transfer architecture style)。

用REST架构风格构建的服务(RESTful服务),用简单的XML等形式封装数据、通过HTTP传输数据。

与基于SOAP的服务开发方法相比,施加于服务开发者的技术负担更小,特别是服务只需发送和接收简单的XML消息时。

REST架构风格是关于资源的,资源是用URI(Uniform Resource Indicator)标识的表示(representation)。
资源可以是任意信息,例如Book、Order等。客户通过交换资源的表示来查询或更新URI标识的资源。

表示中包含以具体格式记录的实际信息,常见的格式有HTML/XML/JSON。客户通常可以指定它/他/她需要的表示。所有处理特定资源上的信息均包含于请求自身,使得交互是无状态的。

用REST架构风格原则构建的Web服务称为RESTful Web服务。RESTful Web服务可视为可通过URI标识的资源。RESTful Web服务用标准的HTTP方法(GET/POST…)暴露操作的集合。客户使用HTTP协议通过URI访问/调用这些方法。

RESTful Service URI example
http://cxf.spike.com/department/deptname/employee
GET 返回部门中雇员列表
POST 创建部门中雇员记录
DELETE 删除部门中雇员记录

JSR support
JAX-RS[2]
JAS-RS定义这些目标:
POJO为中心
JAX-RS API提供了一组注解和相关的类/接口,将POJO暴露为RESTful资源。
HTTP为中心
RESTful资源通过HTTP协议暴露,该规范提供了清晰的HTTP协议与相关的JAX-RS API中类、方法之间的映射。同时提供了如何匹配HTTP请求到资源类和方法的指南。
格式独立
该API提供了一种可插拔机制,该机制允许以标准的方式添加HTTP内容类型。
容器独立
用JAX-RS开发的应用应该可以运行于任意容器中。该规范定义了如何用JAX-RS API部署应用的标准机制。
Java企业版容器包含
该规范定义了RESTful资源如何宿于Java EE6容器和如何利用容器提供的功能。

JAX-RS的实现[3]
Apache CXF 开源的Web服务框架。
Jersey 由Sun提供的JAX-RS的参考实现。
RESTEasy JBoss的实现。
Restlet 由Jerome Louvel和Dave Pawson开发,是最早的REST框架,先于JAX-RS出现。
Apache Wink 一个Apache软件基金会孵化器中的项目,其服务模块实现JAX-RS规范

2 工具

Firefox插件:Poster(https://addons.mozilla.org/en-US/firefox/addon/poster/)

安装后工具位置

工具面板

用数据测试

结果呈现

3 运行实例

Book Shop Application
Functionality:
(1) Category CRUD
(2) Add Books to a Category
(3) Getting Books belongs to a Category

[1]中指出了(CXF) RESTful服务开发实践步骤

(1) 创建Request/Response的Java数据对象

(2) 绑定Request/Response对象

(3) 创建RESTful实现:创建实现类并用JAX-RS注解

(4) 服务单元测试

(5) 创建客户端,调用服务方法

(6) 将服务部署于容器中

(1) 创建Request/Response的Java数据对象

(2) 绑定Request/Response对象

两个JAXB绑定的pojo,JAXB是CXF默认的绑定方式

Book

package demo.restful.pojo;

import javax.xml.bind.annotation.XmlRootElement;

/**
 * Description: Book<br/>
 * Date: 2014-5-12 下午10:54:16
 */
@XmlRootElement(name = "Book")
public class Book {
    private String bookId;
    private String bookISBNnumber;
    private String bookName;
    private String author;//one author only

    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;
    }

    @Override
    public String toString() {
        return "Book [bookId=" + bookId + ", bookISBNnumber=" + bookISBNnumber + ", bookName=" + bookName + ", author=" + author + "]";
    }

}

Category

package demo.restful.pojo;

import java.util.List;

import javax.xml.bind.annotation.XmlRootElement;

/**
 * Description: Category<br/>
 * Date: 2014-5-12 下午10:53:52
 */
@XmlRootElement(name = "Category")
public class Category {
    private String categoryId;
    private String categoryName;
    private List<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 List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }

    @Override
    public String toString() {
        return "Category [categoryId=" + categoryId + ", categoryName=" + categoryName + ", books=" + books + "]";
    }

}

(3) 创建RESTful实现:创建实现类并用JAX-RS注解

CategoryService接口

package demo.restful.service;

import javax.ws.rs.core.Response;

import demo.restful.pojo.Category;

/**
 * Description: Category Service Interface With Exception Handling<br/>
 * Date: 2014-5-12 下午11:12:02
 */
public interface CategoryService {

    public Category getCategory(String id);

    public Response addCategory(Category category);

    public Response deleteCategory(String id);

    public Response updateCategory(Category category);

    public Response addBooks(Category category);

    public Response getBooks(String id);
}

CategoryService实现类

package demo.restful.service;

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;

import demo.restful.data.CategoryDAO;
import demo.restful.pojo.Category;

/**
 * Description: Category Service Implementation With Exception Handling<br/>
 * Date: 2014-5-12 下午11:12:02
 */
@Path("/categoryservice")
@Produces({ "application/xml", "application/json" })
public class CategoryServiceImpl implements CategoryService {
    private CategoryDAO categoryDAO;//wired

    public CategoryDAO getCategoryDAO() {
        return categoryDAO;
    }

    public void setCategoryDAO(CategoryDAO categoryDAO) {
        this.categoryDAO = categoryDAO;
    }

    @GET
    @Path("/category/{id}")
    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/xml", "application/json" })
    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}")
    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")
    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/xml", "application/json" })
    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();
        }
    }
}

以内存中Map实现的DAO:服务支持类CategoryDAO

package demo.restful.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import demo.restful.pojo.Book;
import demo.restful.pojo.Category;

/**
 * Description: Category DAO Stub Implementation<br/>
 * Date: 2014-5-12 下午11:22:17
 */
public class CategoryDAO {
    //category-id : category
    private static Map<String, Category> categoryMap = new HashMap<String, Category>();
    //category-id : books
    private static Map<String, List<Book>> bookMap = new HashMap<String, List<Book>>();
    static {
        //Populate some static data
        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");
        List<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);
    }

    //Add Books associated with the Category
    public void addBook(Category category) {
        bookMap.put(category.getCategoryId(), category.getBooks());
    }

    public List<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);
    }
}

(4) 服务单元测试

因服务有灵活的部署方式,部署在Servlet容器中上一篇记录中已经有所说明,另一种方式是以常规应用程序直接运行在JVM中。

Server实现

Spring配置文件restapp.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="categoryService" class="demo.restful.service.CategoryServiceImpl">
        <property name="categoryDAO">
            <ref bean="categoryDAO" />
        </property>
    </bean>

    <bean id="categoryDAO" class="demo.restful.data.CategoryDAO">
    </bean>

</beans>

常量类

package demo.restful;

/**
 * Description: 常量类<br/>
 * Date: 2014-5-12 下午11:41:09
 */
public class Constants {
    public static final String SERVICE_URL = "http://localhost:9000/";
}

Server

package demo.restful.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import demo.restful.Constants;
import demo.restful.pojo.Book;
import demo.restful.pojo.Category;
import demo.restful.service.CategoryService;
import demo.restful.service.CategoryServiceImpl;

/**
 * Description: Server<br/>
 * Date: 2014-5-12 下午11:37:09
 */
public class Server {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { "/demo/restful/restapp.xml" });
        CategoryService categoryService = (CategoryServiceImpl) appContext.getBean("categoryService");

        // Service instance
        JAXRSServerFactoryBean restServer = new JAXRSServerFactoryBean();
        restServer.setResourceClasses(Category.class, Book.class);
        restServer.setServiceBean(categoryService);
        restServer.setAddress(Constants.SERVICE_URL);
        restServer.create();

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
            br.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Server Stopped");
        System.exit(0);
    }
}

这样自然的,单元测试就有两种方法:部署在Servlet容器中的服务以浏览器/Poster测试,以常规应用程序部署的服务则可以编写JUnit单元测试。

Poster测试

这里用到的Poster的两个主要设置:

"Content to Send"label中将"Content Type"设置为application/xml(或application/json,视准备数据而定)

"Header"label中添加Name: Accept, Value: application/xml(或application/json)

新增Category

更新Category

JUnit单元测试

HTTPClient - 简单的服务客户端示例

package demo.restful.client;

import java.util.Iterator;

import org.apache.cxf.jaxrs.client.WebClient;

import demo.restful.pojo.Book;
import demo.restful.pojo.Category;

/**
 * Description: HTTP Client<br/>
 * Date: 2014-5-12 下午11:57:41
 */
public class HTTPClient {

    public static void main(String[] args) {
        WebClient client = WebClient.create("http://localhost:9000/");
        Category category = client.path("categoryservice/category/001").accept("application/xml").get(Category.class);
        System.out.println("Category details from REST service.");
        System.out.println("Category Name " + category.getCategoryName());
        System.out.println("Category Id " + category.getCategoryId());
        System.out.println("Book details for Category " + category.getCategoryId() + " from REST service");
        String bookString = "categoryservice/category/" + category.getCategoryId() + "/books";
        WebClient clientBook = WebClient.create("http://localhost:9000/");
        Category categoryBooks = clientBook.path(bookString).accept("application/xml").get(Category.class);
        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());
        }
    }

}

RESTCategoryService,测试媒体类型application/xml,为直观显示执行结果,未使用JUnit断言。

package demo.restful.client;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.ws.rs.core.Response;

import org.apache.cxf.jaxrs.client.WebClient;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import demo.restful.pojo.Book;
import demo.restful.pojo.Category;

/**
 * Description: RESTCategoryService in Servlet Container Unit test<br/>
 * Date: 2014-5-13 下午9:41:27
 */
public class RESTCategoryServiceTest {
    private WebClient client = null;
    private static final String FORMAT = "application/xml";
    private static String id = null;

    @BeforeClass
    public static void setUpBeforClass() {
        id = newId();
    }

    @Before
    public void setUp() {
        client = WebClient.create("http://localhost:8082/CXF/");
    }

    @Test
    public void getCategory() {
        System.out.println("======================getCategory");
        Category category = client.path("categoryservice/category/001").accept(FORMAT).get(Category.class);
        System.out.println(category);
        System.out.println("======================getCategory");

    }

    @Test
    public void addCategory() {
        System.out.println("======================addCategory");
        Category category = new Category();
        category.setCategoryId(id);
        category.setCategoryName(".NET");
        System.out.println("Add " + category + "...");
        Category response = client.path("categoryservice/category").accept(FORMAT).type(FORMAT).post(category, Category.class);
        System.out.println(response);
        //test using query
        System.out.println("Get category " + id + "...");
        client = WebClient.create("http://localhost:8082/CXF/");//new WebClient!!!
        System.out.println(client.path("categoryservice/category/" + id).accept(FORMAT).get(Category.class));
        System.out.println("======================addCategory");
    }

    @Test
    public void updateCategory() {
        System.out.println("======================updateCategory");
        Category category = new Category();
        category.setCategoryId(id);
        category.setCategoryName("Microsoft .NET");
        Response response = client.path("categoryservice/category").put(category);
        System.out.println(response.getStatus());
        System.out.println(response.getEntity());
        System.out.println("======================updateCategory");
    }

    @Test
    public void addBooks() {
        System.out.println("======================addBooks");
        client.path("/categoryservice/category/book").type(FORMAT).accept(FORMAT);
        Category cat = new Category();
        cat.setCategoryId(id);
        cat.setCategoryName("Fiction Series");
        Book book1 = new Book();
        book1.setAuthor("Naveen Balani");
        book1.setBookId("NB001");
        book1.setBookISBNnumber("ISBNB001");
        book1.setBookName("Fiction Book1");
        List<Book> booksList = new ArrayList<Book>();
        booksList.add(book1);
        cat.setBooks(booksList);
        Category response = client.post(cat, Category.class);
        System.out.println(response);
        System.out.println("======================addBooks");
    }

    @Test
    public void getBooks() {
        System.out.println("======================getBooks");
        Category category = client.path("/categoryservice/category/" + id + "/books").accept(FORMAT).get(Category.class);
        System.out.println("Book details retreived from service with format " + FORMAT);
        List<Book> books = category.getBooks();
        for (Book book : books) {
            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());
        }
        System.out.println("======================getBooks");
    }

    @Test
    public void deleteCategory() {
        System.out.println("======================deleteCategory");
        Response response = client.path("categoryservice/category/" + id).delete();
        System.out.println(response.getStatus());
        System.out.println("======================deleteCategory");
    }

    private static String newId() {
        return UUID.randomUUID().toString().replaceAll("\\-", "").toUpperCase();
    }
}

JSONRESTCategoryServiceTest,与RESTCategoryService基本相同,唯一的区别在于媒体类型为application/json

package demo.restful.client;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.ws.rs.core.Response;

import org.apache.cxf.jaxrs.client.WebClient;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import demo.restful.pojo.Book;
import demo.restful.pojo.Category;

/**
 * Description: JSONRESTCategoryService in Servlet Container Unit test<br/>
 * Date: 2014-5-13 下午9:41:27
 */
public class JSONRESTCategoryServiceTest {
    private WebClient client = null;
    private static final String FORMAT = "application/json";
    private static String id = null;

    @BeforeClass
    public static void setUpBeforClass() {
        id = newId();
    }

    @Before
    public void setUp() {
        client = WebClient.create("http://localhost:8082/CXF/");
    }

    @Test
    public void getCategory() {
        System.out.println("======================getCategory");
        Category category = client.path("categoryservice/category/001").accept(FORMAT).get(Category.class);
        System.out.println(category);
        System.out.println("======================getCategory");

    }

    @Test
    public void addCategory() {
        System.out.println("======================addCategory");
        Category category = new Category();
        category.setCategoryId(id);
        category.setCategoryName(".NET");
        System.out.println("Add " + category + "...");
        Category response = client.path("categoryservice/category").accept(FORMAT).type(FORMAT).post(category, Category.class);
        System.out.println(response);
        //test using query
        System.out.println("Get category " + id + "...");
        client = WebClient.create("http://localhost:8082/CXF/");//new WebClient!!!
        System.out.println(client.path("categoryservice/category/" + id).accept(FORMAT).get(Category.class));
        System.out.println("======================addCategory");
    }

    @Test
    public void updateCategory() {
        System.out.println("======================updateCategory");
        Category category = new Category();
        category.setCategoryId(id);
        category.setCategoryName("Microsoft .NET");
        Response response = client.path("categoryservice/category").put(category);
        System.out.println(response.getStatus());
        System.out.println(response.getEntity());
        System.out.println("======================updateCategory");
    }

    @Test
    public void addBooks() {
        System.out.println("======================addBooks");
        client.path("/categoryservice/category/book").type(FORMAT).accept(FORMAT);
        Category cat = new Category();
        cat.setCategoryId(id);
        cat.setCategoryName("Fiction Series");
        Book book1 = new Book();
        book1.setAuthor("Naveen Balani");
        book1.setBookId("NB001");
        book1.setBookISBNnumber("ISBNB001");
        book1.setBookName("Fiction Book1");
        List<Book> booksList = new ArrayList<Book>();
        booksList.add(book1);
        cat.setBooks(booksList);
        Category response = client.post(cat, Category.class);
        System.out.println(response);
        System.out.println("======================addBooks");
    }

    @Test
    public void getBooks() {
        System.out.println("======================getBooks");
        Category category = client.path("/categoryservice/category/" + id + "/books").accept(FORMAT).get(Category.class);
        System.out.println("Book details retreived from service with format " + FORMAT);
        List<Book> books = category.getBooks();
        for (Book book : books) {
            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());
        }
        System.out.println("======================getBooks");
    }

    @Test
    public void deleteCategory() {
        System.out.println("======================deleteCategory");
        Response response = client.path("categoryservice/category/" + id).delete();
        System.out.println(response.getStatus());
        System.out.println("======================deleteCategory");
    }

    private static String newId() {
        return UUID.randomUUID().toString().replaceAll("\\-", "").toUpperCase();
    }
}

(5) 创建客户端,调用服务方法

见HTTPClient示例。

(6) 将服务部署于容器中

上一篇记录中已经有所说明。

//FIXME need to add description about Servlet container delopyment descriptor  and CXF-Spring Intergration configuarations

Servlet容器部署描述符web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>CXF</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
    <servlet>
        <description>Apache CXF Endpoint</description>
        <display-name>cxf</display-name>
        <servlet-name>cxf</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>cxf</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
        WEB-INF/cxf-beans.xml
        classpath:/demo/restful/restapp.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

CXF-Spring集成配置文件cxf-beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">

    <import resource="classpath:META-INF/cxf/cxf-all.xml" />
    <!-- <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"
        /> -->
    <import resource="classpath:/demo/restful/restapp.xml" />

    <jaxws:endpoint xmlns:tns="http://cxf.spike.com/" id="helloservice" implementor="com.spike.cxf.HelloServiceImpl"
        wsdlLocation="wsdl/helloserviceimpl.wsdl" endpointName="tns:HelloServiceImplPort" serviceName="tns:HelloServiceImplService"
        address="/HelloServiceImplPort">
        <jaxws:features>
            <bean class="org.apache.cxf.feature.LoggingFeature" />
        </jaxws:features>
    </jaxws:endpoint>

    <jaxrs:server id="categoryRESTService" address="/">
        <jaxrs:features>
            <cxf:logging />
        </jaxrs:features>
        <jaxrs:serviceBeans>
            <ref bean="categoryService" />
        </jaxrs:serviceBeans>
    </jaxrs:server>
</beans>

参考资料

[1]Balani N., Hathi R..Apache CXF web service development Develop and deploy SOAP and RESTful web service[M]. Birmingham: Packet Publishing. 2009.
[2]JSR311: JAX-RS: The JavaTM API for RESTful Web Services[EB/OL]. https://jcp.org/en/jsr/detail?id=311. 2014-05-12.
[3]JAX-RS. Wiki. http://zh.wikipedia.org/wiki/JAX-RS. 2014-05-12.

最新文章

  1. [转载]Java 8 日期&amp;时间 API
  2. sass中级语法
  3. node body-parser
  4. java SpringUtil获取bean
  5. Liz Murray成功故事的偶然与必然(转)
  6. [leetcode72]Edit Distance(dp)
  7. C#中OpenFileDialog的使用
  8. 翻译Android USB HOST API
  9. php部分学习笔记
  10. java链接mysql数据库
  11. 约瑟夫环-循环队列算法(曾微软,google笔试题)
  12. 如何去掉修改Joomla、joomlart及其模版版权、标志、图标的方法
  13. 开机出现loading Operating System的解决方案
  14. 利用ATiny85制作BadUSB
  15. nodejs静态web服务
  16. Python自动化开发 - AJAX
  17. 如何在ecplise中配置maven以及ecplise访问本地仓库
  18. Exchanger学习
  19. js随机生成[n,m)的数字(不包括m)
  20. WCF之契约的分类(部分為參考他人)

热门文章

  1. The C10K problem
  2. FloatingActionButton增强版,一个按钮跳出多个按钮--第三方开源--FloatingActionButton
  3. HDU 1533 KM算法(权值最小的最佳匹配)
  4. DP 剪枝
  5. 求x^0+x^1+x^2+.......x^n mod p; x,n,p&lt;=10^9
  6. 3.5缺少动态连接库.so--cannot open shared object file: No such file or directory
  7. EL表达式中获取list长度
  8. 跨域SSO的实现
  9. 在Hadoop集群中添加机器和删除机器
  10. 走进科学之WAF(Web Appllication Firewall)篇