spring+restful service

Spring整合CXF,發佈RSETful 風格WebService

這篇文章是承接以前CXF整合Spring的這個項目示例的延伸,因此有很大一部分都是同樣的。關於發佈CXF WebServer和Spring整合CXF這裏就再也不多加贅述了。若是你對Spring整合CXF WebService不瞭解,具體你能夠參看這兩篇文章:html

http://www.cnblogs.com/hoojo/archive/2011/03/30/1999563.htmljava

http://www.cnblogs.com/hoojo/archive/2012/07/13/2590593.htmlweb

若是你不瞭解restful風格的WebService,你能夠參考:spring

http://www.oracle.com/technetwork/articles/javase/index-137171.htmlapache

SpringMVC對RESTful的支持:json

http://www.cnblogs.com/hoojo/archive/2011/06/10/2077422.htmlapi

使用 Jersey框架,搭建RESTful WebService(這個也比較簡單)瀏覽器

http://www.ibm.com/developerworks/cn/web/wa-aj-tomcat/tomcat

官方文檔:http://jersey.java.net/nonav/documentation/latest/user-guide.html#d4e8服務器

其中,比較經常使用的RESTful框架就有Jersey、Spring REST、CXF RESTful,這些均可以很好的整合Spring框架,發佈也至關的簡單。且簡單、易用、易上手,文檔也比較豐富。

 

開發環境:

System:Windows

JavaEE Server:tomcat6

JavaSDK: jdk6+

IDE:eclipse、MyEclipse 6.6

 

開發依賴庫:

JDK六、 JavaEE五、CXF-2.3.三、Spring 3.0.4

Email:hoojo_@126.com

Blog:http://blog.csdn.net/IBM_hoojo

http://hoojo.cnblogs.com/

http://hoojo.blogjava.net

 

下面咱們就接着http://www.cnblogs.com/hoojo/archive/2011/03/30/1999563.html這篇文章,開始咱們CXF RESTful WebService的旅程,enjoy~!^_*

 

準備工做

首先,你須要添加相關的jar包

image

其中,jsr331-api-1.1.1.jar是必須的,利用CXF發佈REST服務得用到它,在cxf的lib庫中能夠找到這個jar。

下載地址:http://www.apache.org/dyn/closer.cgi?path=/cxf/2.3.11/apache-cxf-2.3.11.zip

其它的jar包都是非必須的!

JavaEntity

package com.hoo.entity;
 
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
 
/**
 * <b>function:</b> MapBean 封裝Map集合元素
 * @author hoojo
 * @createDate 2012-7-20 下午01:22:31
 * @file MapBean.java
 * @package com.hoo.entity
 * @project CXFWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@XmlRootElement
public class MapBean {
    private Map<String, User> map;

    //@XmlElement(type = User.class)
    public Map<String, User> getMap() {
        return map;
    }
    public void setMap(Map<String, User> map) {
        this.map = map;
    }
}

 

package com.hoo.entity;
 
import java.util.HashMap;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
 
/**
 * <b>function:</b> Users Entity
 * @author hoojo
 * @createDate 2011-3-18 上午09:27:31
 * @file Users.java
 * @package com.hoo.entity
 * @project CXFWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@XmlRootElement(name = "UserInfos")
public class Users {
    private List<User> users;

    private User[] userArr;

    private HashMap<String, User> maps;


   // getter/setter
}
package com.hoo.entity;
 
import java.io.Serializable;
import javax.xml.bind.annotation.XmlRootElement;
 
/**
 * <b>function:</b>User Entity
 * @author hoojo
 * @createDate Dec 16, 2010 10:20:02 PM
 * @file User.java
 * @package com.hoo.entity
 * @project AxisWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@XmlRootElement(name = "UserInfo")
public class User implements Serializable {
    private static final long serialVersionUID = 677484458789332877L;
    private int id;
    private String name;
    private String email;
    private String address;

    //getter/setter

    @Override
    public String toString() {
        return this.id + "#" + this.name + "#" + this.email + "#" + this.address;
    }
}

1、定義你的WebService的接口RESTSample.java,代碼以下

package com.hoo.service;
 
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.core.Context;
import javax.ws.rs.core.MediaType;
 
import com.hoo.entity.MapBean;
import com.hoo.entity.User;
import com.hoo.entity.Users;
 
 
/*
     註釋(Annotation):在 javax.ws.rs.* 中定義,是 JAX-RS (JSR 311) 規範的一部分。
    @Path:定義資源基 URI。由上下文根和主機名組成,資源標識符相似於 http://localhost:8080/RESTful/rest/hello。
    @GET:這意味着如下方法能夠響應 HTTP GET 方法。
    @Produces:以純文本方式定義響應內容 MIME 類型。
   
    @Context: 使用該註釋注入上下文對象,好比 Request、Response、UriInfo、ServletContext 等。
    @Path("{contact}"):這是 @Path 註釋,與根路徑 「/contacts」 結合造成子資源的 URI。
    @PathParam("contact"):該註釋將參數注入方法參數的路徑,在本例中就是聯繫人 id。其餘可用的註釋有 @FormParam、@QueryParam 等。
    @Produces:響應支持多個 MIME 類型。在本例和上一個示例中,APPLICATION/XML 將是默認的 MIME 類型。
 */
