当前位置:   article > 正文

在springboot中创建webservice服务_springboot webservice

springboot webservice

        最近因为业务的需要,甲方让我在项目中提供webservice接口,在创建webservice的过程中,遇到了许多的坑,躺了许多雷,为了避免大家采坑,现整理如下。

        首先是springboot的pom.xml文件,主要是引入以下依赖

  1. <dependency>
  2. <groupId>javax.xml.bind</groupId>
  3. <artifactId>jaxb-api</artifactId>
  4. <version>2.3.0</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.sun.xml.bind</groupId>
  8. <artifactId>jaxb-impl</artifactId>
  9. <version>2.3.0</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.sun.xml.bind</groupId>
  13. <artifactId>jaxb-core</artifactId>
  14. <version>2.3.0</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>javax.activation</groupId>
  18. <artifactId>activation</artifactId>
  19. <version>1.1.1</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-web-services</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.apache.cxf</groupId>
  27. <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
  28. <version>3.3.1</version>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.apache.cxf</groupId>
  32. <artifactId>cxf-rt-transports-http</artifactId>
  33. <version>3.2.2</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.codehaus.woodstox</groupId>
  37. <artifactId>stax2-api</artifactId>
  38. <version>4.0.0</version>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.codehaus.woodstox</groupId>
  42. <artifactId>woodstox-core-asl</artifactId>
  43. <version>4.4.1</version>
  44. </dependency>
  45. <!-- 这个主要是client访问的,但是问题多多-->
  46. <dependency>
  47. <groupId>org.apache.axis</groupId>
  48. <artifactId>axis</artifactId>
  49. <version>1.4</version>
  50. </dependency>
  51. <dependency>
  52. <groupId>axis</groupId>
  53. <artifactId>axis-jaxrpc</artifactId>
  54. <version>1.4</version>
  55. </dependency>
  56. <dependency>
  57. <groupId>commons-discovery</groupId>
  58. <artifactId>commons-discovery</artifactId>
  59. <version>0.2</version>
  60. </dependency>
  61. <dependency>
  62. <groupId>wsdl4j</groupId>
  63. <artifactId>wsdl4j</artifactId>
  64. <version>1.6.3</version>
  65. </dependency>

 我的jdk环境是jdk11,所以要引入最开始的4个依赖。

还有,springboot的版本不能太高,我原先的版本是2.3.3,跑不起来,后来在网上查到是版本不兼容导致的问题,于是把springboot的版本降到2.0.1,后来才跑起来。

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
         <version>2.0.1.RELEASE</version>
         <!--<version>2.3.3.RELEASE</version>-->
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

然后,新建webservice的接口文件,如下所示:

  1. package com.mango.jkm.webservice;
  2. import java.util.List;
  3. import javax.jws.WebMethod;
  4. import javax.jws.WebParam;
  5. import javax.jws.WebService;
  6. @WebService(name = "Wbceshijk", targetNamespace = "http://server.webservice.example.com")
  7. public interface Wbceshijk {
  8. @WebMethod
  9. String emrService(@WebParam(name = "data") String data,@WebParam(name = "data2") String data2);
  10. @WebMethod
  11. String student1111(@WebParam(name = "data") String data,@WebParam(name = "data2") String data2);
  12. @WebMethod
  13. String aboutstudent(@WebParam(name="student") Student student);
  14. @WebMethod
  15. String studentlist(List<Student> list1);
  16. }

