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類型的類型