MyEclipse8.0中使用 JAX-WS 部署 WebService 实例

示例背景简单描述.

有一个学校A提供一个Web Service服务:

1.只要使用者B 输入一个学生的ID号, A就能告诉B这个学生的详细信息.

2.只要使用者B 输入一个是否是男性的逻辑值, A就能向B提供这个班级中所有按逻辑值找到的学员信息

3.只要使用者B 输入一个学生的ID号和密码, 和这个学生的新的详细信息, 那么A就可以帮助B修改这个学生的信息.

根据这个需求, 应该先实现服务提供者A所能提供的服务(对应以上)

1.public Student getStudentInfoByStuID(Integer stuID){}

2.public List<Student> getStudentsInfoBySex(boolean isMale){}

3.public boolean updateStudentInfo(Integer stuID,String password,Student newStudentInfo){}

下面是具体操作步骤:

Step 01: 创建一个Web Project: StudentServer,完成实体类,业务逻辑和服务接口的实现.

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

Student.java

package com.apt.server.entity;

import java.util.Date;

/**
 * A Student class
 * @author Simonlv
 */
public class Student {

 private Integer id;
 private String name;
 private String password;
 private Integer age;
 private Date birthDay;
 private boolean isMale;
 private double height;

 public Student(Integer id, String name, String password, Integer age,
   Date birthDay, boolean isMale, double height) {
  this.id = id;
  this.name = name;
  this.password = password;
  this.age = age;
  this.birthDay = birthDay;
  this.isMale = isMale;
  this.height = height;
 }

 //getter/setter methods

}

StudentBiz.java

package com.apt.server.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.apt.server.entity.Student;

/**
 * Student Business Logic Object .This class is mainly used for loading Student
 * data or updating Student information by some condition.
 * 
 * @author Simonlv
 */
public class StudentBiz {

 /**
  * Get the information of a student by giving this student ID NO.
  * 
  * @param stuID
  *            Student's ID NO.
  * @return The detailed information of a student,a student object.
  */
 public Student getStudentInfoByStuID(Integer stuID) {
  //student ZhangSan Female
  Student s1 = new Student(1001, "zhangSan", "111111", 21, new Date(), false, 175.50d);
  //student liSi Male
  Student s2 = new Student(1002, "liSi", "222222", 25, new Date(), true, 185.50d);
  if(stuID==1001){
   return s1;
  }else{
   return s2;
  }
 }

 /**
  * Get the information of all students with gender is M or F
  * 
  * @param isMale
  *            true indicate Male, false means Female
  * @return A list collection with the object of student class.
  */
 public List<Student> getStudentsInfoBySex(boolean isMale) {
  //student zhangSan_1 Female
  Student s1 = new Student(1001, "zhangSan_1", "111111", 21, new Date(), false, 171.50d);
  //student zhangSan_2 Female
  Student s2 = new Student(1001, "zhangSan_2", "111111", 22, new Date(), false, 172.50d);
  //student zhangSan_3 Female
  Student s3 = new Student(1001, "zhangSan_3", "111111", 23, new Date(), false, 173.50d);
  //student zhangSan_4 Female
  Student s4 = new Student(1001, "zhangSan_4", "111111", 24, new Date(), false, 174.50d);
  
  //student liSi Male
  Student s5 = new Student(1002, "liSi", "222222", 25, new Date(), true, 181.50d);
  //student wangWu Male
  Student s6 = new Student(1002, "wangWu", "222222", 25, new Date(), true, 182.50d);
  
  //List collection of Student
  List<Student> list = new ArrayList<Student>();
  if(isMale){
   //Male
   list.add(s5);
   list.add(s6);
  }else{
   //Female
   list.add(s1);
   list.add(s2);
   list.add(s3);
   list.add(s4);
  }
  return list;
 }

 /**
  * Update a student information by putting ID,Password and the new
  * information of this student
  * 
  * @param stuID the ID of a student
  * @param password the password of a student
  * @param newStudentInfo An object of Student type.
  * @return true-update successfully ,or false-update failure.
  */
 public boolean updateStudentInfo(Integer stuID, String password,
   Student newStudentInfo) {
  //student ZhangSan Female
  Student s1 = new Student(1001, "zhangSan", "111111", 21, new Date(), false, 175.50d);
  //check
  if(stuID==s1.getId() && password.equals(s1.getPassword())){
   //success ...
   return true;
  }else{
   return false;
  }
 }
}

 Step02:要将此WEB程序发布成为 Web Service,找到此图标,点击进去

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

 Step03:选中要发布成为WebService的项目, Framework:JAX-WS, Strategy: Create web service from Java class