然后是接口的实现类

  1. package com.mango.jkm.webservice;
  2. import java.util.List;
  3. import javax.jws.WebParam;
  4. import javax.jws.WebService;
  5. import org.springframework.stereotype.Component;
  6. @Component
  7. @WebService( targetNamespace = "http://server.webservice.example.com",
  8. endpointInterface = "com.mango.jkm.webservice.Wbceshijk")
  9. public class Webserviceceshi implements Wbceshijk{
  10. @Override
  11. public String emrService( String data,String data2) {
  12. if(null == data || "".equals(data.trim())){
  13. return "传入的参数为空";
  14. }
  15. return "data="+data+"@data2="+data2;
  16. }
  17. @Override
  18. public String student1111(String data, String data2) {
  19. // TODO 自动生成的方法存根
  20. return "22222data="+data+"@data2="+data2;
  21. }
  22. @Override
  23. public String aboutstudent(Student student) {
  24. // TODO 自动生成的方法存根
  25. System.out.println(student==null);
  26. return "student.getName()="+student.getName();
  27. }
  28. @Override
  29. public String studentlist(List<Student> list1) {
  30. // TODO 自动生成的方法存根
  31. return "list1.size()="+list1.size();
  32. }
  33. }

 再然后是webservice的配置相关

  1. package com.mango.jkm.webservice;
  2. import javax.xml.ws.Endpoint;
  3. import org.apache.cxf.Bus;
  4. import org.apache.cxf.bus.spring.SpringBus;
  5. import org.apache.cxf.jaxws.EndpointImpl;
  6. import org.apache.cxf.transport.servlet.CXFServlet;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.web.servlet.ServletRegistrationBean;
  9. import org.springframework.context.annotation.Bean;
  10. import org.springframework.context.annotation.Configuration;
  11. @Configuration
  12. public class WebServiceConfig {
  13. @Autowired
  14. private Wbceshijk serverServiceDemo;
  15. /**
  16. * Apache CXF 核心架构是以BUS为核心,整合其他组件。
  17. * Bus是CXF的主干, 为共享资源提供一个可配置的场所,作用类似于Spring的ApplicationContext,这些共享资源包括
  18. * WSDl管理器、绑定工厂等。通过对BUS进行扩展,可以方便地容纳自己的资源,或者替换现有的资源。默认Bus实现基于Spring架构,
  19. * 通过依赖注入,在运行时将组件串联起来。BusFactory负责Bus的创建。默认的BusFactory是SpringBusFactory,对应于默认
  20. * 的Bus实现。在构造过程中,SpringBusFactory会搜索META-INF/cxf(包含在 CXF 的jar中)下的所有bean配置文件。
  21. * 根据这些配置文件构建一个ApplicationContext。开发者也可以提供自己的配置文件来定制Bus。
  22. */
  23. @Bean(name = Bus.DEFAULT_BUS_ID)
  24. public SpringBus springBus() {
  25. return new SpringBus();
  26. }
  27. /**
  28. * 此方法作用是改变项目中服务名的前缀名,此处127.0.0.1或者localhost不能访问时,请使用ipconfig查看本机ip来访问
  29. * 此方法被注释后, 即不改变前缀名(默认是services), wsdl访问地址为 http://127.0.0.1:8080/services/ws/api?wsdl
  30. * 去掉注释后wsdl访问地址为:http://127.0.0.1:8080/soap/ws/api?wsdl
  31. * http://127.0.0.1:8080/soap/列出服务列表 或 http://127.0.0.1:8080/soap/ws/api?wsdl 查看实际的服务
  32. * 新建Servlet记得需要在启动类添加注解:@ServletComponentScan
  33. *
  34. * 如果启动时出现错误:not loaded because DispatcherServlet Registration found non dispatcher servlet dispatcherServlet
  35. * 可能是springboot与cfx版本不兼容。
  36. * 同时在spring boot2.0.6之后的版本与xcf集成,不需要在定义以下方法,直接在application.properties配置文件中添加:
  37. * cxf.path=/service(默认是services)
  38. */
  39. // @Bean
  40. // public ServletRegistrationBean dispatcherServlet() {
  41. // return new ServletRegistrationBean(new CXFServlet(), "/soap/*");
  42. // }
  43. @Bean
  44. public Endpoint endpoint() {
  45. EndpointImpl endpoint = new EndpointImpl(springBus(), serverServiceDemo);
  46. endpoint.publish("/ws/api");
  47. return endpoint;
  48. }
  49. }

然后我在aplication.yml文件中添加了配置信息(非必要)

cxf:
  path: /service

这个是Student类

  1. package com.mango.jkm.webservice;
  2. import java.io.Serializable;
  3. import javax.xml.bind.annotation.XmlAccessType;
  4. import javax.xml.bind.annotation.XmlAccessorType;
  5. import javax.xml.bind.annotation.XmlRootElement;
  6. import javax.xml.bind.annotation.XmlType;
  7. @XmlRootElement(name="Student")
  8. @XmlAccessorType(XmlAccessType.FIELD)
  9. @XmlType(propOrder={"name", "address","age"})
  10. public class Student implements Serializable {
  11. /**
  12. *
  13. */
  14. private static final long serialVersionUID = 3428504463675931746L;
  15. public String name;
  16. public String address;
  17. public String age;
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. public String getAddress() {
  25. return address;
  26. }
  27. public void setAddress(String address) {
  28. this.address = address;
  29. }
  30. public String getAge() {
  31. return age;
  32. }
  33. public void setAge(String age) {
  34. this.age = age;
  35. }
  36. @Override
  37. public String toString() {
  38. return "#" + this.name + "#";
  39. }
  40. }

 然后,启动springboot,访问对应的地址http://localhost:8081/service/ws/api?wsdl,得到熟悉的界面,可以看到webservice也启动成功了(webservice的端口号就是springboot项目自己的端口号)

然后,可以用soupui工具进行访问,

 

点击ok,就可以看到在接口文件中定义的4个方法

点击里面的emrService节点的request1,进行测试,可以看到返回数据结果

 

