上一節實踐了Webservice的用戶端開發,那麼核心問題服務是如何開發和釋出呢?Webservice 服務端的開發有多種方式:
1、利用jdk+myeclipse ,釋出和開發一個背景服務(适合獨立服務)
2、利用axis2+myeclipse+tomcat 開發和釋出(适合web工程)
3、利用cxf + myeclipse +tomcat 開發和釋出(适合web工程)
4、利用 xfire +myeclipse+tomcat 開發和釋出(适合web工程)
從本節開始,将實踐這些不同的釋出webservice的方法,本節就先實踐第一種,利用 jdk+myeclipse來釋出一個背景服務
一、目标
1、掌握jdk中編寫webservice服務端工程的設定和開發過程
2、編寫用戶端
3、服務端和用戶端釋出,并進行調試
二、服務端編寫
1、建立一個服務端工程StudyWsStudent ( 關于學生的webservice 服務)
為了便于服務端的程式進行擴充,在服務端的設計上,采用接口程式設計的方式,即采用 實體類,dao接口,dao實作,接口類的方式才組織。 代碼都很簡單。
進入後的選項要注意一下
Framework這裡,注意選JAX-WS, 另外JTL 這裡選none
先看一下工程的結構:
代碼如下:
實體類Student
package com.study.entity;
import java.util.List;
public class Student {
String Name;
String Sex;
String Birth;
String DateIn;
//已經選擇的課程
List<String> ListLesson;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getSex() {
return Sex;
}
public void setSex(String sex) {
Sex = sex;
}
public String getBirth() {
return Birth;
}
public void setBirth(String birth) {
Birth = birth;
}
public String getDateIn() {
return DateIn;
}
public void setDateIn(String dateIn) {
DateIn = dateIn;
}
//采用dao 方式開發的情況下,實體類是否要設計action?
boolean selectLesson( String Lesson ){
if(ListLesson.size()>10)
{
System.out.println("You have select ten Lesson, cannot select more!");
return false;
}
else{
ListLesson.add(Lesson);
}
return true;
}
}
實體操作接口StudentDAO
package com.study.dao;
import com.study.entity.Student;
public interface StudentDAO {
//學生操作,新增學生
boolean addStudent(Student student);
//學生操作,删除學生
boolean delStudent(Student student);
//學生操作,修改學生資訊
boolean modifyStudent(Student student);
//學生操作,查詢學生資訊,查詢到傳回學生對象,否則傳回null
Student queryStudent( String StudentName);
}
操作接口實作 StudentDAOImpl
package com.study.dao.impl;
import com.study.dao.StudentDAO;
import com.study.entity.Student;
public class StudentDAOImpl implements StudentDAO {
@Override
public boolean addStudent(Student student) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean delStudent(Student student) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean modifyStudent(Student student) {
// TODO Auto-generated method stub
return false;
}
@Override
public Student queryStudent(String StudentName) {
// TODO Auto-generated method stub
return null;
}
}
最後是Webservice 接口服務StudentOptApi
package com.study.student.service;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import com.study.dao.StudentDAO;
import com.study.dao.impl.StudentDAOImpl;
import com.study.entity.Student;
@WebService
public class StudentOptApi {
List<String > listStudentInfo=new ArrayList<String>();
StudentDAO studentDAO ;
// public StudentOptApi(){
// System.out.println("studentDAO is init");
// studentDAO= new StudentDAOImpl();
// }
@WebMethod(exclude = true)
public StudentDAO getStudentDAO() {
return studentDAO;
}
@WebMethod(exclude = true)
public void setStudentDAO(StudentDAO studentDAO) {
this.studentDAO = studentDAO;
}
public boolean addStudent( Student student){
//調用studentDAO.addStudent 方法入庫
System.out.println("Now put student into DB!");
studentDAO.addStudent(student);
//listStudent模拟資料庫中的student對象集合
listStudentInfo.add("Name:"+student.getName()+",sex:"+student.getSex()+",birthday:"+student.getBirth());
// for( Student aStudent : listStudent ){
// System.out.println(aStudent.getName());
// }
return true;
}
@WebMethod(operationName = "queryStudent")
public String queryStudent( @WebParam(name = "StudentName")String studentName){
for(String aStudentInfo : listStudentInfo )
{
if(aStudentInfo.startsWith("Name:"+studentName+",")){
System.out.println("queryStudent Infomation successfully !");
return aStudentInfo;
}
else{
System.out.println("queryStudent Infomation failture !");
}
}
return "null";
}
public static void main(String[] args) {
// create and publish an endpoint
StudentOptApi studentWs = new StudentOptApi();
studentWs.studentDAO= new StudentDAOImpl();
Student student1 = new Student();
student1.setName("Tom");
student1.setSex("male");
student1.setBirth("1970/05/08");
Student student2 = new Student();
student2.setName("Lili");
student2.setSex("female");
student2.setBirth("1972/05/23");
studentWs.addStudent(student1);
studentWs.addStudent(student2);
//Endpoint endpoint = Endpoint.publish("http://localhost:8080/StudentService/", studentWs);
Endpoint endpoint = Endpoint.publish("http://localhost:8080/StudentService/queryStudent", studentWs);
}
}
這裡需要注意一下 StudentService 類,它采用了Webservice的annotation,@WebMethod(operationName = "addStudent",exclude = true), 如果不加 exclude = true 會報告下列錯誤
錯誤這裡說明了,JAXB 不支援interfaces類。 而我們的服務是面向接口的程式設計,是以需要通過 exclude = true 來解決這個問題。
另外,如果沒有寫類的初始化方法,也會報下面的異常
Exception in thread "main" com.sun.xml.internal.ws.model.RuntimeModelerException: The web service defined by the class
com.study.student.service.StudentService does not contain any valid WebMethods.
at com.sun.xml.internal.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:233)
at com.sun.xml.internal.ws.server.EndpointFactory.createSEIModel(EndpointFactory.java:328)
at com.sun.xml.internal.ws.server.EndpointFactory.createEndpoint(EndpointFactory.java:190)
好,現在運作一下這個服務類,我們通過URL來打開這個服務
http://localhost:8080/StudentService/queryStudent
也給出了wsdl的位址,可以通過這個位址擷取wsdl檔案,并編寫用戶端
三、用戶端編寫
根據上一篇的說明,用戶端的開發步驟如下:
1)擷取wsdl 檔案
2)并寫編譯成本地java 檔案
3)編寫用戶端代碼
在本例中,由于服務在本地搭建的,是以可以1),2) 兩步合并處理,使用的指令為:
C:\jdk1.6.0_43\bin\wsimport -d E:\tmp -s E:\cwqwork\myeclipse_workspace\StudyDubboCli\src -keep -verbose http://localhost:8080/StudentService/queryStudent?wsdl
wsimport 的幾個參數含義這裡列一下:
-keep:是否生成java源檔案
-d:指定輸出目錄
-s:指定源代碼輸出目錄
-p:以package的形式生成檔案
-verbose:在控制台顯示輸出資訊
執行上面的指令後,就可以生成用戶端需要的java檔案,如下圖:
下面,列一下用戶端的編碼: StudentWsCli.java
package com.study.webservice.client;
import com.study.student.service.StudentOptApi;
import com.study.student.service.StudentOptApiService;
public class StudentWsCli {
public static void main(String[] args) {
//從webservice接口中擷取到接口對象
StudentOptApi studentService = new StudentOptApiService().getStudentOptApiPort() ;
String info1 = studentService.queryStudent("Tom");
System.out.println(info1);
String info2 = studentService.queryStudent("Lili");
System.out.println(info2);
String info3 = studentService.queryStudent("Jerry");
System.out.println(info3);
}
}
在myeclipse裡面,工程情況如下:
運作用戶端,用戶端列印如下:
查詢"Tom", “Lili”,接口傳回 Tom的相關資訊,查詢“Jerry",接口傳回null
四、服務端釋出
下面嘗試将服務端釋出到虛拟機上運作,實踐一下服務端部署的過程。
因為是部署到虛拟機,用戶端要從主控端連接配接,是以修改一下服務端的endpoint代碼,将localhost修改為 0.0.0.0 表示允許全部的外部ip接入。将服務端用fatjar 打包後,傳送到虛拟機192.168.136.144上, 運作 java -jar StudyWsStudent_fat.jar
打開http://192.168.136.144:8080/StudentService/queryStudent 無法打開(原因後面說)
http://192.168.136.144:8080/StudentService/queryStudent?wsdl 正常打開
用用戶端連接配接,注意用戶端要修改一下StudentOptApiService.java檔案中的ip位址,否則要用http://192.168.136.144:8080/StudentService/queryStudent?wsdl 這個位址重新編譯。
用戶端連接配接正常,說明程式是釋出正常的。
現在回過來檢查 http://192.168.136.144:8080/StudentService/queryStudent 無法打開的原因,因為我們是用java自帶的編寫webservice服務,是以檢查一下144上的java版本,發現jar包是用jdk 1.6而 144上是java 1.8 。 144上有另外一個java 1.7,用1.7來運作,這下可以正常打開URL了
五、soap工具調試
最後介紹一個soap工具,因為webservice是基于soap協定的,是以可以用soap工具來進行測試,這裡簡單介紹一個soap工具soapUi
通過這個工具可以不用開發webservice用戶端直接通過工具調測接口。
建立一個工程:
點OK後,在左邊的樹上選擇要測試的接口,輕按兩下打開測試界面,輸入參數,執行,可以在輸出區看到輸出結果。