CXF開發webservice

什麼是CXF:javascript

Apache CXF = Celtix + Xfirehtml

            支持多種協議:java

            SOAP1.1,1.2jquery

            XML/HTTPc++

            CORBA(Common Object Request Broker Architecture公共對象請求代理體系結構,早期語言使用的WS。                    C,c++,C#) web

            並能夠與Spring進行快速無縫的整合ajax

            靈活的部署:能夠運行在Tomcat,Jboss,Jetty(內置),IBMWS,BeaWL上面。spring


安裝CXF的其餘支持項目:apache

Ant編程

Tomcat

並設置如下環境變量:

            JAVA_HOME  

            CXF_HOME

            ANT_HOME

            CATALINA_HOME

            Path = %JAVA_HOME%\bin;%CXF_HOME%\bin;%CATALINA_HOME%\bin;%ANT_HOME%\bin

            CLASSPATH=.;%CXF_HOME%\lib\cxf-manifest.jar;.\build\classes


在Eclipse中開發CXF的JavaSE應用:

導入CXF中的 全部jar文件。能夠經過WACH_JARS來觀察各jar文件的用途。

創建好以後的項目如圖所示:



CXF發佈服務的類:

用兩個不一樣的類發佈應用:

            ServerFactoryBean   -- FacotryBean

            JaxWsServerFactoryBean(建議使用此類)

使用ServerFactoryBean發佈服務:

    

/**
 * 使用ServerFactoryBean發佈CXF的javase應用
 * @author zhaoqx
 *
 */
public class HelloService {
	
	public String sayHello(String name){
		System.out.println("sayHello called...");
		return "hello " + name;
	}
	public static void main(String[] args) {
		ServerFactoryBean bean = new ServerFactoryBean();
		bean.setAddress("http://192.168.1.24:9999/Hello");
		bean.setServiceClass(HelloService.class);
		bean.setServiceBean(new HelloService());
		bean.create();
		System.err.print("啓動成功");
	}
}


使用ClientProxyFactoryBean客戶端調用

使用ServerFactoryBean發佈服務之後,在沒有接口的狀況下,可使用wsimport生成的客戶端代碼調用成功。

但若是要使用ClientProxyFactoryBean客戶端去調用服務器,則必需要先在服務器端建立一個接口。(一直以來,Spring都要求面向接口編程,而cxf與Spring能很好的整合,也就在此。),因此,必需要重寫服務器端的代碼。這將致使剛纔使用wsimport生成的調用代碼失效。

同時, ClientProxyFactoryBean因爲要用到CXF環境,因此要導入CXF的全部包。

同時,若是是在本項目中調用,則能夠直接使用本項目的接口。

若是在其餘項目中調用,仍然需wsimport生成的類,但只須要一個接口。



使用JaxWsServerFactoryBean發佈服務: (建議使用此類)

    JaxWsServerFactoryBean是ServerFactoryBean的子類,也是功能擴展類。但在CXF的API文檔中沒有提供此類API,請經過查看源代碼的方式獲取此類的幫助。此類,必需要在被髮布爲服務的類上添加@WebService註解,若是不加註解,雖然不出錯,但也不會對外暴露任何方法。使用此類生成的wsdl文件更加規範。

@WebService
//@javax.xml.ws.BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public class HiService {
	public String sayHi(String name){
		System.out.println("服務調用");
		return "Hi"+name;
	}
	public static void main(String[] args) {
		JaxWsServerFactoryBean bean = new JaxWsServerFactoryBean();
		bean.setAddress("http://localhost:9999/two");
		bean.setServiceClass(HiService.class);
		bean.setServiceBean(new HiService());
		bean.create();
		System.err.print("服務啓動成功");
	}
}


使用JaxWsProxyFactoryBean客戶端調用:

此調用過程與ClientProxyFactoryBean的要求同樣,也必需要擁有一個接口。

此時,仍然可使用wsimport生成接口,在其餘項目的調用。



規範的作法應該是先書寫一個接口,以下:

@WebService
public interface IHelloService {
	public String sayHello(String name);
}
public class IHelloServiceImpl implements IHelloService {

