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 服务实现的Bean:MyServiceImpl
}
}
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();
}
}
}
这个类中的QName、Service 之后介绍
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.2、message:SOAP
3.1.3、portType:指明服务器的接口,并且通过operation绑定相应的in和out的消息:其中in表示参数,out表示返回值
3.1.4、binding:指定传递消息所使用的格式
3.1.5、service:指定服务所发布的名称
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类型的类型