上一节实践了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后,在左边的树上选择要测试的接口,双击打开测试界面,输入参数,执行,可以在输出区看到输出结果。