/**
 * <b>function:</b> CXF RESTful風格WebService
 * @author hoojo
 * @createDate 2012-7-20 下午01:23:04
 * @file RESTSampleSource.java
 * @package com.hoo.service
 * @project CXFWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@Path(value = "/sample")
public interface RESTSample {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String doGet();

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/request/{param}")
    public String doRequest(@PathParam("param") String param,
            @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse);

    @GET
    @Path("/bean/{id}")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public User getBean(@PathParam("id") int id);

    @GET
    @Path("/list")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Users getList();

    @GET
    @Path("/map")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public MapBean getMap();

    /*
        @Consumes:聲明該方法使用 HTML FORM。
        @FormParam:注入該方法的 HTML 屬性肯定的表單輸入。
        @Response.created(uri).build(): 構建新的 URI 用於新建立的聯繫人(/contacts/{id})並設置響應代碼(201/created)。
        您可使用 http://localhost:8080/Jersey/rest/contacts/<id> 訪問新聯繫人
     */
    @POST
    @Path("/postData")
    public User postData(User user) throws IOException;

    @PUT
    @Path("/putData/{id}")
    @Consumes(MediaType.APPLICATION_XML)
    public User putData(@PathParam("id") int id, User user);

    @DELETE
    @Path("/removeData/{id}")
    public void deleteData(@PathParam("id") int id);
}

 

2、RESTSample接口的實現,這裏咱們只是簡單的實現下,並非涉及實際的具體業務

package com.hoo.service;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
import com.hoo.entity.MapBean;
import com.hoo.entity.User;
import com.hoo.entity.Users;
 
 
/*
     註釋(Annotation):在 javax.ws.rs.* 中定義,是 JAX-RS (JSR 311) 規範的一部分。
    @Path:定義資源基 URI。由上下文根和主機名組成,資源標識符相似於 http://localhost:8080/RESTful/rest/hello。
    @GET:這意味着如下方法能夠響應 HTTP GET 方法。
    @Produces:以純文本方式定義響應內容 MIME 類型。
   
    @Context: 使用該註釋注入上下文對象,好比 Request、Response、UriInfo、ServletContext 等。
    @Path("{contact}"):這是 @Path 註釋,與根路徑 「/contacts」 結合造成子資源的 URI。
    @PathParam("contact"):該註釋將參數注入方法參數的路徑,在本例中就是聯繫人 id。其餘可用的註釋有 @FormParam、@QueryParam 等。
    @Produces:響應支持多個 MIME 類型。在本例和上一個示例中,APPLICATION/XML 將是默認的 MIME 類型。
 */
