WebService学习总结(四)--基于CXF的服务端开发

 

本节将实践目前最流行的第二种web service 发布和调试框架  CXF

Apache CXF 是一个开放源代码框架,提供了用于方便地构建和开发 Web 服务的可靠基础架构。它允许创建高性能和可扩展的服务,您可以将这样的服务部署在 Tomcat 和基于 Spring 的轻量级容器中,以及部署在更高级的服务器上。Java的webService实现本身就是一个很耗性能的实现方案(xml与java对象之间在服务端以及客户端的互转比较消耗性能),目前java主流的webService应用以CXF、AXIS2为主,CXF比AXIS2效率更高,并且在java 应用中CXF很成熟,因此CXF在webservice中占有非常重要的地位。

下面一张网络上的图比较好的说明了CXF 与web service的关系

下面将具体说说如何使用CXF 进行Webservice 开发。关于CXF的实践分2篇,

    第一篇通过注解发布webservice,利用cxf 进行客户端开发。

    第二篇:通过spring与cxf 结合进行发布

 

前面已经学习了使用JDK发布WebService本文内容,下面学习cxf框架完成服务器发布 和 客户端开发

  需要准备环境 myeclipse 和 cxf 包 (我是用的Myeclipse2017 和 apache-cxf-3.1.15.zip的cxf包、jdk 1.8 环境  -- ps:apache-cxf-3.2.4.zip 版本太高,报错 好像跟jdk版本有关系,所以用了 apache-cxf-3.1.15.zip的cxf包)

 

1、服务端发布方式:用cxf 框架方式

1、首先在myeclipse中创建一个java web project

工程里面的类分别是Student.java   StudentDAO.java  StudentDAOImpl.java  StudentWs.java StudentWsImpl.java,

本文的Student对象用的是单例模式

这里重点贴一下 StudentWs.java  和  StudentWsImpl.java.    StudentWs是暴露的接口类,也是web service 服务接口,  实现类是服务的实现。

项目结构如下图

需要的jar包

我用的是apache-cxf-3.2.4 在lib里面拿过来的

 

基本代码如下:

Student.java 类

package com.myl.entity;
/**
 * 
 * @author maoyl
 * @date 2018.4.15
 * 实体类
 *
 */
public class Student {

    private String name;
    private String sex;
    private String brithday;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getBrithday() {
        return brithday;
    }
    public void setBrithday(String brithday) {
        this.brithday = brithday;
    }
    
}

GetStudentUtil.java

package com.myl.entity;

/**
 * 
 * @author myl
 * @date 2018.4.15
 * 单例获取Student
 *
 */
public class GetStudentUtil {
    
    private static Student student = new Student();
    
    private GetStudentUtil(){
        
    }
    
    public static Student getStudent(){
        return student;
    }

}

StudentDao.java

package com.myl.dao;

import com.myl.entity.Student;

/**
 * 
 * @author myl
 * @date 2018.4.15
 * Dao层接口
 *
 */
public interface StudentDao {
    
    public boolean addStudentDao(String name, String sex, String brithday);
    
    public Student queryStudentDao(String name); 

}

StudentDaoImpl.java

package com.myl.dao.daoImpl;

import com.myl.dao.StudentDao;
import com.myl.entity.GetStudentUtil;
import com.myl.entity.Student;

/**
 * 
 * @author myl
 * @date 2018.4.15
 * Dao层实现类
 *
 */
public class StudentDaoImpl implements StudentDao {
    
    public Student student;

    @Override
    public boolean addStudentDao(String name, String sex, String brithday) {
        student = GetStudentUtil.getStudent();
        System.out.println("student是否为空--"+student);
        System.out.println(student.getName());
        System.out.println();
        student.setName(name);
        student.setSex(sex);
        student.setBrithday(brithday);
        
        
        return true;
    }

    @Override
    public Student queryStudentDao(String name) {
        student = GetStudentUtil.getStudent();
        //代替DB
//        student.setName("mao");
//        student.setSex("boy");
//        student.setBrithday("22");
        System.out.println("------查询学生-------");
        if(name == null){
            System.out.print("输入为学生名称为null");
            return null;
        }
        if(!name.equals(student.getName())){
            System.out.println("没有此人");
            student =null;
        }
        System.out.println("返回student------------------");
        return student;
    }

}

StudentWs.java

package com.myl.service;

import com.myl.entity.Student;

/**
 * 
 * @author myl
 * @date 2018.4.15
 * service层接口
 *
 */
public interface StudentWs {

    public boolean addStudentService(String name, String sex, String brithday);
    
    public Student queryStudentService(String name);
}

StudentWsImpl.java

package com.myl.service.serviceImpl;

import javax.jws.WebMethod;
import javax.jws.WebService;
import com.myl.dao.StudentDao;
import com.myl.dao.daoImpl.StudentDaoImpl;
import com.myl.entity.Student;
import com.myl.service.StudentWs;

/**
 * 
 * @author myl
 * @date 2018.4.15
 * service层实现类,也是暴露给客户端的接口
 * exclude = true表示不暴露给客户端
 * @WebMethod(operationName = "queryStudentService") 标注自定义方法
 * @WebMethod 默认为该方法名
 *
 */