	public String sayHello(String name) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return sdf.format(new Date())+"=== hello=====" + name;
	}
	
	public static void main(String[] args) {
		JaxWsServerFactoryBean bean = new JaxWsServerFactoryBean();
		bean.setAddress("http://192.168.1.24:8888/sayHi");
		bean.setServiceClass(IHelloService.class);
		bean.setServiceBean(new IHelloServiceImpl());
		//加入請求消息攔截器
		bean.getInInterceptors().add(new LoggingInInterceptor());
		//加入響應消息攔截器
		bean.getOutInterceptors().add(new LoggingOutInterceptor());
		bean.create();
		System.err.print("服務啓動成功");
	}

}


wsdl2java生成客戶代碼:

在cxf中,也提供了一個用於生成客戶端調用代碼的工具。它的功能就如同wsimport同樣。

先讓咱們瞭解一下cxf的wsdl2java工具,能夠生成一堆客戶端調用的代碼。

此工具位於cxf_home/bin目錄下。參數與wsimport有所不一樣。

它包含如下參數:

-d參數,指定代碼生成的目錄。

-p參數,指定生成的新的包結構。

須要說明的是,因爲wsdl2java是根據jdk1.7生成的本地代碼,因此,須要對生成的代碼作一點點修改。

在命令行執行:

wsdl2java –d . http://127.0.0.1:6666/helloworld?wsdl


調用端代碼:


使用JavaScript也能夠訪問WebServie:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>使用jquery的ajax調用Web服務 </title>
    <script type="text/javascript" src="js/jquery-1.6.2.js"></script>
    <script type="text/javascript">
    	$(function(){
    		$("#but1").click(function(){
    			//指定訪問服務的地址
    			var wsUrl = "http://localhost:8090/CXF03/cxf/hi";
    			//構造請求體
    			var soap = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHi xmlns:ns2="http://kaiyi/"><arg0>abc</arg0></ns2:sayHi></soap:Body></soap:Envelope>';
    			$.ajax({
						url:wsUrl,
						type:'post',
						dataType:'xml',
						contentType:'text/xml;charset=UTF-8',
						data:soap,
						success:function(data){
							alert('OK!');
							var o = $(data);
							alert(o.find('return').eq(0).text());
						},
						error:function(){
							alert('error!');
						}
						});
    		});
    	});
    </script>
  </head>
  
  <body>
    <input type="button" value="發送jquery的ajax請求" id="but1">
  </body>
</html>


以上均是非WEB的開發下面介紹基於web的cxf

因爲cxf的web項目已經集成了Spring因此,cxf的服務類都是在spring的配置文件中完成的。如下是步驟:

第一步:創建一個web項目。

第二步:準備全部jar包。將cxf_home\lib項目下的全部jar包所有copy到新項目的lib目錄下,裏面已經包含了spring3.0的jar包。

第三步:在web.xml中配置cxf的核心servlet,CXFServlet。

第四步:建立(最好是Copy)cxf-servlet.xml文件。這是一個spring的配置文件。


cxf-servlet.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:soap="http://cxf.apache.org/bindings/soap" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans.xsd
						http://cxf.apache.org/bindings/soap 
						http://cxf.apache.org/schemas/configuration/soap.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
						">
	<!-- 引入CXF Bean定義以下,早期的版本中使用 -->
	<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" />

	<!-- 經過spring配置文件發佈CXF的服務 -->

	<!-- 第一種發佈方式:沒有接口的發佈(簡單發佈) -->
	<!-- 
		id:惟一標識
		address:訪問url
		implementor:提供服務的類型 
	 -->
	<jaxws:endpoint id="helloService" address="/hello"
		implementor="kaiyi.HelloService">
		<!-- 加入消息攔截器 -->
		<jaxws:inInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
		</jaxws:inInterceptors>
		<jaxws:outInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
		</jaxws:outInterceptors>
	</jaxws:endpoint>
	
	<!-- 第二種發佈方式:帶有接口的發佈 -->
	<jaxws:server id="hiService" address="/hi" serviceClass="kaiyi.IHiService">
		<jaxws:serviceBean>
			<!-- 提供服務的實現類 -->
			<bean class="kaiyi.IHiServiceImpl"></bean>
		</jaxws:serviceBean>
		<!-- 加入消息攔截器  -->
		<jaxws:inInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
		</jaxws:inInterceptors>
		<jaxws:outInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
		</jaxws:outInterceptors>
	</jaxws:server>
	
	<!-- 配置restful方式的web服務 -->
	<bean id="ps" class="restful.PersonServiceImpl"></bean>
	<jaxrs:server id="personService" address="/p">
		<jaxrs:serviceBeans>
			<ref bean="ps"/>
		</jaxrs:serviceBeans>
		<jaxrs:inInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
		</jaxrs:inInterceptors>
		<jaxrs:outInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
		</jaxrs:outInterceptors>
	</jaxrs:server>
