Web Service 开发系列文章之一(开篇实例:代码优先的开发方式)

Web Service开篇

1、第一个实例

建立一个Java Web Service需要三个步骤:1、创建接口;2、创建实现类;3、开启服务

 

1.1、创建接口 IMyService

    在Eclipse中新建一个Java Project,添加一个包org.decarl.service

 

在包中添加接口IMyService

在接口上添加Annotation @WebService,在接口里定义两个方法

 

package org.decarl.service;

 

import javax.jws.WebService;

 

@WebService

public interface IMyservice {

    public int add (int a, int b);

    public int minus (int a, int b);

}

 

1.2 创建实现类 MyServiceImpl

重点注意在类定义上面加上Annotation

 

@WebService(endpointInterface = "org.decarl.service.IMyservice")

 

其中endpointInterface指的是对外提供服务的接口

 

 

代码实现如下:

 

 

package org.decarl.service;

 

import javax.jws.WebService;

 

@WebService(endpointInterface = "org.decarl.service.IMyservice")

public class MyServiceImpl implements IMyservice {

 

    @Override

    public int add(int a, int b) {

        System.out.println(a + "+" + b + "=" + (a + b) );

        return a + b;

    }

 

    @Override

    public int minus(int a, int b) {

        System.out.println(a + "-" + b + "=" + (a - b) );

        return a - b;

    }

}

 

 

1.3 创建服务(开启服务)

核心是 Endpoint.publish函数

 

代码如下:

 

package org.decarl.service;

import javax.xml.ws.Endpoint;

public class MyService {

    public static void main(String[] args) {

        String address = "http://localhost:8888/ns";

        

        //第二个参数:要发布这个接口的哪一个实现类

        Endpoint.publish(address, new MyServiceImpl());

        

        //SEI Service Endpoint Interface 服务提供的接口:IMyService

        //SIB Service Implements Bean 服务实现的BeanMyServiceImpl

    }

}

1.4、建立一个TestClient进行测试

package org.decarl.service;

 

import java.net.MalformedURLException;

import java.net.URL;

import javax.xml.namespace.QName;

import javax.xml.ws.Service;

 

public class TestClient {

    public static void main(String[] args) {    

        try {

            //创建访问wsdl服务地址的URL

            URL url = new URL("http://localhost:8888/ns?wsdl");

            //通过QName指明服务的具体信息

            QName sName = new QName("http://service.decarl.org/", "MyServiceImplService");

            //创建服务

            Service service = Service.create(url, sName);

            //实现接口

            IMyservice ms = service.getPort(IMyservice.class);

            System.out.println(ms.add(12, 13));

            

            //以上服务有问题,依然依赖于IMyservice接口

            

        } catch (MalformedURLException e) {

            e.printStackTrace();

        }    

    }

}

这个类中的QNameService 之后介绍

 

1.5、启动测试

1.5.1 、启动MyService类(启动服务)

 

右键->Run as->Java Application

 

 

控制台输出如下:

 

 

 

之后在浏览器中输入地址:http://localhost:8888/ns?wsdl

页面显示如下:

 

 

其中TestClient类中的QName构造方法的参数对应着上图中红框中的tagetNameSpace和name

 

QName sName = new QName("http://service.decarl.org/", "MyServiceImplService");

 

 

1.5.2、调用这个服务

在TestClient类中右键->Run as->Java Application

 

控制台输出如下:

 

 

但是此时还是依赖IMyservice, 服务的调用是通过WSDL即可完成

WSDL可能是Java或者.NET开发生成的

 

 

2、第一个实例改进

2.1、wsimport 命令 (通过WSDL生成本地的服务class文件)

wsimport -d D:/wsimport/ -keep -verbose http://localhost:8888/ns?wsdl

wsimport -d D:/wsimport -keep -verbose http://localhost:8888/ns?wsdl

wsimport -d D:\wsimport -keep -verbose http://localhost:8888/ns?wsdl

 

注意:如果被指定的目录D: /wsimport 在D盘,则应该先将命令提示符切换到D盘再执行上述命令

 

-keep参数会在生成class文件的同时也生成java文件

-verbose 生成详细信息

 

2.2、新建一个项目来测试生成的class

2.2.1、新建一个Java 项目,将刚刚生成的包拷贝到源代码的目录

 

复制org,然后在src文件夹上右键粘贴

 

 

 

2.2.2、将原来的TestClient直接复制到这个项目中就可以直接运行了

 

2.2.3、创建另一种访问方式

 

新建一个类 TestClient2

 

代码如下:

package org.decarl.service;

 

public class TestClient2 {

 

    public static void main(String[] args) {

        //MyServiceImplService通过WSDL生成的用于做访问的类

        MyServiceImplService msis = new MyServiceImplService();

        IMyservice ms = msis.getMyServiceImplPort();

        System.out.println(ms.minus(29, 11));

    }

}

 