/**
 * <b>function:</b> CXF RESTful風格WebService
 * @author hoojo
 * @createDate 2012-7-20 下午01:23:04
 * @file RESTSampleSource.java
 * @package com.hoo.service
 * @project CXFWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@Path(value = "/sample")
public class RESTSampleSource implements RESTSample {

    @Context
    private UriInfo uriInfo;

    @Context
    private Request request;
 

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String doGet() {
        return "this is get rest request";
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/request/{param}")
    public String doRequest(@PathParam("param") String param,
            @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) {
        System.out.println(servletRequest);
        System.out.println(servletResponse);
        System.out.println(servletRequest.getParameter("param"));
        System.out.println(servletRequest.getContentType());
        System.out.println(servletResponse.getCharacterEncoding());
        System.out.println(servletResponse.getContentType());
        return "success";
    }

    @GET
    @Path("/bean/{id}")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public User getBean(@PathParam("id") int id) {
        System.out.println("####getBean#####");
        System.out.println("id:" + id);
        System.out.println("Method:" + request.getMethod());
        System.out.println("uri:" + uriInfo.getPath());
        System.out.println(uriInfo.getPathParameters());

        User user = new User();
        user.setId(id);
        user.setName("JojO");
        return user;
    }

    @GET
    @Path("/list")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Users getList() {
        System.out.println("####getList#####");
        System.out.println("Method:" + request.getMethod());
        System.out.println("uri:" + uriInfo.getPath());
        System.out.println(uriInfo.getPathParameters());

        List<User> list = new ArrayList<User>();
        User user = null;
        for (int i = 0; i < 4;i ++) {
            user = new User();
            user.setId(i);
            user.setName("JojO-" + i);
            list.add(user);
        }
        Users users = new Users();
        users.setUsers(list);
        return users;
    }

    @GET
    @Path("/map")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public MapBean getMap() {
        System.out.println("####getMap#####");
        System.out.println("Method:" + request.getMethod());
        System.out.println("uri:" + uriInfo.getPath());
        System.out.println(uriInfo.getPathParameters());

        Map<String, User> map = new HashMap<String, User>();
        User user = null;
        for (int i = 0; i < 4;i ++) {
            user = new User();
            user.setId(i);
            user.setName("JojO-" + i);
            map.put("key-" + i, user);
        }
        MapBean bean = new MapBean();
        bean.setMap(map);
        return bean;
    }

    /*
        @Consumes:聲明該方法使用 HTML FORM。
        @FormParam:注入該方法的 HTML 屬性肯定的表單輸入。
        @Response.created(uri).build(): 構建新的 URI 用於新建立的聯繫人(/contacts/{id})並設置響應代碼(201/created)。
        您可使用 http://localhost:8080/Jersey/rest/contacts/<id> 訪問新聯繫人
     */
    @POST
    @Path("/postData")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public User postData(User user) throws IOException {
        System.out.println(user);
        user.setName("jojo##12321321");
        return user;
    }

    @PUT
    @Path("/putData/{id}")
    @Produces({ MediaType.APPLICATION_XML })
    public User putData(@PathParam("id") int id, User user) {
        System.out.println("#####putData#####");
        System.out.println(user);
        user.setId(id);
        user.setAddress("hoojo#gz");
        user.setEmail("hoojo_@126.com");
        user.setName("hoojo");
        System.out.println(user);
        return user;
    }

    @DELETE
    @Path("/removeData/{id}")
    public void deleteData(@PathParam("id") int id) {
        System.out.println("#######deleteData#######" + id);
    }
}

3、配置咱們的WebService,修改applicationContext-server.xml。這裏主要是添加jaxrs標籤的支持,修改頭部文件以下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs"
    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-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.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">

特別注意上面加粗帶下劃線的部分,這是新增長的配置。咱們發佈restful WebService須要用到它。

而後在配置文件中添加以下配置

<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<bean id="restSample" class="com.hoo.service.RESTSampleSource"/>
<!-- 這裏的地址很重要,客戶端須要經過這個地址來訪問WebService -->
<jaxrs:server id="restServiceContainer" address="/rest">
    <jaxrs:serviceBeans>
        <ref bean="restSample" />
    </jaxrs:serviceBeans>
    <jaxrs:extensionMappings>
        <entry key="json" value="application/json" />
        <entry key="xml" value="application/xml" />
    </jaxrs:extensionMappings>
    <jaxrs:languageMappings>
           <entry key="en" value="en-gb"/>
    </jaxrs:languageMappings>
</jaxrs:server>

這樣服務器端就完成了CXF RESTful WebService的發佈,啓動你的tomcat。而後在瀏覽器中服務地址:http://localhost:8000/CXFWebService/ (其實這裏請求的是CXFServlet,你能夠看看上一篇Spring整合CXF文章的web.xml的配置)

你就能夠看到咱們這裏剛剛發佈的RESTSample rest的WebService

image 

你也能夠看看裏面的xml,也就是WebService的wsdl文件內容。咱們找一個GET方式的WebService的方法,在瀏覽器中調用一下試試

http://localhost:8000/CXFWebService/rest/sample/bean/123

這個url對應到下面這個方法

@GET
@Path("/bean/{id}")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public User getBean(@PathParam("id") int id)

結果以下

image

一篇xml文檔內容。

 

4、編寫客戶端代碼,調用RESTful WebService

package com.hoo.client;
 
import java.io.IOException;
import javax.ws.rs.core.MediaType;
import org.apache.cxf.jaxrs.client.WebClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.hoo.entity.MapBean;
import com.hoo.entity.User;
import com.hoo.entity.Users;
import com.hoo.service.RESTSample;
 
