三、发布WebService
由于本示例的WebService类使用了一个Java类(DataForm类),因此,在发布WebService之前,需要先将DataForm.class文件复制到<Tomcat安装目录>/webapps/axis2/WEB-INF/classes/data目录中,然后将ComplexTypeService.class文件复制到<Tomcat安装目录>/webapps/axis2/WEB-INF/pojo目录中,最后启动Tomcat(如果Tomcat已经启动,由于增加了一个DataForm类,因此,需要重新启动Tomcat)。
四、使用Java编写调用WebService的客户端代码
在客户端仍然使用了RPC的调用方式,代码如下:
import javax.xml.namespace.QName;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;
public class ComplexTypeRPCClient
{
public static void main(String[] args) throws Exception
{
RPCServiceClient serviceClient = new RPCServiceClient();
Options options = serviceClient.getOptions();
EndpointReference targetEPR = new EndpointReference(
" http://localhost:8080/axis2/services/ComplexTypeService " );
options.setTo(targetEPR);
// 下面的代码调用uploadImageWithByte方法上传图像文件
/
// 打开图像文件,确定图像文件的大小
java.io.File file = new java.io.File( " f://images.jpg " );
java.io.FileInputStream fis = new java.io.FileInputStream( " f://images.jpg " );
// 创建保存要上传的图像文件内容的字节数组
byte [] buffer = new byte [( int ) file.length()];
// 将图像文件的内容读取buffer数组中
int n = fis.read(buffer);
System.out.println( " 文件长度: " + file.length());
Object[] opAddEntryArgs = new Object[]{ buffer, n };
Class[] classes = new Class[]{ Boolean. class };
QName opAddEntry = new QName( " http://ws.apache.org/axis2 " , " uploadImageWithByte " );
fis.close();
// 开始上传图像文件,并输出uploadImageWithByte方法的返回传
System.out.println(serviceClient.invokeBlocking(opAddEntry,opAddEntryArgs, classes)[ 0 ]);
/
// 下面的代码调用了getArray方法,并返回一维String数组
/
opAddEntry = new QName( " http://ws.apache.org/axis2 " , " getArray " );
String[] strArray = (String[]) serviceClient.invokeBlocking(opAddEntry,
new Object[]{}, new Class[]{String[]. class })[ 0 ];
for (String s : strArray)
System.out.print(s + " " );
System.out.println();
/
// 下面的代码调用了getMDArray方法,并返回一维String数组
/
opAddEntry = new QName( " http://ws.apache.org/axis2 " , " getMDArray " );
strArray = (String[]) serviceClient.invokeBlocking(opAddEntry, new Object[]{},
new Class[]{String[]. class })[ 0 ];
for (String s : strArray)
{
String[] array = s.split( " , " );
for (String ss: array)
System.out.print( " < " + ss + " > " );
System.out.println();
}
System.out.println();
/
// 下面的代码调用了getDataForm方法,并返回DataForm对象实例
/
opAddEntry = new QName( " http://ws.apache.org/axis2 " , " getDataForm " );
data.DataForm df = (data.DataForm) serviceClient.invokeBlocking(opAddEntry, new Object[]{},
new Class[]{data.DataForm. class })[ 0 ];
System.out.println(df.getAge());
/
// 下面的代码调用了getDataFormBytes方法,并返回字节数组,最后将返回的字节数组反序列化后,转换成DataForm对象实例
/
opAddEntry = new QName( " http://ws.apache.org/axis2 " , " getDataFormBytes " );
buffer = ( byte []) serviceClient.invokeBlocking(opAddEntry, new Object[]{}, new Class[]{ byte []. class })[ 0 ];
java.io.ObjectInputStream ois = new java.io.ObjectInputStream(
new java.io.ByteArrayInputStream(buffer));
df = (data.DataForm) ois.readObject();
System.out.println(df.getName());
//
}
}
<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} @font-face {font-family:""@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ @page {} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} -->
运行上面的程序,将输出如下的内容:
true
自行车 飞机 火箭
< 自行车 > < 飞机 > < 火箭 >
< 中国 > < 美国 > < 德国 >
< 超人 > < 蜘蛛侠 > < 钢铁侠 >
20
bill
五、使用C#编写调用WebService的客户端代码
在Visual Studio中使用WebService就简单得多。假设引用WebService时的引用名为complexType,则下面的代码调用了uploadImageWithByte方法来上传图像文件。在Visual Studio引用WebService时,uploadImageWithByte方法多了两个out参数,在使用时要注意。
System.IO.FileStream fs = new System.IO.FileStream( @" f:/images.jpg " , System.IO.FileMode.Open);
byte [] buffer = new byte [fs.Length];
fs.Read(buffer, 0 , ( int )fs.Length);
bool r;
bool rs;
cts.uploadImageWithByte( buffer, ( int )fs.Length, true , out r, out rs);
在获得二维数组时,可以将数据加载到DataGridView或其他类似的控件中,代码如下:
for ( int i = 0 ; i < strArray.Length; i ++ )
{
// 用正则表达式将带分隔符的字符串转换成String数组
String[] columns = strArray[i].Split( ' , ' );
// 如果DataGridView的表头不存在,向DataGridView控件添加三个带表头的列
if (dataGridView1.Columns.Count == 0 )
for ( int j = 0 ; j < columns.Length; j ++ )
dataGridView1.Columns.Add( " column " + (j + 1 ).ToString(), " 列 " + (j + 1 ).ToString());
// 添加行
dataGridView1.Rows.Add( 1 );
for ( int j = 0 ; j < columns.Length; j ++ )
{
dataGridView1.Rows[i].Cells[j].Value = columns[j];
}
}
<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} @font-face {font-family:""@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ @page {} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} -->
向DataGridView控件添加数据后的效果如图1所示。
图1
<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} @font-face {font-family:""@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ @page {} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; layout-grid:15.6pt;} div.Section1 {page:Section1;} -->
对于其他的WebService方法的调用都非常简单,读者可以自己做这个实验。
要注意的是,由于.net和java序列化和反序列化的差异,通过序列化的方式传递对象实例只使用于客户端与服务端为同一种语言或技术的情况,如客户端和服务端都使用Java来编写。
如果读者要上传大文件,应尽量使用FTP的方式来传递,而只通过WebService方法来传递文件名等信息。这样有助于提高传输效率。