• SpringBoot项目添加WebService服务


    1.简单描述

    WebService简单理解就是用http发送接收xml数据,但这个xml得遵守系统的规范。这个规范就是WSDL(Web服务描述语言,Web Services Description Language)。

    在WebService中传输的xml有一个正式的名称叫Soap(简单对象访问协议 Simple Object Access Protocol)。

    WebService分为客户端和服务端。这两个都可以做数据源提供数据,比如说客户端发送大量数据给服务端,服务端接收大量数据。也可以是客户端发起请求获取服务端提供的大量数据。所有谁生产谁消费这事对Webservice不必纠结。

    2.代码实现

    SpringBoot项目中还是推荐使用注解的方式实现WebService,这样比较优雅。

    1.首先要引入大量的依赖。目前部分jar可能有漏斗,如果项目对安全有较高的要求请引入没有漏洞版本的jar

    1. <!-- webService依赖-->
    2. <dependency>
    3. <groupId>org.apache.cxf</groupId>
    4. <artifactId>cxf-core</artifactId>
    5. <version>${cxf-core.version}</version>
    6. </dependency>
    7. <dependency>
    8. <groupId>org.apache.cxf</groupId>
    9. <artifactId>cxf-rt-frontend-jaxws</artifactId>
    10. <version>${cxf-core.version}</version>
    11. </dependency>
    12. <dependency>
    13. <groupId>org.apache.cxf</groupId>
    14. <artifactId>cxf-rt-transports-http-jetty</artifactId>
    15. <version>${cxf-core.version}</version>
    16. </dependency>
    17. <dependency>
    18. <groupId>org.apache.cxf</groupId>
    19. <artifactId>cxf-rt-transports-http</artifactId>
    20. <version>${cxf-core.version}</version>
    21. </dependency>
    22. <dependency>
    23. <groupId>org.springframework.boot</groupId>
    24. <artifactId>spring-boot-starter-web-services</artifactId>
    25. <version>2.7.0</version>
    26. </dependency>
    27. <dependency>
    28. <groupId>org.apache.cxf</groupId>
    29. <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
    30. <version>${cxf-core.version}</version>
    31. </dependency>
    32. <dependency>
    33. <groupId>com.sun.xml.ws</groupId>
    34. <artifactId>jaxws-ri</artifactId>
    35. <version>2.3.5</version>
    36. <type>pom</type>
    37. </dependency>
    38. <!-- https://mvnrepository.com/artifact/org.apache.cxf.services/cxf-services -->
    39. <dependency>
    40. <groupId>org.apache.cxf.services</groupId>
    41. <artifactId>cxf-services</artifactId>
    42. <version>3.4.3</version>
    43. <type>pom</type>
    44. </dependency>
    45. <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-bindings-soap -->
    46. <dependency>
    47. <groupId>org.apache.cxf</groupId>
    48. <artifactId>cxf-rt-bindings-soap</artifactId>
    49. <version>${cxf-core.version}</version>
    50. </dependency>
    51. <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-api -->
    52. <dependency>
    53. <groupId>org.apache.cxf</groupId>
    54. <artifactId>cxf-api</artifactId>
    55. <version>2.7.18</version>
    56. </dependency>

    接着实现服务器端的代码

    服务器端的代码有两部分一部分是WebService接口,一部分是发布WebService的配置类

    接口定义(规范WSDL)

    1. import javax.jws.WebMethod;
    2. import javax.jws.WebParam;
    3. import javax.jws.WebService;
    4. /**
    5. * Webservice 发送数据
    6. * @author dhh
    7. */
    8. @WebService(serviceName = "WebServiceSender",
    9. targetNamespace="http://service.rebate.modules.jeecg.org/",
    10. endpointInterface = "org.jeecg.modules.rebate.service.WebServiceServer")
    11. public interface WebServiceServer {
    12. @WebMethod(operationName = "Invoke")
    13. void invoke(@WebParam(name="from",targetNamespace = "http://service.rebate.modules.jeecg.org/")String from,
    14. @WebParam(name="token",targetNamespace = "http://service.rebate.modules.jeecg.org/")String token,
    15. @WebParam(name="funcName",targetNamespace = "http://service.rebate.modules.jeecg.org/")String funcName,
    16. @WebParam(name="parameters",targetNamespace = "http://service.rebate.modules.jeecg.org/")String parameters) throws Exception;
    17. }

    实现类(接收到请求后服务器端做处理)

    1. import lombok.extern.slf4j.Slf4j;
    2. import org.jeecg.modules.rebate.service.WebServiceServer;
    3. import org.springframework.stereotype.Service;
    4. /**
    5. * @author dhh
    6. */
    7. @Slf4j
    8. @Service
    9. public class WebServiceSenderServiceImpl implements WebServiceServer {
    10. @Override
    11. public void invoke(String from, String token, String funcName, String parameters) throws Exception {
    12. if("数据来源".equals(from)){
    13. switch (funcName) {
    14. }
    15. }else{
    16. log.info("未知来源的数据{},禁止写入!",from);
    17. throw new Exception("未知来源的数据,禁止写入");
    18. }
    19. }
    20. }

    配置类(发布服务)

    1. import org.apache.cxf.jaxws.EndpointImpl;
    2. import org.apache.cxf.Bus;
    3. import org.apache.cxf.bus.spring.SpringBus;
    4. import org.apache.cxf.phase.Phase;
    5. import org.apache.cxf.transport.servlet.CXFServlet;
    6. import org.jeecg.modules.rebate.service.WebServiceServer;
    7. import org.jeecg.modules.rebate.service.impl.WebServiceSenderServiceImpl;
    8. import org.springframework.boot.web.servlet.ServletRegistrationBean;
    9. import org.springframework.context.annotation.Bean;
    10. import org.springframework.context.annotation.Configuration;
    11. import javax.xml.ws.Endpoint;
    12. /**
    13. * @author dhh
    14. */
    15. @Configuration
    16. public class WebServiceConfig {
    17. @Bean(name = "cxfServlet") // 注入servlet bean name不能dispatchlet ,否则会覆盖dispatcherServlet
    18. public ServletRegistrationBean<CXFServlet> cxfServlet() {
    19. return new ServletRegistrationBean<CXFServlet>(new CXFServlet(), "/webservice/*");
    20. }
    21. @Bean
    22. public WebServiceServer webServiceSender() {
    23. return new WebServiceSenderServiceImpl();
    24. }
    25. @Bean(name = Bus.DEFAULT_BUS_ID)
    26. public SpringBus springBus() {
    27. return new SpringBus();
    28. }
    29. @Bean
    30. public Endpoint endpoint() {
    31. // 参数二,是SEI实现类对象
    32. EndpointImpl endpoint = new EndpointImpl(this.springBus(),this.webServiceSender());
    33. // 发布服务
    34. endpoint.publish("/server");
    35. return endpoint;
    36. }
    37. }

    接下来启动项目访问/webservice/server?wsdl 就可以看看WSDL的内容了。

    然后搭建客户端

    客户端搭建很简单,就是用http发送一个xml,困难在xml数据的格式要遵守服务端定义的wsdl要求。比如命名空间要和服务端的一致(http://service.rebate.modules.jeecg.org/),参数数量和名称也要和服务端定义的一致方可

    1. import lombok.extern.slf4j.Slf4j;
    2. import org.dom4j.Document;
    3. import org.dom4j.DocumentException;
    4. import org.dom4j.DocumentHelper;
    5. import org.dom4j.Element;
    6. import org.jeecg.modules.rebate.bean.WebServiceRequest;
    7. import org.jeecg.modules.rebate.entity.AttachmentInfo;
    8. import org.jeecg.modules.rebate.entity.ProjectInfo;
    9. import org.jeecg.modules.rebate.entity.ProjectScope;
    10. import org.jeecg.modules.rebate.service.WebServiceClientService;
    11. import org.springframework.stereotype.Service;
    12. import java.io.*;
    13. import java.net.HttpURLConnection;
    14. import java.net.URL;
    15. import java.nio.charset.StandardCharsets;
    16. import java.util.List;
    17. import java.util.Map;
    18. /**
    19. * @author dhh
    20. */
    21. @Slf4j
    22. @Service
    23. public class WebServiceClientServiceImpl implements WebServiceClientService {
    24. /**
    25. * 发送请求,发送请求时,将数据封装起来
    26. */
    27. @Override
    28. public String send(WebServiceRequest request, String xmlEntry) {
    29. try {
    30. URL url = new URL(request.getRequestUrl());
    31. HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    32. connection.setRequestMethod("POST");
    33. connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
    34. connection.setDoOutput(true);
    35. connection.setDoInput(true);
    36. String xml = this.requestXmlBuilder(request.getEsbCode(), request.getComp(),request.getFrom(),request.getToken(), request.getFuncName(), xmlEntry);
    37. connection.setRequestProperty("Content-Length",String.valueOf(xml.length()));
    38. OutputStream out = connection.getOutputStream();
    39. out.write(xml.getBytes(StandardCharsets.UTF_8));
    40. int responseCode = connection.getResponseCode();
    41. if(responseCode==200){
    42. InputStream in = connection.getInputStream();
    43. String result = getResult(in);
    44. log.info(result);
    45. return result;
    46. }
    47. } catch (IOException e) {
    48. log.error(e.getMessage());
    49. }
    50. return "ERROR";
    51. }

    这里我将构建xml单独写了一个方法,可以根据服务端WSDL规范自行定义

    1. private String requestXmlBuilder(String esbCode,String COMP,String from ,String token,String funcName,String xml){
    2. StringBuffer buffer= new StringBuffer();
    3. buffer.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:boi=\"http://service.rebate.modules.jeecg.org/\">");
    4. buffer.append("<soapenv:Header>");
    5. buffer.append("<extraParams>");
    6. buffer.append("<esbCode>");
    7. // esbCode:数据
    8. buffer.append(esbCode);
    9. buffer.append("</esbCode>");
    10. buffer.append("<COMP>");
    11. // COMP:数据
    12. buffer.append(COMP);
    13. buffer.append("</COMP>");
    14. buffer.append("</extraParams>");
    15. buffer.append("</soapenv:Header>");
    16. buffer.append("<soapenv:Body>");
    17. buffer.append("<boi:Invoke>");
    18. buffer.append("<boi:from>");
    19. buffer.append(from);
    20. buffer.append("</boi:from>");
    21. buffer.append("<boi:token>");
    22. buffer.append(token);
    23. buffer.append("</boi:token>");
    24. buffer.append("<boi:funcName>");
    25. // funcName:数据
    26. buffer.append(funcName);
    27. buffer.append("</boi:funcName>");
    28. buffer.append("<boi:parameters><![CDATA[");
    29. // XML:数据
    30. buffer.append(xml);
    31. buffer.append("]]></boi:parameters>");
    32. buffer.append("</boi:Invoke>");
    33. buffer.append("</soapenv:Body>");
    34. buffer.append("</soapenv:Envelope>");
    35. return buffer.toString();
    36. }

    后面直接调用客户端方法请求本地服务端就可以测试客户端了,以上结束。

    参考连接:webservice关于入参掉用各种报错信息及解决方法汇总org.apache.cxf.interceptor.Fault: Unmarshalling Error: 意外的元素...... - 走看看

    实例篇——webservice实现互相传递数据 - 走看看 

    Apache CXF -- Developing a Service 

    后面还有拦截器的用法,感兴趣的可以了解一下!

  • 相关阅读:
    【Unity编辑器扩展】GF_HybridCLR自定义Toolbar, 一键出包/打热更扩展工具
    vsCode Mac版 配置C/C++,并运行代码
    第56章 业务逻辑之物流/配送实体定义
    .bss (the block starting symbol)
    Linux的基本权限
    Default Probability
    Java中的Optional
    计算机毕业设计之java+ssm基于web的农业信息管理系统
    ## 其它问题
    NewStarCTF2023week2-R!!C!!E!!
  • 原文地址:https://blog.csdn.net/weixin_43493089/article/details/125523527