/**
 * <b>function:</b> RESTful風格WebService
 * @author hoojo
 * @createDate 2012-7-20 下午03:31:03
 * @file RSETServiceClient.java
 * @package com.hoo.client
 * @project CXFWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class RSETServiceClient {
 
    private static WebClient client;

    @Before
    public void init() {
        // 手動建立webClient對象,注意這裏的地址是發佈的那個/rest地址
        //String url = "http://localhost:8000/CXFWebService/rest/";
        //client = WebClient.create(url);
 
        // 從Spring Ioc容器中拿webClient對象
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-client.xml");
        client = ctx.getBean("webClient", WebClient.class);
    }

    @After
    public void destory(){
    }

    @Test
    public void testGet() {
        System.out.println(client.path("sample").accept(MediaType.TEXT_PLAIN).get(String.class));
    }

    @Test
    public void testRequest() {
        System.out.println(client.path("sample/request/234234").accept(MediaType.TEXT_PLAIN).get(String.class));
    }

    @Test
    public void testBean() {
        User user = client.path("sample/bean/{id}", 25).accept(MediaType.APPLICATION_XML).get(User.class);
        System.out.println(user);
    }

    @Test
    public void testList() {
        System.out.println(client.path("sample/list").accept(MediaType.APPLICATION_XML).get(Users.class).getUsers());
    }

    @Test
    public void testMap() {
        System.out.println(client.path("sample/map").accept(MediaType.APPLICATION_XML).get(MapBean.class).getMap());
    }

    @Test
    public void testDeleteData() {
        client.path("sample/removeData/23").delete();
    }

    @Test
    public void testPostData() {
        User user = new User();
        user.setId(21432134);
        user.setAddress("hoojo#gz");
        user.setEmail("hoojo_@126.com");
        user.setName("hoojo");
        System.out.println(client.path("sample/postData").accept(MediaType.APPLICATION_XML).post(user, User.class));
    }

    @Test
    public void testPutData() {
        User user = new User();
        user.setId(21432134);
        System.out.println(client.path("sample/putData/1").accept(MediaType.APPLICATION_XML).put(user).getEntity());
    }
}

若是你喜歡用Spring的方式,還須要在applicationContext-client.xml中增長以下配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    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-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://cxf.apache.org/jaxws
    http://cxf.apache.org/schemas/jaxws.xsd">

    <bean id="webClient" class="org.apache.cxf.jaxrs.client.WebClient" factory-method="create">
        <constructor-arg type="java.lang.String" value="http://localhost:8000/CXFWebService/rest/" />
    </bean>

</beans>

這種是利用WebClient對象來調用WebService,還有一種方法也能夠調用WebService,代碼以下:

// 手動建立
//RESTSample sample = JAXRSClientFactory.create("http://localhost:8000/CXFWebService/rest", RESTSample.class);
 
// 從Spring Ioc容器中拿webClient對象
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-client.xml");
RESTSample sample = ctx.getBean("restSampleBean", RESTSample.class);
 
System.out.println(sample);
 
System.out.println(sample.doGet());
//System.out.println(sample.doRequest("haha", null, null));
System.out.println(sample.getBean(22));
System.out.println(sample.getList());
System.out.println(sample.getMap().getMap());
User user = new User();
user.setId(21432134);
user.setAddress("hoojo#gz");
user.setEmail("hoojo_@126.com");
user.setName("hoojo");
System.out.println(sample.postData(user));
System.out.println(sample.putData(111, user));
sample.deleteData(2);

這種方式相對比WebClient要簡單,直接使用接口中的方法便可。一樣若是你要整合到Spring能夠在applicationContext-client.xml中增長配置以下:

<bean id="restSampleBean" class="org.apache.cxf.jaxrs.client.JAXRSClientFactory" factory-method="create">
    <constructor-arg type="java.lang.String" value="http://localhost:8000/CXFWebService/rest/" />
    <constructor-arg type="java.lang.Class" value="com.hoo.service.RESTSample" />
</bean>

 

執行以上方法能夠看到控制檯打印結果以下:

client console
org.apache.cxf.jaxrs.client.ClientProxyImpl@1cf7491
this is get rest request
22#JojO#null#null
com.hoo.entity.Users@16eb6bc
{key-0=0#JojO-0#null#null, key-1=1#JojO-1#null#null, key-2=2#JojO-2#null#null, key-3=3#JojO-3#null#null}
21432134#jojo##12321321#hoojo_@126.com#hoojo#gz
111#hoojo#hoojo_@126.com#hoojo#gz
 
server console
####getBean#####
id:22
Method:GET
uri:sample/bean/22
{id=[22]}
####getList#####
Method:GET
uri:sample/list
{}
####getMap#####
Method:GET
uri:sample/map
{}
21432134#hoojo#hoojo_@126.com#hoojo#gz
#####putData#####
21432134#hoojo#hoojo_@126.com#hoojo#gz
111#hoojo#hoojo_@126.com#hoojo#gz
#######deleteData#######2

就這樣,整合restful WebService成功。

Spring整合CXF,發佈RSETful 風格WebService

這篇文章是承接以前CXF整合Spring的這個項目示例的延伸,因此有很大一部分都是同樣的。關於發佈CXF WebServer和Spring整合CXF這裏就再也不多加贅述了。若是你對Spring整合CXF WebService不瞭解,具體你能夠參看這兩篇文章:

http://www.cnblogs.com/hoojo/archive/2011/03/30/1999563.html

http://www.cnblogs.com/hoojo/archive/2012/07/13/2590593.html

若是你不瞭解restful風格的WebService,你能夠參考:

http://www.oracle.com/technetwork/articles/javase/index-137171.html

SpringMVC對RESTful的支持:

http://www.cnblogs.com/hoojo/archive/2011/06/10/2077422.html

使用 Jersey框架,搭建RESTful WebService(這個也比較簡單)

http://www.ibm.com/developerworks/cn/web/wa-aj-tomcat/

官方文檔:http://jersey.java.net/nonav/documentation/latest/user-guide.html#d4e8

其中,比較經常使用的RESTful框架就有Jersey、Spring REST、CXF RESTful,這些均可以很好的整合Spring框架,發佈也至關的簡單。且簡單、易用、易上手,文檔也比較豐富。

 

開發環境:

System:Windows

JavaEE Server:tomcat6

JavaSDK: jdk6+

IDE:eclipse、MyEclipse 6.6

 

開發依賴庫:

JDK六、 JavaEE五、CXF-2.3.三、Spring 3.0.4

Email:hoojo_@126.com

Blog:http://blog.csdn.net/IBM_hoojo

http://hoojo.cnblogs.com/

http://hoojo.blogjava.net

 

下面咱們就接着http://www.cnblogs.com/hoojo/archive/2011/03/30/1999563.html這篇文章,開始咱們CXF RESTful WebService的旅程,enjoy~!^_*

 

準備工做

首先,你須要添加相關的jar包

image

其中,jsr331-api-1.1.1.jar是必須的,利用CXF發佈REST服務得用到它,在cxf的lib庫中能夠找到這個jar。

下載地址:http://www.apache.org/dyn/closer.cgi?path=/cxf/2.3.11/apache-cxf-2.3.11.zip

其它的jar包都是非必須的!

JavaEntity

package com.hoo.entity;
 
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
 
/**
 * <b>function:</b> MapBean 封裝Map集合元素
 * @author hoojo
 * @createDate 2012-7-20 下午01:22:31
 * @file MapBean.java
 * @package com.hoo.entity
 * @project CXFWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@XmlRootElement
public class MapBean {
    private Map<String, User> map;

    //@XmlElement(type = User.class)
    public Map<String, User> getMap() {
        return map;
    }
    public void setMap(Map<String, User> map) {
        this.map = map;
    }
}

 

package com.hoo.entity;
 
import java.util.HashMap;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
 
/**
 * <b>function:</b> Users Entity
 * @author hoojo
 * @createDate 2011-3-18 上午09:27:31
 * @file Users.java
 * @package com.hoo.entity
 * @project CXFWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@XmlRootElement(name = "UserInfos")
public class Users {
    private List<User> users;

    private User[] userArr;

    private HashMap<String, User> maps;


   // getter/setter
}
package com.hoo.entity;
 
import java.io.Serializable;
import javax.xml.bind.annotation.XmlRootElement;
 
/**
 * <b>function:</b>User Entity
 * @author hoojo
 * @createDate Dec 16, 2010 10:20:02 PM
 * @file User.java
 * @package com.hoo.entity
 * @project AxisWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@XmlRootElement(name = "UserInfo")
public class User implements Serializable {
    private static final long serialVersionUID = 677484458789332877L;
    private int id;
    private String name;
    private String email;
    private String address;

    //getter/setter

    @Override
    public String toString() {
        return this.id + "#" + this.name + "#" + this.email + "#" + this.address;
    }
}

1、定義你的WebService的接口RESTSample.java,代碼以下

package com.hoo.service;
 
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.core.Context;
import javax.ws.rs.core.MediaType;
 
import com.hoo.entity.MapBean;
import com.hoo.entity.User;
import com.hoo.entity.Users;
 
 
/*
     註釋(Annotation):在 javax.ws.rs.* 中定義,是 JAX-RS (JSR 311) 規範的一部分。
    @Path:定義資源基 URI。由上下文根和主機名組成,資源標識符相似於 http://localhost:8080/RESTful/rest/hello。
    @GET:這意味着如下方法能夠響應 HTTP GET 方法。
    @Produces:以純文本方式定義響應內容 MIME 類型。
   
    @Context: 使用該註釋注入上下文對象,好比 Request、Response、UriInfo、ServletContext 等。
    @Path("{contact}"):這是 @Path 註釋,與根路徑 「/contacts」 結合造成子資源的 URI。
    @PathParam("contact"):該註釋將參數注入方法參數的路徑,在本例中就是聯繫人 id。其餘可用的註釋有 @FormParam、@QueryParam 等。
    @Produces:響應支持多個 MIME 類型。在本例和上一個示例中,APPLICATION/XML 將是默認的 MIME 類型。
 */