其中MyServiceImplService这个类是wsimport生成的用于提供服务接口访问的类

 

 

2.3、wsimport命令的其他参数

-p 指定包名 不加-keep (-keep生成java文件)

wsimport -d D:/wsimport/ -p test -verbose http://localhost:8888/ns?wsdl

 

 

-d 指定生成的目录

-keep 指定是否生成.java源文件

-verbose 显示生成的详细过程及信息

http://localhost:8888/ns?wsdl 网络中的WSDL文件

 

 

 

3、WSDL分析

3.1、WSDL五大部分

3.1.1 types:用来定义访问的类型

3.1.2message:SOAP

3.1.3portType:指明服务器的接口,并且通过operation绑定相应的inout的消息:其中in表示参数,out表示返回值

3.1.4binding:指定传递消息所使用的格式

3.1.5service:指定服务所发布的名称

 

 

 

4、使用系统提供的丰富的Annotation

 

修改第一个项目中IMyService

 

package org.decarl.service;

 

import javax.jws.WebParam;

import javax.jws.WebResult;

import javax.jws.WebService;

 

@WebService

public interface IMyservice {

      

    

    @WebResult(name = "addResult")

    public int add (@WebParam(name="a")int a, @WebParam(name="b")int b);

    

    @WebResult(name = "minusResult")

    public int minus (@WebParam(name="a")int a, @WebParam(name="b")int b);

}

 

 

 

于是对应生成的WSDL type会相应的改变

 

 

打了红框的部分已经随着Annotation改变了

 

原来的代码和WSDL,注意打红框的部分

package org.decarl.service;

import javax.jws.WebParam;

import javax.jws.WebResult;

import javax.jws.WebService;

 

@WebService

public interface IMyservice {

    public int add (int a, int b);

    public int minus (int a, int b);

}

 

再加一个比较明显的例子

package org.decarl.service;

import javax.jws.WebParam;

import javax.jws.WebResult;

import javax.jws.WebService;

 

@WebService

public interface IMyservice {

    

    @WebResult(name = "addResult111111111111")

    public int add (@WebParam(name="a111111111111")int a,

             @WebParam(name="b111111111111")int b);

    

    @WebResult(name = "minusResult222222222222")

    public int minus (@WebParam(name="a222222222222")int a,

             @WebParam(name="b222222222222")int b);

}

 

 

 

5、传递类类型的数据(传递对象数据)

5.1 在第一项目中添加一个User类(实体类)

 

package org.decarl.service;

 

public class User {

    private int id;

    private String username;

    private String password;

    public int getId() {

        return id;

    }

    public void setId(int id) {

        this.id = id;

    }

    public String getUsername() {

        return username;

    }

    public void setUsername(String username) {

        this.username = username;

    }

    public String getPassword() {

        return password;

    }

    public void setPassword(String password) {

        this.password = password;

    }

}

 

5.2、在IMyservice接口中添加一个和User有关的方法Login

 

package org.decarl.service;

 

import javax.jws.WebParam;

import javax.jws.WebResult;

import javax.jws.WebService;

 

@WebService

public interface IMyservice {

      

    

    @WebResult(name = "addResult")

    public int add (@WebParam(name="a")int a,

             @WebParam(name="b")int b);

    

    @WebResult(name = "minusResult")

    public int minus (@WebParam(name="a")int a,

             @WebParam(name="b")int b);

    

    @WebResult(name = "loginUser")

    public User login(@WebParam(name = "username")String username,

             @WebParam(name = "password")String password);

    

}

 

5.3、在实现类MyServiceImpl中添加login方法的实现

package org.decarl.service;

 

import javax.jws.WebService;

 

@WebService(endpointInterface = "org.decarl.service.IMyservice")

public class MyServiceImpl implements IMyservice {

 

    @Override

    public int add(int a, int b) {

        System.out.println(a + "+" + b + "=" + (a + b) );

        return a + b;

    }

 

    @Override

    public int minus(int a, int b) {

        System.out.println(a + "-" + b + "=" + (a - b) );

        return a - b;

    }

 

    @Override

    public User login(String username, String password) {

        System.out.println(username + "is logining");

        User user = new User();

        user.setId(1);

        user.setUsername(username);

        user.setPassword(password);

        return user;

    }

}

 

下面来看WSDL是怎么生成对象的

 

 

 

上面红框中的文字:

loginResponse类型在下面定义(沿着蓝色箭头),而loginResponse中又定义了user类型;user类型是一个包含了一个xs:int类型和两个xs:string类型的类型

 

posted on 2012-05-15 19:15  decarl  阅读(10914)  评论(2编辑  收藏  举报