</beans>


web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	
	<!-- 經過上下文參數指定spring配置文件的位置 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:cxf-servlet.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<!-- 配置CXF框架的核心Servlet  -->
	<servlet>
		<servlet-name>cxf</servlet-name>
		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
		<!-- 經過初始化參數指定配置文件的位置 -->
		<!--  
		<init-param>
			<param-name>config-location</param-name>
			<param-value>classpath:cxf-servlet.xml</param-value>
		</init-param>-->
		 
	</servlet>

	<servlet-mapping>
		<servlet-name>cxf</servlet-name>
		<url-pattern>/cxf/*</url-pattern>
	</servlet-mapping>
	
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

這是個人包結構:

/**
 * 使用ServerFactoryBean發佈CXF的javase應用
 * @author zhaoqx
 *
 */
@WebService
public class HelloService {
	
	public String sayHello(String name){
		System.out.println("sayHello called...");
		return "hello " + name;
	}
	
}


package kaiyi;

import javax.jws.WebService;

@WebService
public interface IHiService {
	public String sayHi(String name);
}
package kaiyi;

public class IHiServiceImpl implements  IHiService{

	public String sayHi(String name) {
		System.out.println("sayHi....");
		return "hi " + name;
	}

}

            
在地址欄訪問:

Java項目代碼調用服務:

使用純Java項目調用

一、根據客戶端生成的代碼來調用。(優選這種方式)請先生成而後在任意的Java項目中調用 。

二、客戶端只擁有一個接口,使用JaxWsProxyFactoryBean來調用。

由於如下使用了JaxWsProxyFactoryBean,因此,仍然須要CXF的環境,而使用此環境就會形成Jar文件的大量冗餘,因此你們要謹慎選擇(一下的地址是隨便貼的)。

在Spring項目中,經過配置文件調用:

如下是使用Spring的配置文件調用:

新創建一個Java項目,並加載cxf的全部包。

只須要生成的接口文件.

在classpath下新創建一個ClientBeans.xml文件.

優勢與缺點:

        此種狀況,適合於一個Javaweb項目已經集成了Spring。並但願經過CXF配置的方式調用Web服務。

        此種狀況,仍然須要導入CXF的大量jar包。

        這種狀況也存在必定優勢,如能夠將外部的Web服務經過配置文件注入(DI)到Action類中。


結構圖以下(帶接口的方式):


ClientBeans.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:soap="http://cxf.apache.org/bindings/soap"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans.xsd
						http://cxf.apache.org/bindings/soap 
						http://cxf.apache.org/schemas/configuration/soap.xsd
						http://cxf.apache.org/jaxws 
						http://cxf.apache.org/schemas/jaxws.xsd">
		<!-- 配置客戶端bean -->
		<!-- 
			id:惟一標識
			address:請求的服務地址
			serviceClass:客戶端接口
		 -->
		<jaxws:client id="hiService" address="http://localhost:8090/CXF03/cxf/hi" serviceClass="kaiyi.IHiService"></jaxws:client>
		
</beans>


如下是調用代碼:

package test;

import kaiyi.IHiService;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("ClientBeans.xml");
		IHiService ihi = (IHiService) ctx.getBean("hiService");
		ihi.sayHi("abc");
		System.out.println(ihi.getClass().getName());
	}
}