/**
 * <b>function:</b> CXF RESTful風格WebService
 * @author hoojo
 * @createDate 2012-7-20 下午01:23:04
 * @file RESTSampleSource.java
 * @package com.hoo.service
 * @project CXFWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@Path(value = "/sample")
public interface RESTSample {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String doGet();

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/request/{param}")
    public String doRequest(@PathParam("param") String param,
            @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse);

    @GET
    @Path("/bean/{id}")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public User getBean(@PathParam("id") int id);

    @GET
    @Path("/list")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Users getList();

    @GET
    @Path("/map")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public MapBean getMap();

    /*
        @Consumes:聲明該方法使用 HTML FORM。
        @FormParam:注入該方法的 HTML 屬性肯定的表單輸入。
        @Response.created(uri).build(): 構建新的 URI 用於新建立的聯繫人(/contacts/{id})並設置響應代碼(201/created)。
        您可使用 http://localhost:8080/Jersey/rest/contacts/<id> 訪問新聯繫人
     */
    @POST
    @Path("/postData")
    public User postData(User user) throws IOException;

    @PUT
    @Path("/putData/{id}")
    @Consumes(MediaType.APPLICATION_XML)
    public User putData(@PathParam("id") int id, User user);

    @DELETE
    @Path("/removeData/{id}")
    public void deleteData(@PathParam("id") int id);
}

 

