学习WEB SERVICE一例 (2006-7-12)
一.环境
本例环境:winxp home,oracle 9i,axis1.3,tomcat4.1,开发环境eclipse3.01.
顺便说一下如何发布axis:将下载的axis-bin-1.3包中的axis目录(里面有WEB-INF目录)COPY到%tomcat4.1%\webapps\下即可.
二.示例说明
1.目的: 验证一下WEB SERVICE中,如何返回JavaBean.
2.服务说明: 查询人员信息,每个人员有这样几个字段:id,name(姓名),age(年龄),birthday(生日),salary(工资),phones(多个电话,以数组实现).
3.服务名称: getPersonList(),返回一个Person的数组. (该方法是类DBQueryService中的一个方法)
4.JAVA类: DBQueryService(设计本例最初是从数据库表中取数据,故以DB开头),提供WEB SERVICE服务的类
Person:JavaBean.包含返回的数据.
三.示例开发过程
1.编写Person JavaBean源代码如下:
package demo1;
import java.util.*;
public class Person {
private int id;
private String name;
private int age;
private Date date;
private double salary;
private String[] phones;
public Person(){}
///setter method
public void setId(int id){
this.id=id;
}
public void setName(String name){
this.name=name;
}
public void setAge(int age){
this.age=age;
}
public void setDate(Date date){
this.date=date;
}
public void setSalary(double salary){
this.salary=salary;
}
public void setPhones(String[] phones){
this.phones=phones;
}
////getter method
public int getId(){
return id;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public Date getDate(){
return date;
}
public double getSalary(){
return salary;
}
public String[] getPhones(){
return phones;
}
}
2.编写DBQueryService,源代码如下:
package demo1;
import java.sql.*;
import java.util.Date;
public class DBQueryService {
public Person[] getPersonList(){
Person[] persons=null;
try{
String driverName = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@127.0.0.1:1521:oradb";
Class.forName(driverName);
Connection conn = DriverManager.getConnection(url,"wlz","wlz");
Statement stmt1 = conn.createStatement();
ResultSet rscount = stmt1.executeQuery("select count(id) from ws_demo");
//取得行数,以动态建立数组
rscount.next();
int rowNums=rscount.getInt(1);
if(rowNums>0){
persons=new Person[rowNums];
}else{
return persons; //返回空值
}
//取出结果集
Statement stmt2=conn.createStatement();
ResultSet rs=stmt2.executeQuery("select * from ws_demo order by id");
for(int i=0;i<rowNums;i++){
if(rs.next()){
Person person=new Person();
person.setId(rs.getInt("id"));
person.setName(rs.getString("name"));
person.setAge(rs.getInt("age"));
person.setDate(rs.getDate("birthday"));
person.setSalary(rs.getDouble("salary"));
String[] phones=new String[]{rs.getString("phone"),rs.getString("mobile")};
person.setPhones(phones);
persons[i]=person;
}
}
stmt1.close();
stmt2.close();
rscount.close();
rs.close();
conn.close(); //正常来说,conn.close()应放在finally里面
}catch(Exception e){
System.out.println("---------------------------------");
System.out.println(e.getMessage());
e.printStackTrace();
System.out.println("---------------------------------");
}
/*
//如果不想用数据库,使用下面代码,将上面try{}catch{}间的代码注释掉,从学习的效果来说,是一样的。
persons=new Person[2]; //暂且用两个练练手
Person p0=new Person();
p0.setId(1);
p0.setName("张三丰");
p0.setAge(100);
p0.setDate(new Date()); //暂时用当天
p0.setSalary(1055.62);
String[] phone0=new String[]{"0XX-2391XXXX","13X00000001"};
p0.setPhones(phone0);
persons[0]=p0;
Person p1 =new Person();
p1.setId(2);
p1.setName("张无忌");
p1.setAge(30);
p1.setDate(new Date()); //暂时用当天
p1.setSalary(1578.94);
String[] phone1=new String[]{"0XX-2391XXXX"};
p1.setPhones(phone1);
persons[1]=p1;
*/
return persons;
}
//main仅用于测试是否能从数据库返回数据,变成服务时,可将其删除
public static void main(String[] args){
DBQueryService service=new DBQueryService();
Person[] p=service.getPersonList();
System.out.println(" the query result is: \n-----------------------------------------------------------------------------------------");
System.out.println("id\tname\tage\tbirthday\t\t\tsalary\tphones");
System.out.println("-----------------------------------------------------------------------------------------");
String[] phones;
for(int i=0;i<p.length;i++){
Person person=p[i];
phones=person.getPhones();
String s=person.getId()+"\t"+person.getName()+"\t"+person.getAge()+"\t"+person.getDate()+"\t"+person.getSalary()+"\t";
for(int j=0;j<phones.length;j++){
if(phones[j]!=null){
s+=phones[j]+"\t";
}
}
System.out.println(s);
}
System.out.println("-----------------------------------------------------------------------------------------");
}
}
3.数据库建表语句(ORACLE 9i,各位看官可将其改成其他数据库)
create table ws_demo(
id int,
name varchar2(20),
age smallint,
birthday date,
salary number(10,2),
phone varchar2(20),
mobile varchar2(20),
primary key (id)
)
至于数据,就得你自己来添加了.
4.发布服务
1),将编译好的两个类(怎么编译?不用我说了吧.值得注意的一点就是类路径要包含axis的几个jar文件),COPY到%tomcat4.1%\webapps\axis\WEB-INF\classes\demo1里(demo1是两个类的包名)
2).将下面的XML代码COPY进%tomcat4.1%\webapps\axis\WEB-INF里的server-config.wsdd.(这个文件从哪来,是执行org.apache.axis.client.AdminClient得来的,具体可参考别人资料.)
<service name="DBQueryService" provider="java:RPC">
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="demo1.DBQueryService"/>
<beanMapping languageSpecificType="java:demo1.Person" qname="ns:Person" xmlns:ns="urn:DBQueryService"/>
</service>
至此,发布完毕.让我们看一下,启动tomcat4.1,在IE中打入地址 http://localhost:8080/axis/services/DBQueryService?wsdl,
如果IE显示一堆XML,说明发布成功.
5.客户端调用
本例采用DII方式调用(根据试验,将DII代码放在JSP中也可运行),源代码:
package demo1;
import org.apache.axis.client.Service;
import org.apache.axis.client.Call;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import javax.xml.namespace.QName;
import java.net.URL;
import java.text.SimpleDateFormat;
public class DemoClient {
public static void main(String[] args) throws Exception {
String endPoint="http://localhost:8080/axis/services/DBQueryService";
Service service=new Service();
Call call=(Call)service.createCall();
call.setTargetEndpointAddress(new URL(endPoint));
QName qn=new QName("urn:DBQueryService","DBQueryService");
call.registerTypeMapping(Person.class,qn,
new BeanSerializerFactory(Person.class,qn),
new BeanDeserializerFactory(Person.class,qn));
call.setOperationName(new QName("urn:DBQueryService","getPersonList"));
call.setReturnType(qn,Person[].class); //灵机一动想出来的。
Person[] persons=(Person[])call.invoke(new Object[]{});
if(persons==null) System.out.println("abc");
printData(persons);
}
public static void printData(Person[] persons){
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
if(persons==null){
System.out.println("the result is null.");
return;
}
System.out.println("the query result is: \n-----------------------------------------------------------------------------------------");
System.out.println("id\tname\tage\tbirthday\tsalary\tphones");
System.out.println("-----------------------------------------------------------------------------------------");
String[] phones;
for(int i=0;i<persons.length;i++){
Person person=persons[i];
phones=person.getPhones();
String s=person.getId()+"\t"+person.getName()+"\t"+person.getAge()+"\t"+sdf.format(person.getDate())+"\t"+person.getSalary()+"\t";
for(int j=0;j<phones.length;j++){
if(phones[j]!=null){
s+=phones[j]+"\t";
}
}
System.out.println(s);
}
System.out.println("-----------------------------------------------------------------------------------------");
}
}
四.点评
本例有选择的使用int,String,double,String[]等JAVA数据,及一个JavaBean(Person)数组,来验证WEB SERVICE与JAVA中的数据传递(其实你也看到,这种转换是自动进行的),
在编程当中值得注意的是:
1.遵守JavaBean规范,要有一个默认构造函数,每个属性要有对应的setter和getter方法.
2.JavaBean可实现嵌套,如Person中可以再定义一个Address类的JavaBean.
3.本例中未涉及自定义序列化和反序列化.
五.本示例效果:(采用不连接数据库的代码)
the query result is:
-----------------------------------------------------------------------------------------
id name age birthday salary phones
-----------------------------------------------------------------------------------------
1 张三丰 100 2006-07-13 1055.62 0XX-2391XXXX 13X00000001
2 张无忌 30 2006-07-13 1578.94 0XX-2391XXXX
-----------------------------------------------------------------------------------------