在这里可以看出,创建WebService的方式有两种:

第一种是 Create web service from WSDL document . 先写WSDL 文档,然后再由WSDL文件生成服务器端的类和服务. 但是这种方式不是很直观, 对于WSDL文件的语法和格式以及提供的插件工具要很熟悉.

第二种是 Create web service form Java class. 这种方式非常简单, 我们只需要提供我们所写好的预备对外公开的API接口类(这里的接口不一定是指Interface.泛指提供方法入口的类)

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

 Step04:准备选择哪个JAVA类将成为Web Service 对外服务的接口

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

 Step05: 选择了StudentBiz 业务逻辑类,会自动创建一个 Delegate class name:com.apt.server.service.StudentBizDelegate

(此处有时需手动填写,并不是通过browser找到)

必须要注意的:  同时要求选择 Generate WSDL in project, 因为是通过类来生成映射的WSDL文件,最终对外发布的也是这个WSDL文件.

WSDL Customization 中

Target namespace 可以保持默认,ServiceName和Service port可以更改,但是需要知道更改了后,这些东西将会出现在哪个文件中. 所以初步阶段默认即可. 同时要说的是,如果你的包名,类名都设计的很合理,那么这几个参数的名字也是很合理的.

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
 
点击下一步.

  Step06: Generating JAX-WS Web Services' has encountered a problem. An internal error occurred during: Generating JAX-WS Web Services.

在我的印象中,类似于这样的错误发生了很多次,每次都有这样或那样不同的问题,绕不过去必须解决. 并且这种错误不是在某某编译器编译后告诉你一个结果, 也不是在某某服务器启动后加载时出现的异常.

所以遇到这样的问题,方式就是尽量理解它所提供的错误说明和 Error Log

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

Step07:对于“Generating JAX-WS Web Services' has encountered a problem. ”这种错误的处理

看Step06中图片, Show Error Log,点击进去查看错误日志-这是最最有效的方式, 如果在网上搜, 同样的问题可能会有N多不同的答案,原因一会再说.

看到下图中有一句很长的话吗?

counts of IllegalAnnotaionException.apt.server.entity.Student does not have a no-arg default constructor .....明白了吗?

再回头看看刚才所写的 Student.java 中,Student类中有无参的构造方法吗? 没有. 原因就在这里.

 MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

为什么刚才说同样的错误问题Step06有N个不同的回答.我故意又改错了某些代码,生成时报Step06的错误看看错误,还是看错误日志(如下图所示) : 第一行:

******.GetStudentInfoByStuID is not found.Have you run APT to generate them . 但是这个错误不会是像刚才那样容易理解,并且拿着 Have you run APT to generate them 去网上搜索的话估计也会被各种各样的答案弄崩溃掉.解决方式各种各样,有的需要下载jar,有的需要使用工具编译. 总之, 我受到过这样的错误引导.  其实如果这个代码接口是你写的,这个Web Service 现在也是你去发布生成的话, 对于 GetStudentInfoByStuID is not found - "GetStudentInfoByStuID 方法没有找到" 难道不会疑惑吗? 明明是写过的代码,有印象,并且好像写了它的几个重载方法.--问题就出在重载上了.导致不能找到这个方法.  WebService目前应该可以做到重载了,但是我没有动手实践过.

所以同样的Step06不能 generate成功 ,其实有很多原因.

我在最初尝试发布Web Service的时候碰到的错误远不止这些,这是最好演示的几个错误问题.要说的是:

即使是发现了从未没有出现过的错误,那也要用从来没有过的态度坚决地把这个错误搞定.

知道这些错误原因了,就把代码中的错误解决掉,后面继续.

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

 注解: 如果没有记错的话, 不同版本的IDE,错误出现的位置不一样,有的是在代码发布到容器和容器加载阶段(MyEclipse 6.5) , 有的是在WebService创建和发布阶段(MyEclipse8.x),个人认为这是MyEclipse8.x在这里比MyEclipse6.5好的地方吧.