2、RESTSample接口的實現,這裏咱們只是簡單的實現下,並非涉及實際的具體業務

package com.hoo.service;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
import com.hoo.entity.MapBean;
import com.hoo.entity.User;
import com.hoo.entity.Users;
 
 
/*
     註釋(Annotation):在 javax.ws.rs.* 中定義,是 JAX-RS (JSR 311) 規範的一部分。
    @Path:定義資源基 URI。由上下文根和主機名組成,資源標識符相似於 http://localhost:8080/RESTful/rest/hello。
    @GET:這意味着如下方法能夠響應 HTTP GET 方法。
    @Produces:以純文本方式定義響應內容 MIME 類型。
   
    @Context: 使用該註釋注入上下文對象,好比 Request、Response、UriInfo、ServletContext 等。
    @Path("{contact}"):這是 @Path 註釋,與根路徑 「/contacts」 結合造成子資源的 URI。
    @PathParam("contact"):該註釋將參數注入方法參數的路徑,在本例中就是聯繫人 id。其餘可用的註釋有 @FormParam、@QueryParam 等。
    @Produces:響應支持多個 MIME 類型。在本例和上一個示例中,APPLICATION/XML 將是默認的 MIME 類型。
 */
/**
 * <b>function:</b> CXF RESTful風格WebService
 * @author hoojo
 * @createDate 2012-7-20 下午01:23:04
 * @file RESTSampleSource.java
 * @package com.hoo.service
 * @project CXFWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@Path(value = "/sample")
public class RESTSampleSource implements RESTSample {

    @Context
    private UriInfo uriInfo;

    @Context
    private Request request;
 

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String doGet() {
        return "this is get rest request";
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/request/{param}")
    public String doRequest(@PathParam("param") String param,
            @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) {
        System.out.println(servletRequest);
        System.out.println(servletResponse);
        System.out.println(servletRequest.getParameter("param"));
        System.out.println(servletRequest.getContentType());
        System.out.println(servletResponse.getCharacterEncoding());
        System.out.println(servletResponse.getContentType());
        return "success";
    }

    @GET
    @Path("/bean/{id}")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public User getBean(@PathParam("id") int id) {
        System.out.println("####getBean#####");
        System.out.println("id:" + id);
        System.out.println("Method:" + request.getMethod());
        System.out.println("uri:" + uriInfo.getPath());
        System.out.println(uriInfo.getPathParameters());

        User user = new User();
        user.setId(id);
        user.setName("JojO");
        return user;
    }

    @GET
    @Path("/list")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Users getList() {
        System.out.println("####getList#####");
        System.out.println("Method:" + request.getMethod());
        System.out.println("uri:" + uriInfo.getPath());
        System.out.println(uriInfo.getPathParameters());

        List<User> list = new ArrayList<User>();
        User user = null;
        for (int i = 0; i < 4;i ++) {
            user = new User();
            user.setId(i);
            user.setName("JojO-" + i);
            list.add(user);
        }
        Users users = new Users();
        users.setUsers(list);
        return users;
    }

    @GET
    @Path("/map")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public MapBean getMap() {
        System.out.println("####getMap#####");
        System.out.println("Method:" + request.getMethod());
        System.out.println("uri:" + uriInfo.getPath());
        System.out.println(uriInfo.getPathParameters());

        Map<String, User> map = new HashMap<String, User>();
        User user = null;
        for (int i = 0; i < 4;i ++) {
            user = new User();
            user.setId(i);
            user.setName("JojO-" + i);
            map.put("key-" + i, user);
        }
        MapBean bean = new MapBean();
        bean.setMap(map);
        return bean;
    }

    /*
        @Consumes:聲明該方法使用 HTML FORM。
        @FormParam:注入該方法的 HTML 屬性肯定的表單輸入。
        @Response.created(uri).build(): 構建新的 URI 用於新建立的聯繫人(/contacts/{id})並設置響應代碼(201/created)。
        您可使用 http://localhost:8080/Jersey/rest/contacts/<id> 訪問新聯繫人
     */
    @POST
    @Path("/postData")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public User postData(User user) throws IOException {
        System.out.println(user);
        user.setName("jojo##12321321");
        return user;
    }

    @PUT
    @Path("/putData/{id}")
    @Produces({ MediaType.APPLICATION_XML })
    public User putData(@PathParam("id") int id, User user) {
        System.out.println("#####putData#####");
        System.out.println(user);
        user.setId(id);
        user.setAddress("hoojo#gz");
        user.setEmail("hoojo_@126.com");
        user.setName("hoojo");
        System.out.println(user);
        return user;
    }

    @DELETE
    @Path("/removeData/{id}")
    public void deleteData(@PathParam("id") int id) {
        System.out.println("#######deleteData#######" + id);
    }
}

