博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
cxf构建webservice的两种方式
阅读量:7078 次
发布时间:2019-06-28

本文共 13554 字,大约阅读时间需要 45 分钟。

一、简介

  对于基于soap传输协议的webservice有两种开发模式,代码优先和契约优先的模式。代码优先的模式是通过编写服务器端的代码,使用代码生成wsdl;契约优先模式首先编写wsdl,再通过wsdl生成服务器端的代码。对于代码优先的模式在 一文中已经做出介绍,这里主要介绍第二种方式。

二、wsdl文件结束

  一般wsdl文件结构如下:

  对于根元素中的xmlns与targetNamespace是包名的反转,name为实现类的名称。其他的属性都是固定的。

  <wsdl:types> 中主要定义元素和元素的类型。 一般对于一个接口来说,参数的整体作为一个输入元素类型,接口的返回值也是作为一个输出的元素类型。

  <wsdl:message > 主要定义接口的请求和响应消息。<wsdl:part>中的element属性使用到了<wsdl:types> 中定义的元素。

  <wsdl:portType name="MyService"> 主要定义了接口的操作,name表示接口的名称;<wsdl:operation name="sayHello">定义了具体的方法,name为方法的名称。子元素input和output使用到了message元素。

   <wsdl:binding name="MyServiceImplServiceSoapBinding" type="tns:MyService"> type为wsdl:portType中的那么值;name为我们自己定义的。子元素<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />是固定的。 <wsdl:operation name="sayHello">中子元素input和outputname和operation中子元素的name一直。

  <wsdl:service name="MyServiceImplService">定义了绑定的信息,<wsdl:port binding="tns:MyServiceImplServiceSoapBinding">type就是绑定的时候定义的name,子元素address为定义的地址;增加接口的时候不需要更改。

  wsdl是一个基于schema的xml文件,通过这个文件我们可以定义出接口的名称,参数类型,返回值等信息,也可以同该文件生成客户端和服务器端代码。

三、wsdl的各种返回类型

  1、返回列表类型

       对应于 List<Student> getStudentsByAge(int age) 方法,wsdl相关定义如下:

  在MyServiceImplPortImpl中的实现方法,可以做如下类似实现

public com.cxf.test.StudentsType getStudentsByAge(AgetType parameters) {         LOG.info("Executing operation getStudentsByAge");        System.out.println(parameters);        try {            System.out.println("getStudentsByAge invoked!");            System.out.println("gae : " + parameters.getAge());            com.cxf.test.StudentsType students =  new StudentsType();            StudentType stu1 = new StudentType();            stu1.setName("zhangsan1");                        StudentType stu2 = new StudentType();            stu1.setName("zhangsan2");                        students.getStudents().add(stu1);            students.getStudents().add(stu2);                        return students;        } catch (java.lang.Exception ex) {            ex.printStackTrace();            throw new RuntimeException(ex);        }    }

  2、voide 无返回值类型

   对应于 void deleteById(int id) 方法,wsdl相关定义如下:

  此时我们可以将生成的deleteById方法的返回类型改成void,需要同时修改接口和实现类。如:

  MyService 接口中的方法

@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)    @WebResult(name = "deleteByIdResponse", targetNamespace = "http://test.cxf.com/", partName = "parameters")    @WebMethod    public void deleteById(        @WebParam(partName = "parameters", name = "deleteByIdRequest", targetNamespace = "http://test.cxf.com/")        IdType parameters    );

  MyServiceImplPortImpl类中的方法

public void deleteById(IdType parameters) {         LOG.info("Executing operation deleteById");        System.out.println(parameters);        try {                        System.out.println(parameters.getId());        } catch (java.lang.Exception ex) {            ex.printStackTrace();            throw new RuntimeException(ex);        }    }

  3、返回枚举类型

  枚举为:enum{TEACHER, STUDENT, PRESIDENT} ;对应的方法为:enum getRoleById(int id),wsdl定义如下:

  在MyServiceImplPortImpl中的实现方法,可以做如下类似实现