經過JS來調用WebService:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>使用jquery的ajax調用Web服務 </title>
    <script type="text/javascript" src="js/jquery-1.6.2.js"></script>
    <script type="text/javascript">
    	$(function(){
    		$("#but1").click(function(){
    			//指定訪問服務的地址
    			var wsUrl = "http://localhost:8090/CXF03/cxf/hi";
    			//構造請求體
    			var soap = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHi xmlns:ns2="http://kaiyi/"><arg0>abc</arg0></ns2:sayHi></soap:Body></soap:Envelope>';
    			$.ajax({
						url:wsUrl,
						type:'post',
						dataType:'xml',
						contentType:'text/xml;charset=UTF-8',
						data:soap,
						success:function(data){
							alert('OK!');
							var o = $(data);
							alert(o.find('return').eq(0).text());
						},
						error:function(){
							alert('error!');
						}
						});
    		});
    	});
    </script>
  </head>
  
  <body>
    <input type="button" value="發送jquery的ajax請求" id="but1">
  </body>
</html>

POJO類:

package pojo;



import java.io.Serializable;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "person")
public class Person implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String id;
	private String name;
	private String desc;
	
	@XmlElement(name = "id")
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	@XmlElement(name = "name")
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@XmlElement(name = "desc")
	public String getDesc() {
		return desc;
	}
	public void setDesc(String desc) {
		this.desc = desc;
	}
	@Override
	public String toString() {
		return "Person [desc=" + desc + ", id=" + id + ", name=" + name + "]";
	}
	
	
}

如今通常來講用URL的方式調用restful服務比較流行:


它與WSDL方式徹底不一樣,採用的是一種新型的方式,企業開發使用較爲常見:

Available RESTful services:

Endpoint address: http://localhost:8090/CXF03/cxf/p
WADL : http://localhost:8090/CXF03/cxf/p?_wadl&type=xml

訪問後返回的是json或者XML數據

此種方式只須要在cxf-servlet.xml配置一下便可:

<!-- 配置restful方式的web服務 -->
	<bean id="ps" class="restful.PersonServiceImpl"></bean>
	<jaxrs:server id="personService" address="/p">
		<jaxrs:serviceBeans>
			<ref bean="ps"/>
		</jaxrs:serviceBeans>
		<jaxrs:inInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
		</jaxrs:inInterceptors>
		<jaxrs:outInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
		</jaxrs:outInterceptors>
	</jaxrs:server>


如下是訪問方式:

package test;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.junit.Test;

import pojo.Person;


// 使用URL的方式調用restful服務
public class UrlConnectionTest {
	

	@Test
	public void test1() throws Exception {
		String wsUrl = "http://localhost:8090/CXF03/cxf/p/persons/id0";
		URL url = new URL(wsUrl);
		
		URLConnection conn = url.openConnection();
		HttpURLConnection con = (HttpURLConnection)conn;
		
		con.setRequestMethod("GET");
		int code = con.getResponseCode();
		if(code == 200){
			InputStream in = con.getInputStream();
			byte[] b = new byte[1024];
			int len = 0;
			StringBuffer sb = new StringBuffer();
			while((len=in.read(b))!=-1){
				String s = new String(b,0,len,"UTF-8");
				sb.append(s);
			}
			String json = sb.toString();
			JSONObject o = JSONObject.fromObject(json);
			json = o.getString("person").toString();
			//將String轉換爲Person對象
			Person person = (Person) JSONObject.toBean(JSONObject.fromObject(json), Person.class);
			System.out.println("----"+person);
		}
		con.disconnect();
	}
	
	
	@Test
	public void test2() throws Exception {
		String wsUrl = "http://localhost:8090/CXF03/cxf/p/persons";
		URL url = new URL(wsUrl);
		
		URLConnection conn = url.openConnection();
		HttpURLConnection con = (HttpURLConnection)conn;
		
		con.setRequestMethod("GET");
		int code = con.getResponseCode();
		if(code == 200){
			InputStream in = con.getInputStream();
			byte[] b = new byte[1024];
			int len = 0;
			StringBuffer sb = new StringBuffer();
			while((len=in.read(b))!=-1){
				String s = new String(b,0,len,"UTF-8");
				sb.append(s);
			}
			String json = sb.toString();
			JSONObject o = JSONObject.fromObject(json);
			Object obj = o.get("person");
			json = obj.toString();
		
			List<Person> list = (List<Person>)JSONArray.toCollection(JSONArray.fromObject(json), Person.class);
			for(Person p:list){
				System.out.println(p);
			}
		}
		con.disconnect();
	}

}

