• 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.15in>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 即可

  • 相关阅读:
    StringTable
    TCP网络协议
    也说JVM内存区域
    JVM类加载
    java中的引用:强、软、弱、虚
    AQS
    vscode支持unicode编码
    设计模式简记-快速改善代码质量的编程规范
    擅事利器
    设计模式简记-通过重构增强代码可测试性实战
  • 原文地址:https://www.cnblogs.com/maoyali/p/8850430.html
Copyright © 2020-2023  润新知