3、配置咱們的WebService,修改applicationContext-server.xml。這裏主要是添加jaxrs標籤的支持,修改頭部文件以下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs"
    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-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.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">

特別注意上面加粗帶下劃線的部分,這是新增長的配置。咱們發佈restful WebService須要用到它。

而後在配置文件中添加以下配置

<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<bean id="restSample" class="com.hoo.service.RESTSampleSource"/>
<!-- 這裏的地址很重要,客戶端須要經過這個地址來訪問WebService -->
<jaxrs:server id="restServiceContainer" address="/rest">
    <jaxrs:serviceBeans>
        <ref bean="restSample" />
    </jaxrs:serviceBeans>
    <jaxrs:extensionMappings>
        <entry key="json" value="application/json" />
        <entry key="xml" value="application/xml" />
    </jaxrs:extensionMappings>
    <jaxrs:languageMappings>
           <entry key="en" value="en-gb"/>
    </jaxrs:languageMappings>
</jaxrs:server>

這樣服務器端就完成了CXF RESTful WebService的發佈,啓動你的tomcat。而後在瀏覽器中服務地址:http://localhost:8000/CXFWebService/ (其實這裏請求的是CXFServlet,你能夠看看上一篇Spring整合CXF文章的web.xml的配置)

你就能夠看到咱們這裏剛剛發佈的RESTSample rest的WebService

image 

你也能夠看看裏面的xml,也就是WebService的wsdl文件內容。咱們找一個GET方式的WebService的方法,在瀏覽器中調用一下試試

http://localhost:8000/CXFWebService/rest/sample/bean/123

這個url對應到下面這個方法

@GET
@Path("/bean/{id}")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public User getBean(@PathParam("id") int id)

結果以下

image

一篇xml文檔內容。

 

4、編寫客戶端代碼,調用RESTful WebService

package com.hoo.client;
 
import java.io.IOException;
import javax.ws.rs.core.MediaType;
import org.apache.cxf.jaxrs.client.WebClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.hoo.entity.MapBean;
import com.hoo.entity.User;
import com.hoo.entity.Users;
import com.hoo.service.RESTSample;
 