我感觉webservice也是post方式接口,因为我用apipost工具进行测试,body里放左侧的请求的xml,得到完全相同的的结果,为了验证我的猜想,我用springboot自带的RestTemplate类发送了一次post请求,发现也是得到了右侧的返回内容,这是我的测试类

  1. package com.mango.jkm.webservice;
  2. import javax.xml.namespace.QName;
  3. import javax.xml.rpc.ParameterMode;
  4. import javax.xml.rpc.encoding.XMLType;
  5. import org.apache.axis.client.Call;
  6. import org.apache.axis.client.Service;
  7. import org.apache.axis.encoding.ser.BeanDeserializerFactory;
  8. import org.apache.axis.encoding.ser.BeanSerializerFactory;
  9. import org.springframework.http.HttpEntity;
  10. import org.springframework.http.HttpHeaders;
  11. import org.springframework.http.MediaType;
  12. import org.springframework.http.ResponseEntity;
  13. import org.springframework.web.client.RestTemplate;
  14. import com.alibaba.fastjson.JSONObject;
  15. public class WbClient {
  16. public static void invokeService3() {
  17. try {
  18. //1、直接引用远程的wsdl文件
  19. String endpoint = "http://localhost:8081/service/ws/api?wsdl";
  20. Service service = new Service();
  21. Call call = (Call) service.createCall(); //创建服务
  22. call.setTargetEndpointAddress(endpoint);
  23. //2、定义报名和接口方法
  24. QName qn=new QName("http://server.webservice.example.com", //wsdl文件中的targetNamespace
  25. "aboutstudent");
  26. call.setOperationName(qn);
  27. //3、设置参数
  28. Student student=new Student();
  29. student.setName("张小鑫");
  30. student.setAddress("sssss");
  31. student.setAge("10");
  32. call.registerTypeMapping(Student.class,qn,
  33. new BeanSerializerFactory(Student.class, qn),
  34. new BeanDeserializerFactory(Student.class, qn));
  35. call.addParameter("student",
  36. new QName("http://server.webservice.example.com", "Student"), javax.xml.rpc.ParameterMode.IN);
  37. // call.addParameter("student", org.apache.axis.encoding.XMLType.XSD_ANYTYPE,
  38. // javax.xml.rpc.ParameterMode.IN);//接口的参数
  39. call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//设置返回类型
  40. call.setUseSOAPAction(true);
  41. String result = (String)call.invoke(new Object[]{student});
  42. System.out.println("result="+result);
  43. } catch (Exception e) {
  44. e.printStackTrace();
  45. }
  46. }
  47. public static void invokeService_2(){
  48. try {
  49. //1、直接引用远程的wsdl文件
  50. String endpoint = "http://localhost:8081/service/ws/api?wsdl";
  51. Service service = new Service();
  52. Call call = (Call) service.createCall(); //创建服务
  53. call.setTargetEndpointAddress(endpoint);
  54. //2、定义报名和接口方法
  55. call.setOperationName(new QName("http://server.webservice.example.com", //wsdl文件中的targetNamespace
  56. "emrService") //接口实现功能的方法
  57. );
  58. //3、设置参数
  59. call.addParameter("data", XMLType.XSD_STRING,ParameterMode.IN);// 接口的参数
  60. call.addParameter("data2",XMLType.XSD_STRING,ParameterMode.IN);// 接口的参数
  61. call.setReturnType(XMLType.XSD_STRING);// 设置返回类型
  62. //4、给方法传递参数,并且调用方法
  63. String result = (String) call.invoke(new Object[] {"1111" ,"2222"});
  64. System.out.println("result="+result);
  65. } catch (Exception e) {
  66. e.printStackTrace();
  67. }
  68. //
  69. }
  70. public static void restfangwen() {
  71. RestTemplate restTemplate = new RestTemplate();
  72. HttpHeaders headers = new HttpHeaders();
  73. headers.setContentType(MediaType.APPLICATION_XML);
  74. String xml="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://server.webservice.example.com\">\r\n"
  75. + " <soapenv:Header/>\r\n"
  76. + " <soapenv:Body>\r\n"
  77. + " <ser:aboutstudent>\r\n"
  78. + " <!--Optional:-->\r\n"
  79. + " <student>\r\n"
  80. + " <!--Optional:-->\r\n"
  81. + " <name>zx</name>\r\n"
  82. + " <!--Optional:-->\r\n"
  83. + " <address>address</address>\r\n"
  84. + " <!--Optional:-->\r\n"
  85. + " <age>18</age>\r\n"
  86. + " </student>\r\n"
  87. + " </ser:aboutstudent>\r\n"
  88. + " </soapenv:Body>\r\n"
  89. + "</soapenv:Envelope>";
  90. HttpEntity requestEntity = new HttpEntity<>(xml, headers);
  91. ResponseEntity<String> resEntity = restTemplate.postForEntity("http://localhost:8081/service/ws/api",
  92. requestEntity, String.class);
  93. String result=resEntity.getBody();
  94. System.out.println("str="+result);
  95. }
  96. public static void main(String[] args) {
  97. WbClient.restfangwen();
  98. }
  99. }

 在这个测试类中,我访问的是webservice里的aboutstudent方法,能得到对应的返回内容

str=<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:aboutstudentResponse xmlns:ns2="http://server.webservice.example.com"><return>student.getName()=zx</return></ns2:aboutstudentResponse></soap:Body></soap:Envelope>

用axis能访问emrService方法,并且返回正确的数据。如果输入参数不是java基本类型而是类的话,怎么弄都不好使,网上各种办法都不好使,我也不知道为啥。各位大神如果你们成功了,就请在留言区说一下,小弟不胜感激。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/53895
推荐阅读
相关标签
  

闽ICP备14008679号