Step08: 在解决了刚才错误的情况下,最后生成了 WebService的 Server 端,结构图如下:

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

多了一些内容:

com.apt.server.service.StudentBizDelegate.java

WEB-INF 下的 wsdl文件夹和两个文件 .xsd,和 wsdl 文件.

WEB-INF 下的 sun-jaxws.xml文件

修改了 web.xml文件.

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns=" http://java.sun.com/xml/ns/javaee"
 xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <servlet>
  <description>JAX-WS endpoint - StudentBizService</description>
  <display-name> StudentBizService</display-name>
  <servlet-name> StudentBizService</servlet-name>
  <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name> StudentBizService</servlet-name>
  <url-pattern> /StudentBizPort</url-pattern>
 </servlet-mapping>
 <welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>
 <listener>
  <listener-class>
   com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
 </listener>
</web-app>
这个修改的部分就告诉你如何去请求发布的WebService的后缀了,一定是 http://IP:port/web path/StudentBizPort?WSDL
 
Step09: StudentBizService.wsdl WSDL文件可以做修改和方法参数说明
这个视图和文件保持默认即可,可以不用去修改.
以前有通过编辑WSDL视图再生成Java Class,现在不需要,采用的方式是通过Java Class来生成WSDL文件.
MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
 
Step10: StudentBizService.wsdl  上图中 getStudentInfoByStuID 右边的灰色小箭头点击进去,看到的就是下图
可以完成对方法参数的编辑,比如写一些参数说明和注释, 但是参数名称就不要改动了,因为这个参数名称和其它的文件也会有关联. 如果是先写WSDL ,再生成Class 是没有问题的. 所以最好不要修改, 能做的就是加加文档说明
 
MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
点击右键-Show properties可以看看
MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
 
Step11:WSDL-Source
这是WSDL文件的源代码,一般来修改的就是最下面的部分. 因为我们需要去发布一个服务在网络上, 其它应用程序通过访问我们的服务来调用我们的接口. 所以这个地址的发布时
第一个要把这个localhost修改成这个Web project 要运行的服务器IP, 如果不改也没有太大关系,因为localhost确实指的就是自身IP.
第二个是生成的Web Service端口号一般默认都是8080,所以这个端口号肯定要根据你的服务器(我的是使用Tomcat6.0)的端口号来决定.由于我Tomcat中默认的端口号就是8080,所以我不需要修改. 
以前我的是Tomcat server port 我改成了80 ,那么这里自然直接写成 http://localhost/StudentServer/StudentBizPort
MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
 
Step12: Deploy Web Project
MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
 
Step13: Error configuring application listener of class com.sun.xml.ws.transport.http.servlet.WSServletContextListener
java.lang.ClassNotFoundException: com.sun.xml.ws.transport.http.servlet.WSServletContextListener
 
MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
应用程序部署了,但是没有成功,错误如同上面描述一样.找不到这个 WSServletContextListener.
一般找不到某某类,原因只有一个,我们的项目中没有加入这个类所在的jar包.
到网上去Google.肯定又是一大堆的答案,但是基本上都能说正确,就是要去下载jar包.
 
 Step14:在MyEclipse中加入WSServletContextListener所在的jar包.
项目-右键Build Path-Add Libraries..
MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
 
Add MyEclipse Librabires
MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
 
找到如图所示的两个Libraries,并选中即可
MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
 
观察到项目中 jar 环境的变化,多了这两个库
MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log
 
Step15:解决了上述问题,部署-启动服务器后,输入 http://localhost:8080/StudentServer/StudentBizPort?WSDL
访问,如果看到了这个页面-成功.
要知道StudentBizPort 在哪里出现,必须对发布Web Service Server 的前14个阶段中的某些步骤要仔细观察,且对生成出来的WSDL文件和其它文件要仔细观察.

 MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

复制 schemaLocation 的地址放到浏览器中,看看 XSD 文件.

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

至于WSDL文件,有时间的话可以好好研究其中各个元素的含义,特别重要的是它与我们程序中相关接口之间的对应关系.

Web Service 服务器端的配置和发布目前就算完成了. 记住在使用WSDL文件生成客户端时, Tomcat 服务器要一直开启,因为别人要使用你的服务.

到此已经成功部署webservice在服务器上。