public com.cxf.test.RoleType getRoleById(IdType parameters) {         LOG.info("Executing operation getRoleById");        System.out.println(parameters);        try {            System.out.println("id: " + parameters.getId());            com.cxf.test.RoleType roleType = RoleType.PRESIDENT;            return roleType;        } catch (java.lang.Exception ex) {            ex.printStackTrace();            throw new RuntimeException(ex);        }    }

  4、返回嵌套的对象类型

  嵌套对象结构如下

Student{

  int id;
  String name;
  Date date;
  Teacher teacher;
}
Teacher{
  String name;
  Boss boss;
}

Boss{

  String name;
  Parent parent;
}

Parent{

  String name;
}

  对于的方法为:Student getStudentById(int studentId),wsdl文件如下:

  在MyServiceImplPortImpl中的实现方法,可以做如下类似实现

public com.cxf.test.StudentType getStudentById(StudentIdType parameters) {         LOG.info("Executing operation getStudentById");        System.out.println(parameters);        try {            ParentType parentType = new ParentType();            parentType.setName("lisi");                        BossType bossType = new BossType();            bossType.setName("boss");            bossType.setParent(parentType);                        TeacherType teacherType = new TeacherType();            teacherType.setName("teacher");            teacherType.setBoss(bossType);                        com.cxf.test.StudentType student = new StudentType();            student.setId(parameters.getId());            student.setName("zhangsan");            student.setDate(getGregorianCalendar(new Date()));            student.setTeacher(teacherType);                        return student;        } catch (java.lang.Exception ex) {            ex.printStackTrace();            throw new RuntimeException(ex);        }    } private XMLGregorianCalendar getGregorianCalendar(Date date){        GregorianCalendar gc = new GregorianCalendar();        gc.setTime(date);        XMLGregorianCalendar calendar = new com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl(gc);        return calendar;    }

  客户端调用的时候

com.cxf.test.StudentIdType id = new StudentIdType(); id.setId(11111); com.cxf.test.StudentType student = port.getStudentById(id); System.out.println(student.getId()); System.out.println(student.getName()); System.out.println(student.getDate());  System.out.println(student.getTeacher().getBoss().getParent().getName());

  5、文件上传

   boolean upload(File file ),wsdl文件如下:

  接口实现类如下:

public com.cxf.test.BooleanType upload(FileType parameters) {         LOG.info("Executing operation upload");        System.out.println(parameters);        try {            byte[] buffer = parameters.getFileContent();            OutputStream os = new FileOutputStream(new File("test2.txt"));            os.write(buffer);            os.close();                        com.cxf.test.BooleanType result = new BooleanType();            result.setFilename(true);            return result;        } catch (java.lang.Exception ex) {            ex.printStackTrace();            throw new RuntimeException(ex);        }    }

  客户端调用如下:

System.out.println("Invoking upload..."); com.cxf.test.FileType data = new FileType(); InputStream is = new FileInputStream(new File("c:/apache-cxf-3.0.3.zip")); byte[] buffer = new byte[is.available()]; is.read(buffer); data.setFileContent(buffer); com.cxf.test.BooleanType result = port.upload(data); System.out.println(result.isResult());

  这种上传方式有些缺陷,当文件达到一定大小的时候,就会报java.lang.OutOfMemoryError: Java heap space异常。因为这种方式是一次性读取文件,将文件发送给服务器的。

6、使用MTOM文件上传

  这种方法可以解决普通上传遇到的问题。使用MTO上传需要在wsdl定义元素部分添加 xmlns:xmime="http://www.w3.org/2005/05/xmlmime"

命名空间,element添加属性xmime:expectedContentTypes="application/octet-stream"其他部分与普通上传一样。如下所示:

  使用MTOM需要服务端和客户端都需要开启MTOM

  服务端开启MTOM代码如下:

protected MyService_MyServiceImplPort_Server() throws java.lang.Exception {        System.out.println("Starting Server");        Object implementor = new MyServiceImplPortImpl();        String address = "http://localhost:9000/myservice";        javax.xml.ws.Endpoint endPoint = javax.xml.ws.Endpoint.publish(address, implementor);                //服务器端开启MTOM        javax.xml.ws.soap.SOAPBinding binding = (javax.xml.ws.soap.SOAPBinding)endPoint.getBinding();        binding.setMTOMEnabled(true);    }

  接口的实现

public com.cxf.test.BooleanType upload(FileType parameters) {         LOG.info("Executing operation upload");        System.out.println(parameters);        try {                        javax.activation.DataHandler dataHandler = parameters.getFileContent();            //获取文件输入流            InputStream is = dataHandler.getInputStream();                        //获取输出流            OutputStream os = new FileOutputStream(new File("c:/apache-cxf-3.0.3.zip.back"));                        //进行文件保存            int length = 0;            byte[] buffer = new byte[1024];            while(-1 != (length = is.read(buffer))){                os.write(buffer, 0, length);            }                        os.close();            is.close();                        com.cxf.test.BooleanType result = new BooleanType();            result.setResult(true);            return result;        } catch (java.lang.Exception ex) {            ex.printStackTrace();            throw new RuntimeException(ex);        }    }

  客户端的调用 

MyService port = ss.getMyServiceImplPort();// 客户端开启MTOMjavax.xml.ws.Binding binding = ((javax.xml.ws.BindingProvider)port).getBinding();((javax.xml.ws.soap.SOAPBinding)binding).setMTOMEnabled(true);System.out.println("Invoking upload...");//构造数据DataSource ds = new FileDataSource(new File("c:/apache-cxf-3.0.3.zip"));com.cxf.test.FileType data = new FileType();data.setFileContent(new DataHandler(ds));//调用接口com.cxf.test.BooleanType result = port.upload(data);System.out.println(result.isResult());

四、使用wsdl生成代码

  将的bin目录添加到系统环境变量path中,如(C:\apache-cxf-3.0.3\bin)。运行cmd,运行如下命令生成代码:

wsdl2java -all -impl -frontend jaxws21 -encoding utf8  c:/myservice.wsdl   #生成java服务器端和客户端代码,并生成实现类。

  表示使用wsdl生成java代码,-all表示同时生成客户端和服务器端代码; -frontend jaxws21表示 表示兼容jaxs 2.1版本;-encoding utf8 表示代码的编码格式为utf8;c:/myservice.wsdl 表示wsdl文件的地址,也可以是一个网络上的地址。其他命令如下:

wsdl2java -server -impl -frontend jaxws21 -encoding utf8  c:/myservice.wsdl   生成java服务器端代码,并生成实现类。wsdl2java -client -frontend jaxws21 c:/myservice.xml 生成java客户端代码

转载地址:http://snpml.baihongyu.com/

你可能感兴趣的文章
Java并发编程笔记之AbstractQueuedSynchronizer源码分析
查看>>
AI戒毒?没错,北京开始这么干了
查看>>
第178天:表单验证
查看>>
HTTP配置文件详解(访问控制、虚拟主机、DEFLATE、HTTPS配置
查看>>
数据库分离附加(附日记丢失的处理)
查看>>
开启HDR视觉盛宴:究竟什么视频算得上HDR?
查看>>
阿里云视频点播播放常见问题排查指南
查看>>
Java最全异常讲解
查看>>
Android保持屏幕常亮
查看>>
JS-DOM2级事件对象跨浏览器处理(已封装)
查看>>
用户名和密码校验程序
查看>>
浅析Java RTTI 和 反射的概念
查看>>
Django中用户权限模块
查看>>
Android TransitionDrawable:过渡动画Drawable
查看>>
keras实战项目——CIFAR-10 图像分类
查看>>
数据库变更管理
查看>>
隐私浏览器 Tor Browser 8.0.7 发布,安全更新版本
查看>>
Veeam发布2016年业绩: 同比增长28%,预订总收入达6.07亿美元
查看>>
慧荣科技发布全球首款商用SD 5.1控制器解决方案
查看>>
spark 计算结果写入mysql 案例及常见问题解决
查看>>