@WebService
public class StudentWsImpl implements StudentWs {
    
    public StudentDao studentDao;
    
//    @WebMethod(exclude = true)
//    public StudentDao getStudentDao() {
//        return studentDao;
//    }
//
//    @WebMethod(exclude = true)
//    public void setStudentDao(StudentDao studentDao) {
//        this.studentDao = studentDao;
//    }
    public StudentWsImpl() {
        studentDao = new StudentDaoImpl();
    }

    @WebMethod
    @Override
    public boolean addStudentService(String name, String sex, String brithday) {
        
        System.out.println("addStudent-------------");
        boolean result = studentDao.addStudentDao(name, sex, brithday);
        return result;
    }

    @WebMethod(operationName = "queryStudentService")
    @Override
    public Student queryStudentService(String name) {
        
        System.out.println("queryStudent-----------");
        Student student = studentDao.queryStudentDao(name);
        return student;
    }

}

StudentTest.java

package com.myl.test.publish;


import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

import com.myl.service.serviceImpl.StudentWsImpl;

/**
 * 
 * @author myl
 * @date      2018年4月15日   下午11:26:50
 * 服务端发布接口
 */
public class StudentTest {
    
    public static void main(String[] args) {
        System.out.println("web service start");
        //获取工厂对象
        JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
        
        //这里必须传入class,不能是接口,否则客户端会报异常 Could not instantiate service class ... because it is an interface  
        factory.setServiceClass(StudentWsImpl.class);
        //传入接口url
        factory.setAddress("http://localhost:5555/studentws"); 
        //创建接口
        Server server = factory.create();
        //启动接口
        server.start();    
        System.out.println("web service started"); 
    }

}

 测试发布如下图表示成功

访问http://localhost:5555/studentws?wsdl得到下图所示  ps:如果测试服务端和客户端不在同一个的机器上则localhost应该是本机的IP地址

 

 

 

2、使用CXF 进行 客户端开发

 为客户端加上cxf需要的jar包,否则运行会报错误

 

这些是使用cxf 里面的工具wsdl2java  生成的java类。在命令行执行下面命令,就可以生成这些类

D:\用户目录\下载\apache-cxf-3.1.15\bin>wsdl2java -p com.webservice http://localhost:8080/studentws?wsdl

如下图所示生成客户端代码成功:在本目录下 com.webservice中

wsdl2java用法: 
wsdl2java -p com -d src -all  wsdl

-p  指定其wsdl的命名空间,也就是要生成代码的包名
-d  指定要产生代码所在目录 
-client 生成客户端测试web service的代码 
-server 生成服务器启动web  service的代码 
-impl 生成web service的实现代码 
-ant  生成build.xml文件 
-all 生成所有开始端点代码:types,service proxy,,service interface, server mainline, client mainline, implementation object, and an Ant build.xml file. 

  

 把生成的代码放的客户端项目中

 

 编写客户端代码

package com.myl.test.service;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.webservice.StudentWsImpl;

/**
 * @author myl
 * @date 2018年4月15日
 * 客户端调用服务端发布的接口
 */
public class StudentSerivceTest {
    
    public static void main(String[] args) {
        //获取工厂对象
        JaxWsProxyFactoryBean jwpfb = new JaxWsProxyFactoryBean();  
        //加载生成的StudentWsImpl类
        jwpfb.setServiceClass(StudentWsImpl.class);
        //传入url接口地址
        jwpfb.setAddress("http://localhost:5555/studentws?wsdl"); 
        //创建接口对象
        StudentWsImpl ws = (StudentWsImpl) jwpfb.create();
        //调用接口中的方法
        ws.addStudentService("mao", "11", "22");
        ws.addStudentService("ya", "15", "23");
        ws.queryStudentService("mao");
        ws.queryStudentService("ya");
        
    }
    
}

运行客户端如图所示(每个方法中随便输出点东西)

以上即为cxf框架完成webservice的方法

-------------------------------------------------------------------------------------------

遇到问题:

 1、开始我下载的apache-cxf-3.2.4版本的cxf,运行报错

解决方法:

  应该是cxf版本太高,跟jdk1.8的版本有关,于是换了apache-cxf-3.1.15版本的既可以了

 

 2、cxf(3.1.15) 客户端异常 请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称。

 原因是:使用wsdk2java生成客户端文件的时候根据源文件生成了客户端代码,方法名字重复

 

解决方法

    生成代码的时候 使用 -p  com.webservice重命名报名即可

---------

 网上找的方法

    (1)最佳方案包名createTask 改成 全部小写 createtask

    (2)或者生成代码的时候 使用 -p  com.service.createtask 重命名报名即可

    (3)第三那种解决方案不建议,把createTask.java中的  @XmlType(name = "CreateTask", propOrder = {   "arg0"}) 中的name 改成 createTask 即可

 

posted @ 2018-04-16 00:06  maoyl  阅读(355)  评论(0编辑  收藏  举报