一、概覽
方式1:
HttpClient:可以用來調用webservie服務,也可以抓取網頁數據
版本1:HttpClient3.0.x
版本2:HttpClient4.x.x(目前最新4.5.2)
這2個版本的使用方式不一樣;變動較大
方式2:純java(自帶API) jws
方式3:cxf框架
方式4:axis2框架
準備工作:
1.瞭解wsimport java自帶的一個命令(建議使用jdk7,穩定支持)
作用:將wsdl文件生成本地代理(java代碼),方便調用
語法 wsimport [opations] <wsdl_uri>
- wsdl_uri:wsdl 的統一資源標識符
- d :指定要輸出的文件的位置
- s :表示要解析java的源碼 ,默認解析出的是class字節碼
- p : 指定輸出的包名
1. 獲取服務路徑:比如
http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL
2. 獲取wsdl文件.建議使用JDK1.6以上的版本的wsimport命令
進入dos的桌面:
方式1:wsimport http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL
這種默認只會生成class,且會生成默認的包
方式2:生成源碼,指定包和路徑
wsimport -s ./ -p cn.aa http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL
3.可以把class文件打成jar包 jar cvf test.jar 打包目錄
4.放在你的項目中進行調用:
- public static void main(String[] args) {
- MobileCodeWS mobileCodeWs=new MobileCodeWS();
- MobileCodeWSSoap mobileCodeWSSoap=mobileCodeWs.getMobileCodeWSSoap();
- String tel=mobileCodeWSSoap.getMobileCodeInfo("183735xxxx",null);
- System.out.println(tel);
- }
2.規範瞭解
JAVA 中共有三種WebService 規範,分別是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。
1. Jaxws(掌握)
JAX-WS 的全稱爲 Java API for XML-Based Webservices ,早期的基於SOAP 的JAVA 的Web 服務規範JAX-RPC(Java API For XML-RemoteProcedure Call)目前已經被JAX-WS 規範取代。從java5開始支持JAX-WS2.0版本,Jdk1.6.0_13以後的版本支持2.1版本,jdk1.7支持2.2版本。
Jaxws開發的webservice傳輸soap協議。
2JAXM&SAAJ(瞭解)
JAXM(JAVA API For XML Message)主要定義了包含了發送和接收消息所需的API,SAAJ(SOAP With Attachment APIFor Java,JSR 67)是與JAXM 搭配使用的API,爲構建SOAP 包和解析SOAP 包提供了重要的支持,支持附件傳輸等,JAXM&SAAJ 與JAX-WS 都是基於SOAP 的Web 服務,相比之下JAXM&SAAJ 暴漏了SOAP更多的底層細節,編碼比較麻煩,而JAX-WS 更加抽象,隱藏了更多的細節,更加面向對象,實現起來你基本上不需要關心SOAP 的任何細節
3. JAX-RS(掌握)
JAX-RS 是JAVA 針對REST(Representation State Transfer)風格制定的一套Web 服務規範,由於推出的較晚,該規範(JSR 311,目前JAX-RS 的版本爲1.0)並未隨JDK1.6 一起發行。
Rest定義可以自行搜索
jax-RS可以發佈 rest風格webservice,因爲rest的webservice不採用soap傳輸,直接採用http傳輸,可以返回xml或json,比較輕量。
以後可能會流行Rest風格的
二、簡單例子
1.httpClient3.x.x
此方式不需要wsimport命令
- // 通過Http-Client 框架來模擬實現 Http請求--get
- public static String getMobileCodeInfo1(String mobileCode, String userID)
- throws HttpException, IOException {
- HttpClient client = new HttpClient();
- GetMethod getMethod=new GetMethod("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo?mobileCode="
- + mobileCode + "&userID=" + userID);
-
- //執行,得到消息碼
- int code = client.executeMethod(getMethod);
- System.out.println("消息碼:"+code);
- String result="";
- if (code==HttpURLConnection.HTTP_OK) {
- //得到執行結果
- result = getMethod.getResponseBodyAsString();
- System.out.println(result);
- }
-
- return result;
- }
-
-
- // 通過Http-Client 框架來模擬實現 Http請求--post
- // 需要導入3個jar包,本demo的jar包版本是3.1.0
- // 目前最新的是4.5.2,使用方式也發生了變化
- public static String getMobileCodeInfo2(String mobileCode, String userID)
- throws HttpException, IOException {
-
- // 輸入服務網址
- HttpClient client = new HttpClient();
- // GetMethod
- PostMethod post = new PostMethod(
- "http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo");
- // 設置參數
- post.setParameter("mobileCode", mobileCode);
- post.setParameter("userID", userID);
- // client.setTimeout(newTimeoutInMilliseconds);
-
- // 執行,返回一個結果碼
- int code = client.executeMethod(post);
-
- System.out.println("結果碼:" + code);
- // 獲取xml結果
- String result = post.getResponseBodyAsString();
- System.out.println("結果:" + result);
- //釋放連接
- post.releaseConnection();
- return result;
- }
-
- // Post請求 :通過Http-Client 框架來模擬實現 Http請求
- //從xml中獲取請求參數
- //SOAP1.1方式
- //問題:soap怎麼定義,這裏已經返回接結果,但是沒有手機號信息,也就返回的結果匹配,不知道爲什麼
- //估計是配置文件有問題
-
-
- //soap1.1
- @Test
- public void soap() throws Exception{
-
- HttpClient client=new HttpClient();
- PostMethod postMethod=new PostMethod("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx");
- //3.設置請求參數
- postMethod.setRequestBody(new FileInputStream("D:/soap.xml")); //文件名自定義
- //修改請求的頭部
- postMethod.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
- //4.執行請求 ,結果碼
- int code=client.executeMethod(postMethod);
- System.out.println("結果碼:"+code);
- //5. 獲取結果
- String result=postMethod.getResponseBodyAsString();
- System.out.println("Post請求的結果:"+result);
- }
-
- public static void main(String[] args) throws IOException {
- // getMobileInfo("13476699xxx", "");
- getMobileCodeInfo1("13476699xxx", "");//
- // getMobileCodeInfo2("13476699xxx", "");//
- //soap,利用xml傳輸參數
- }
其中:請求參數封裝在soap.xml中
請求規範服務方會提供給你的
soap.xml請求內容如下:
- <?xml version="1.0" encoding="utf-8"?>
- <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <getMobileCodeInfo xmlns="http://WebXml.com.cn/">
- <mobileCode>1347669xxxx</mobileCode>
- <userID></userID>
- </getMobileCodeInfo>
- </soap:Body>
- </soap:Envelope>
httpClient4.x.x不做演示,感興趣的可以去查查,資料很多
2.java自帶API實現
2.1 類發佈
2.1.1 使用默認設置
- @WebService
- //默認服務名會加上Service
- public class PhoneInfoWS {
- //默認方法名getPhoneInfo
- //默認參數名arg0
- //默認返回值名字:return
- //targetNamespace默認情況下爲倒置的包名
- public Phone getPhoneInfo(String OSName) {
- Phone p=new Phone();
- if ("Android".equalsIgnoreCase(OSName)) {
- p.setOS(OSName);
- p.setOwn("Google");
- p.setScale(80);
- }else if("IOS".equalsIgnoreCase(OSName)){
- p.setOS(OSName);
- p.setOwn("Apple");
- p.setScale(14);
- }else if("windows Phone".equalsIgnoreCase(OSName)){
- p.setOS(OSName);
- p.setOwn("Microsoft");
- p.setScale(4);
- }else{
- p.setOS("others");
- p.setOwn("others");
- p.setScale(2);
- }
- return p;
- }
-
-
- //靜態,非public方法不會被自動發佈
- public static String say(String city){
- return "hello"+city;
- }
-
- //訪問時自動生成一個描述文件xml+xsd約束文件
- public static void main(String[] args) {
- //implementor要發佈的對象,一般是接口的實現類
- String address1="http://127.0.0.1/PhoneInfoWS1?WSDL";
- // String address2="http://127.0.0.1/PhoneInfoWS2?WSDL";
- Endpoint point = Endpoint.publish(address1, new PhoneInfoWS());
- Endpoint.publish(address1, new PhoneInfoWS());
- // Endpoint.publish(address2, new PhoneInfoWS());
-
- //關閉發佈
- // point.stop();
-
-
- }
- }
2.1.2自定義設置
- @WebService(serviceName="PhoneInfoService",targetNamespace="http://PhoneService.web.com/")
- //默認服務名會加上Service
- public class PhoneInfoWS1 {
- @WebMethod(operationName="getPhoneInfo")
- public @WebResult(name="phone") Phone getPhoneInfo(@WebParam(name="OSName") String OSName) {
- Phone p=new Phone();
- if ("Android".equalsIgnoreCase(OSName)) {
- p.setOS(OSName);
- p.setOwn("Google");
- p.setScale(80);
- }else if("IOS".equalsIgnoreCase(OSName)){
- p.setOS(OSName);
- p.setOwn("Apple");
- p.setScale(14);
- }else if("windows Phone".equalsIgnoreCase(OSName)){
- p.setOS(OSName);
- p.setOwn("Microsoft");
- p.setScale(4);
- }else{
- p.setOS("others");
- p.setOwn("others");
- p.setScale(2);
- }
- return p;
- }
-
-
- //靜態,非public方法不會被自動發佈
- public static String say(String city){
- return "hello"+city;
- }
-
- //屏蔽要發佈的方法
- @WebMethod(exclude=true)
- public String say1(String city){
- return "hello"+city;
- }
- public String say2(String city){
- return "hello"+city;
- }
-
-
- //訪問時自動生成一個描述文件xml+xsd約束文件
- public static void main(String[] args) {
- //implementor要發佈的對象,一般是接口的實現類
- String address1="http://127.0.0.1/PhoneInfoWS1?WSDL";
- // String address2="http://127.0.0.1/PhoneInfoWS2?WSDL";
- Endpoint point = Endpoint.publish(address1, new PhoneInfoWS1());
- point.toString();
- Endpoint.publish(address1, new PhoneInfoWS1());
- // Endpoint.publish(address2, new PhoneInfoWS1());
-
- //關閉發佈
- // point.stop();
-
-
- }
- }
注意:
1. 在類上添加@WebService註解,代表發佈一個WebService服務
2. 通過EndPoint(端點服務)發佈一個webService。Endpoint也是jdk提供的一個專門用於發佈服務的類,它的publish方法接收兩個參數,
一個是本地的服務地址,二是提供服務的類。它位於javax.xml.ws.*包中。
3. Endpoint.publish(String address, Object implementor) 靜態方法在給定地址處針對指定的實現者對象創建併發布端點
4. 默認public修飾的方法自動發佈,靜態方法不會公佈
5. 如果希望某個方法不對外公開,可以在方法上添加@WebMethod(exclude=true),阻止對外公開。
6. 如果一個類上,被添加了@WebService註解,則必須此類至少有一個可以公開的方法,否則將會啓動失敗。
7.異常處理:
報錯:
com.sun.xml.internal.ws.model.RuntimeModelerException: runtime modeler error: Wrapper class com.web.PhoneService.jaxws.GetPhoneInfo is not found.
Have you run APT to generate them?
解決辦法:jdk7就可以了
8.測試方法:
a.利用上面說的wsimport生成本地代理,然後調用裏面的代碼進行測試就可以了,這裏就省略了
b.更方便的測試是使用Eclipse的Web Services Explorer 或者Myeclipse的SOAP Web Services Explorer進行測試
把鏈接:比如 http://127.0.0.1/PhoneInfoWS1?WSDL 放入到瀏覽器的WSDL地址欄就可以了
2.2接口發佈
- @WebService
- public interface JobService {
- public String getJobInfo();
- }
-
- /*
- * 默認只會發佈接口的方法,實現類自定義的方法不會被髮布了
- * 接口和實現類都需要加註解修飾
- *
- * 聯想Spring的注入只需在實現類加入註解即可
- */
- @WebService(serviceName="JobServiceImplService",
- endpointInterface="com.web.InterfaceService.JobService")
- public class JobServiceImpl implements JobService{
-
- @Override
- public String getJobInfo() {
- // TODO Auto-generated method stub
- return "java開發|前端開發|數據庫開發";
- }
-
- // 實現類自定義的方法不會被髮布
- public String say(String name){
- return "hello "+name;
- }
-
-
- public static void main(String[] args) {
- String address="http://127.0.0.1/JobServiceImpl?WSDL";
- Endpoint.publish(address, new JobServiceImpl());
- System.out.println(address);
- }
-
- }
3.CXF框架
Apache CXF 是一個開源的 Services 框架,是XFire和Celtix項目的結合產品,CXF 幫助您來構建和開發 Services 這些 Services 可以支持多種協議,比如:SOAP、POST/HTTP、RESTful HTTP CXF 大大簡化了 Service可以天然地和 Spring 進行無縫集成。
3.1最簡單的接口發佈
這裏先不與Spring集成,需要的jar包
asm-3.3.jar
commons-logging-1.1.1.jar
cxf-2.4.2.jar
jetty-continuation-7.4.5.v20110725.jar
jetty-http-7.4.5.v20110725.jar
jetty-io-7.4.5.v20110725.jar
jetty-security-7.4.5.v20110725.jar
jetty-server-7.4.5.v20110725.jar
jetty-util-7.4.5.v20110725.jar
neethi-3.0.1.jar
wsdl4j-1.6.2.jar
xmlschema-core-2.0.jar
這裏用的是2.4.2的,老版本,不要介意,最新版本3.1.6,可以自行下載
3.2 結合Spring發佈服務
這裏重點是如何配置發佈服務,業務邏輯僅僅是演示(輔助),不必參考
要發佈的服務:保存和根據姓名查詢員工
saveEmployee findEmployeeByName
步驟:
3.2.1.導包cxf2.7.18裏面的所有jar包 ,其中jetty包不需要,因爲應用是部署在tomcat裏面
3.2. 2.建實體類,DB類(模擬)
- public class Employee {
- private String name;
- private Integer age;
-
- @DateTimeFormat(pattern="yyyy-MM-dd")
- private Date birthday;
-
- public Employee() {
- super();
- }
-
- public Employee(String name, Integer age, Date birthday) {
- super();
- this.name = name;
- this.age = age;
- this.birthday = birthday;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Integer getAge() {
- return age;
- }
-
- public void setAge(Integer age) {
- this.age = age;
- }
-
- public Date getBirthday() {
- return birthday;
- }
-
- public void setBirthday(Date birthday) {
- this.birthday = birthday;
- }
-
- @Override
- public String toString() {
- return "Employee [name=" + name + ", age=" + age + ", birthday="
- + birthday + "]";
- }
-
- }
- //運行時如果報錯Unsupported major.minor version 51.0
- //這說明jdk版本不對,即tomcat的jdk版本跟項目版本不一致
- @Repository
- public class EmployeeDB {
- public EmployeeDB(){}
- private static List<Employee> list=new ArrayList<Employee>();
-
- static{
- list.add(new Employee("小米", 12, new Date()));
- }
-
- public void save(Employee employee){
- list.add(employee);
- }
-
- public Employee findByName(String name){
-
- if (list.size()>0) {
- for(Employee e:list){
- if (e.getName().equals(name)) {
- return e;
- }
- }
- }
- return null;
- }
-
- public List<Employee> findAll(){
- return list;
- }
-
-
- public void deleteByName(String name) throws Exception{
- if (name.length()==0||name==null) {
- throw new Exception("刪除用戶異常");
- }
-
- for (int i = 0; i < list.size(); i++) {
- if (name.equals(list.get(i).getName())) {
- list.remove(list.get(i));
- break;
- }
- }
- }
- }
3.2.3.建立服務類
public void deleteByName(String name) throws Exception{
if (name.length()==0||name==null) {
throw new Exception("刪除用戶異常");
}
for (int i = 0; i < list.size(); i++) {
if (name.equals(list.get(i).getName())) {
list.remove(list.get(i));
break;
}
}
}
}