/**
 * <b>function:</b> RESTful風格WebService
 * @author hoojo
 * @createDate 2012-7-20 下午03:31:03
 * @file RSETServiceClient.java
 * @package com.hoo.client
 * @project CXFWebService
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class RSETServiceClient {
 
    private static WebClient client;

    @Before
    public void init() {
        // 手動建立webClient對象,注意這裏的地址是發佈的那個/rest地址
        //String url = "http://localhost:8000/CXFWebService/rest/";
        //client = WebClient.create(url);
 
        // 從Spring Ioc容器中拿webClient對象
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-client.xml");
        client = ctx.getBean("webClient", WebClient.class);
    }

    @After
    public void destory(){
    }

    @Test
    public void testGet() {
        System.out.println(client.path("sample").accept(MediaType.TEXT_PLAIN).get(String.class));
    }

    @Test
    public void testRequest() {
        System.out.println(client.path("sample/request/234234").accept(MediaType.TEXT_PLAIN).get(String.class));
    }

    @Test
    public void testBean() {
        User user = client.path("sample/bean/{id}", 25).accept(MediaType.APPLICATION_XML).get(User.class);
        System.out.println(user);
    }

    @Test
    public void testList() {
        System.out.println(client.path("sample/list").accept(MediaType.APPLICATION_XML).get(Users.class).getUsers());
    }

    @Test
    public void testMap() {
        System.out.println(client.path("sample/map").accept(MediaType.APPLICATION_XML).get(MapBean.class).getMap());
    }

    @Test
    public void testDeleteData() {
        client.path("sample/removeData/23").delete();
    }

    @Test
    public void testPostData() {
        User user = new User();
        user.setId(21432134);
        user.setAddress("hoojo#gz");
        user.setEmail("hoojo_@126.com");
        user.setName("hoojo");
        System.out.println(client.path("sample/postData").accept(MediaType.APPLICATION_XML).post(user, User.class));
    }

    @Test
    public void testPutData() {
        User user = new User();
        user.setId(21432134);
        System.out.println(client.path("sample/putData/1").accept(MediaType.APPLICATION_XML).put(user).getEntity());
    }
}

若是你喜歡用Spring的方式,還須要在applicationContext-client.xml中增長以下配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    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-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://cxf.apache.org/jaxws
    http://cxf.apache.org/schemas/jaxws.xsd">

    <bean id="webClient" class="org.apache.cxf.jaxrs.client.WebClient" factory-method="create">
        <constructor-arg type="java.lang.String" value="http://localhost:8000/CXFWebService/rest/" />
    </bean>

</beans>

這種是利用WebClient對象來調用WebService,還有一種方法也能夠調用WebService,代碼以下:

// 手動建立
//RESTSample sample = JAXRSClientFactory.create("http://localhost:8000/CXFWebService/rest", RESTSample.class);
 
// 從Spring Ioc容器中拿webClient對象
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-client.xml");
RESTSample sample = ctx.getBean("restSampleBean", RESTSample.class);
 
System.out.println(sample);
 
System.out.println(sample.doGet());
//System.out.println(sample.doRequest("haha", null, null));
System.out.println(sample.getBean(22));
System.out.println(sample.getList());
System.out.println(sample.getMap().getMap());
User user = new User();
user.setId(21432134);
user.setAddress("hoojo#gz");
user.setEmail("hoojo_@126.com");
user.setName("hoojo");
System.out.println(sample.postData(user));
System.out.println(sample.putData(111, user));
sample.deleteData(2);

這種方式相對比WebClient要簡單,直接使用接口中的方法便可。一樣若是你要整合到Spring能夠在applicationContext-client.xml中增長配置以下:

<bean id="restSampleBean" class="org.apache.cxf.jaxrs.client.JAXRSClientFactory" factory-method="create">
    <constructor-arg type="java.lang.String" value="http://localhost:8000/CXFWebService/rest/" />
    <constructor-arg type="java.lang.Class" value="com.hoo.service.RESTSample" />
</bean>

 

執行以上方法能夠看到控制檯打印結果以下:

client console
org.apache.cxf.jaxrs.client.ClientProxyImpl@1cf7491
this is get rest request
22#JojO#null#null
com.hoo.entity.Users@16eb6bc
{key-0=0#JojO-0#null#null, key-1=1#JojO-1#null#null, key-2=2#JojO-2#null#null, key-3=3#JojO-3#null#null}
21432134#jojo##12321321#hoojo_@126.com#hoojo#gz
111#hoojo#hoojo_@126.com#hoojo#gz
 
server console
####getBean#####
id:22
Method:GET
uri:sample/bean/22
{id=[22]}
####getList#####
Method:GET
uri:sample/list
{}
####getMap#####
Method:GET
uri:sample/map
{}
21432134#hoojo#hoojo_@126.com#hoojo#gz
#####putData#####
21432134#hoojo#hoojo_@126.com#hoojo#gz
111#hoojo#hoojo_@126.com#hoojo#gz
#######deleteData#######2

就這樣,整合restful WebService成功。

相關文章
相關標籤/搜索