下面就是怎样使用部署的webservice

准备使用一个web服务,首先要知道它的WSDL URL.

另外,我的客户端可以是C/S程序,也可以是B/S程序,可以使用JAVA,也可以是用C,C#等不同的程序语言,关键的就是需要知道WSDL文件即可. 但是在本示例中只使用了JAVA程序作为客户端, 原因前面也已经提过,就是对于List集合或者其它更复杂的接口在调用它们时不能很好的保证数据解析和传递的正确.

Step16:创建任意的一个JAVA客户端程序,可以是C/S也可以是B/S的程序.

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

Step17:这次是创建一个Web Service Client

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

 

Step18:使用已经存在的WSDL URL 创建一个Web Service 客户端程序

要注意URL中的localhost在实际使用中,应该是Web Service 发布的真正IP地址,端口号也要和服务器端口一致,由于我的服务器端程序和客户端在同一台电脑和部署在同一个服务器中,就只能这么演示.

例如以后可能实际使用的URL是这样的. http://202.87.33.42:8733/StudentServer/StudentBizPort?WSDL

还要创建一个java package - com.test.client .作为客户端生成代码的文件包位置,下一步.

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

 

Step19:会有一个验证界面会验证这个WSDL文件存不存在或者格式是否正确.

自我测试时,停掉服务就会发现这个验证界面或出现错误,可以试着读一读. 因为很多时候你需要在网上找别人发布的Web Service程序来创建你自己的客户端,也需要验证. 有时的验证不能通过,这时就知道原因了.

 MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

 Step20:验证成功后生成的代码

看看其中也有Student类

主要的是StudentBizDelegate.java和StudentBizService.java

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

  Step21:自己写代码测试成功输出

MyEclipse6.5(或以上版本)中使用JAX-WS - 完成 WebService 客户端和服务器端DEMO - lvpin - Java Log

测试类如下:
package com.test.clienttest;
import java.util.List;
import com.test.client.Student;
import com.test.client.StudentBizDelegate;
import com.test.client.StudentBizService;
/**
 * Test Web Services
 * 
 * @author Simonlv
 * 
 */
public class StudentClient {
 // Service Object
 private StudentBizService service;
 // Service Delegate Object
 private StudentBizDelegate delegate;
 // init
 public StudentClient() {
  service = new StudentBizService();
  delegate = service.getStudentBizPort();
 }
 // print student
 private void printStudent(Student s) {
  System.out.println("\nID:" + s.getId() + "\tName:" + s.getName()
    + "\tPWD:" + s.getPassword() + "\tAge:" + s.getAge()
    + "\tBirth day:" + s.getBirthDay() + "\tHeight:"
    + s.getHeight());
 }
 // get student by id
 public void showStudentInfo(Integer ID) {
  Student s = delegate.getStudentInfoByStuID(ID);
  printStudent(s);
 }
 // get students by sex
 public void showStudentBySex(boolean isMale) {
  List<Student> list = delegate.getStudentsInfoBySex(isMale);
  for (Student s : list) {
   printStudent(s);
  }
 }
 // update
 public void updateStudent(Integer id, String pwd, Student stu) {
  boolean suc = delegate.updateStudentInfo(id, pwd, stu);
  System.out.println("Update result:" + suc);
 }
 // Main test
 public static void main(String[] args) {
  StudentClient sc = new StudentClient();
  // 1.Get a student information by student's id.
   sc.showStudentInfo(1001);
  // print result
  // ID:1001 Name:zhangSan PWD:111111 Age:21 Birth
  // day:2010-06-27T20:09:14.437+08:00 Height:175.5
  sc.showStudentInfo(1003);
  // print result
  // ID:1002 Name:liSi PWD:222222 Age:25 Birth
  // day:2010-06-27T20:09:44.250+08:00 Height:185.5
  // 2.Get all students - Male
  sc.showStudentBySex(true);
  // print result
  /**
   * 
   ID:1002 Name:liSi PWD:222222 Age:25 Birth
   * day:2010-06-27T20:10:45.390+08:00 Height:181.5
   * 
   * ID:1002 Name:wangWu PWD:222222 Age:25 Birth
   * day:2010-06-27T20:10:45.390+08:00 Height:182.5
   */
  
  //3. omit ..update ......
 }
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值