咱們能夠根據被調用服務的接口上的註解來決定返回值的數據格式

//@Produces( { MediaType.APPLICATION_XML })

@Produces( { MediaType.APPLICATION_JSON })

public interface IPersonService extends Serializable 


如下是服務代碼:

package restful;

import java.io.Serializable;
import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import pojo.Person;


//@Produces( { MediaType.APPLICATION_XML })
@Produces( { MediaType.APPLICATION_JSON })
public interface IPersonService extends Serializable {
	
	@GET
	@Path(value="/persons/{id}")
	public Person findPersonById(
			@PathParam("id")
			String id);
	
	@GET
	@Path(value="/persons")
	public List<Person> findAllPerson();
}
package restful;



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

import pojo.Person;



public class PersonServiceImpl implements IPersonService {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static Map<String, Person> ps = new HashMap<String, Person>();
	static {
		for(int i=0;i<5;i++){
			Person p = new Person();
			p.setId("id" + i);
			p.setName("person" + i);
			p.setDesc("desc" + i);
			ps.put(p.getId(), p);
		}
	}
	public List<Person> findAllPerson() {
		return new ArrayList<Person>(ps.values());
	}
	public Person findPersonById(String id) {
		return ps.get(id);
	}
	

}


如下是調用代碼:

package test;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.junit.Test;

import pojo.Person;


// 使用URL的方式調用restful服務
public class UrlConnectionTest {
	

	@Test
	public void test1() throws Exception {
		String wsUrl = "http://localhost:8090/CXF03/cxf/p/persons/id0";
		URL url = new URL(wsUrl);
		
		URLConnection conn = url.openConnection();
		HttpURLConnection con = (HttpURLConnection)conn;
		
		con.setRequestMethod("GET");
		int code = con.getResponseCode();
		if(code == 200){
			InputStream in = con.getInputStream();
			byte[] b = new byte[1024];
			int len = 0;
			StringBuffer sb = new StringBuffer();
			while((len=in.read(b))!=-1){
				String s = new String(b,0,len,"UTF-8");
				sb.append(s);
			}
			String json = sb.toString();
			JSONObject o = JSONObject.fromObject(json);
			json = o.getString("person").toString();
			//將String轉換爲Person對象
			Person person = (Person) JSONObject.toBean(JSONObject.fromObject(json), Person.class);
			System.out.println("----"+person);
		}
		con.disconnect();
	}
	
	
	@Test
	public void test2() throws Exception {
		String wsUrl = "http://localhost:8090/CXF03/cxf/p/persons";
		URL url = new URL(wsUrl);
		
		URLConnection conn = url.openConnection();
		HttpURLConnection con = (HttpURLConnection)conn;
		
		con.setRequestMethod("GET");
		int code = con.getResponseCode();
		if(code == 200){
			InputStream in = con.getInputStream();
			byte[] b = new byte[1024];
			int len = 0;
			StringBuffer sb = new StringBuffer();
			while((len=in.read(b))!=-1){
				String s = new String(b,0,len,"UTF-8");
				sb.append(s);
			}
			String json = sb.toString();
			JSONObject o = JSONObject.fromObject(json);
			Object obj = o.get("person");
			json = obj.toString();
		
			List<Person> list = (List<Person>)JSONArray.toCollection(JSONArray.fromObject(json), Person.class);
			for(Person p:list){
				System.out.println(p);
			}
		}
		con.disconnect();
	}

}


這是調用http://localhost:8090/CXF03/cxf/p/persons 地址後被解析的數據

----Person [desc=desc0, id=id0, name=person0]

Person [desc=desc2, id=id2, name=person2]

Person [desc=desc1, id=id1, name=person1]

Person [desc=desc0, id=id0, name=person0]

Person [desc=desc4, id=id4, name=person4]

Person [desc=desc3, id=id3, name=person3]


目前的webservice的就到這!

相關文章
相關標籤/搜索