【Springboot整合系列】SpringBoot整合WebService

目录

  • Web服务介绍
    • Web服务的两种类型
    • Web服务架构
    • Web服务的主要特点
    • Web服务使用场景
    • Web服务标准和技术
  • WebService介绍
  • WebService的作用
    • 适用场景
    • 不适用场景
  • WebService的原理
    • 三个角色
    • 相关概念
  • WebService开发框架
    • 代码实现
      • 服务端
        • 1.引入依赖
        • 2.实体类
        • 3.业务层
          • 接口
          • 接口实现类
        • 4.配置类
        • 5.拦截器
        • 6.启动
      • 客户端
        • 1.引入依赖
        • 2.拦截器
        • 3.实体类
        • 4.调用类
        • 5.接口测试
      • 遇到的问题

Web服务介绍

Web服务的两种类型

  • SOAP Web服务:基于SOAP(Simple Object Access Protocol)协议的Web服务。SOAP是一种用于交换结构化信息的协议,它使用XML作为消息格式,并通常通过HTTP协议进行传输。
  • RESTful Web服务:基于REST(Representational State Transfer)原则的Web服务。RESTful服务使用标准的HTTP方法(如GET、POST、PUT、DELETE)来执行操作,并通常返回JSON或XML格式的数据。

Web服务架构

Web服务的架构通常包括以下关键组件:

  • 服务提供者(Service Provider):提供Web服务的实体。它们发布服务并处理来自客户端的请求。
  • 服务请求者(Service Requestor):使用Web服务的客户端应用程序。它们向服务提供者发送请求并处理响应。
  • 服务描述(Service Description):Web服务的描述文件,通常使用WSDL(Web Services Description Language)或OpenAPI等格式来描述服务的接口和操作。
  • 消息格式(Message Format):Web服务使用的数据交换格式,通常是XML或JSON。
  • 通信协议(Communication Protocol):Web服务之间通信的协议,常见的包括HTTP、HTTPS、SMTP等。

Web服务的主要特点

  • 跨平台性(Platform Independence):由于Web服务使用标准化的协议和数据格式,因此它们可以在不同的平台和操作系统上运行。
  • 松耦合(Loose Coupling):Web服务通过标准化接口进行通信,服务提供者和请求者之间的耦合度较低,可以独立开发和部署。
  • 可组合性(Composability):可以通过组合多个Web服务来创建复杂的应用程序。
  • 可重用性(Reusability):Web服务可以被多个应用程序重复使用,从而提高了软件开发效率。
  • 易于维护(Maintainability):由于Web服务使用标准化的接口和协议,因此易于维护和更新。

Web服务使用场景

Web服务在许多场景下都得到了广泛应用,包括但不限于:

  • 企业应用集成(Enterprise Application Integration,EAI):将不同的企业应用程序和系统集成在一起,实现数据和业务流程的无缝交互。
  • 分布式系统:构建分布式系统和服务导向架构(Service-Oriented Architecture,SOA),提供跨网络的服务和资源共享。
  • 移动应用程序开发:通过Web服务为移动应用程序提供数据和功能支持,与后端服务器进行通信和交互。
  • 云计算:在云平台上部署和管理Web服务,提供云端服务和资源。

Web服务标准和技术

  • SOAP(Simple Object Access Protocol):用于构建基于XML的Web服务的协议。
  • WSDL(Web Services Description Language):用于描述Web服务的接口和操作的XML格式的语言。
  • UDDI(Universal Description, Discovery, and Integration):用于注册和发现Web服务的协议和规范。
  • REST(Representational State Transfer):一种基于HTTP协议的软件架构风格,用于构建RESTful Web服务。
  • JSON(JavaScript Object Notation):一种轻量级的数据交换格式,通常用于RESTful Web服务的数据格式。

WebService介绍

  • WebService是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于Http协议的网络应用间的交互。
  • 其实WebService并不是什么神秘的东西,它就是一个可以远程调用的类,或者说是组件,把你本地的功能开放出去共别人调用。
  • 具体的说,Web Service可以让你的网站使用其他网站的资源,比如在网页上显示天气、地图、twitter上的最新动态等等。

WebService的作用

比如你的项目需要查询某银行账户余额。你能直接查吗,肯定不行,因为数据库是银行的,他不可能给你权限。你想访问他的数据库获取数据,这就需要用到WebService。通过调用银行暴露的接口来得到你想要的数据。

适用场景

  • 软件的集成和复用,如气象局(服务端系统)、天气查询网站等。
    • 发布一个服务(对内/对外),不考虑客户端类型,不考虑性能,建议WebService
    • 服务端已经确定使用webservice,客户端不能选择,必须使用WebService
  • 软件集成即通过远程调用技术,将两个系统整合到一起,从而实现软件集成。
  • 软件复用即同一个款软件的多次集成,最终实现复用。
    在这里插入图片描述

不适用场景

  • 考虑性能时不建议使用WebService:采用xml格式封装数据,所以在传输过程中,要传输额外的标签,随着soap协议的不断完善,标签越来越大,导致webservice的性能下降。
  • 同构程序下不建议使用webservice,比如java 用RMI,不需要翻译成XML的数据。

WebService的原理

三个角色

在Web Service的体系架构中有三个角色:服务提供者(Service Provider),也叫服务生产者;服务请求者(Service Requester),也叫服务消费者;服务注册中心(Service Register),也叫服务代理,服务提供者在这里发布服务,服务请求者在这里查找服务,获取服务的绑定信息。

  • 发布(Publish),服务提供者把服务按照规范格式发布到服务注册中心;
  • 查找(Find),服务请求者根据服务注册中心提供的规范接口发出查找请求,获取绑定服务所需的相关信息。
  • 绑定(Bind),服务请求者根据服务绑定信息对自己的系统进行配置,从而可以调用服务提供者提供的服务。

在这里插入图片描述

相关概念

Web Service的实现是通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI进行注册。

  • XML:(Extensible Markup Language)扩展型可标记语言。面向短期的临时数据处理、面向万维网络,是SOAP的基础。
  • SOAP:(Simple Object Access Protocol)简单对象存取协议。是XML Web Service 的通信协议。当用户通过UDDI找到你的WSDL描述文档后,他通过可以SOAP调用你建立的Web服务中的一个或多个操作。SOAP是XML文档形式的调用方法的规范,它可以支持不同的底层接口,像HTTP(S)或者SMTP。
  • WSDL:(Web Services Description Language) WSDL 文件是一个 XML 文档,用于说明一组 SOAP 消息以及如何交换这些消息。大多数情况下由软件自动生成和使用。
  • UDDI (Universal Description, Discovery, and Integration) 是一个主要针对Web服务供应商和使用者的新项目。在用户能够调用Web服务之前,必须确定这个服务内包含哪些商务方法,找到被调用的接口定义,还要在服务端来编制软件,UDDI是一种根据描述文档来引导系统查找相应服务的机制。UDDI利用SOAP消息机制(标准的XML/HTTP)来发布,编辑,浏览以及查找注册信息。它采用XML格式来封装各种不同类型的数据,并且发送到注册中心或者由注册中心来返回需要的数据。

WebService开发框架

  • WebService服务端是以远程接口为主的,在Java实现的WebService技术里主要依靠CXF开发框架,而这个CXF开发框架可以直接将接口发布成WebService。
  • CXF又分为JAX-WS和JAX-RS,JAX-WS是基于xml协议,而JAX-RS是基于Restful风格,两者的区别如下:
    • RS基于Restful风格,WS基于SOAP的XML协议
    • RS比WS传输的数据更少,效率更高
    • WS只能传输XML数据,RS可以传输XML,也可以传输JSON

代码实现

服务端

1.引入依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>


        <!-- apache-cxf -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.1.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.1.6</version>
        </dependency>

       <!-- apache-cxf  此处与上处二选其一 -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.5.2</version>
        </dependency>
2.实体类
package com.cxf.pojo;

import lombok.*;
import lombok.experimental.Accessors;

import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;

/**
 * @author: zjl
 * @datetime: 2024/3/29
 * @desc:
 */
@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XmlRootElement
@Accessors(chain = true)
public class UserInfo implements Serializable {

    private static final long serialVersionUID = 1L;
    private Long id;
    private String username;
    private String password;
}
3.业务层
接口
package com.cxf.service;

import com.cxf.pojo.UserInfo;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService(name = "userInfoService", targetNamespace = "http://server.service.cxf.com")
public interface UserInfoService {

    @WebMethod(operationName = "saveUserInfo")
    void saveUserInfo(@WebParam(name = "userInfo") UserInfo userInfo);

    @WebMethod
    UserInfo getUserInfoById(@WebParam(name = "id") Long id);
}
接口实现类
package com.cxf.service;

import com.alibaba.fastjson.JSON;
import com.cxf.pojo.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.jws.WebService;

/**
 * WebService涉及到的有这些 "四解三类 ", 即四个注解,三个类
 * @WebMethod
 * @WebService
 * @WebResult
 * @WebParam
 * SpringBus
 * Endpoint
 * EndpointImpl
 *
 * 一般我们都会写一个接口,然后再写一个实现接口的实现类,但是这不是强制性的
 * @WebService 注解表明是一个webservice服务。
 *      name:对外发布的服务名, 对应于<wsdl:portType name="ServerServiceDemo"></wsdl:portType>
 *      targetNamespace:命名空间,一般是接口的包名倒序, 实现类与接口类的这个配置一定要一致这种错误
 *              Exception in thread "main" org.apache.cxf.common.i18n.UncheckedException: No operation was found with the name xxxx
 *              对应于targetNamespace="http://server.webservice.example.com"
 *      endpointInterface:服务接口全路径(如果是没有接口,直接写实现类的,该属性不用配置), 指定做SEI(Service EndPoint Interface)服务端点接口
 *      serviceName:对应于<wsdl:service name="ServerServiceDemoImplService"></wsdl:service>
 *      portName:对应于<wsdl:port binding="tns:ServerServiceDemoImplServiceSoapBinding" name="ServerServiceDemoPort"></wsdl:port>
 *
 * @WebMethod 表示暴露的服务方法, 这里有接口ServerServiceDemo存在,在接口方法已加上@WebMethod, 所以在实现类中不用再加上,否则就要加上
 *      operationName: 接口的方法名
 *      action: 没发现又什么用处
 *      exclude: 默认是false, 用于阻止将某一继承方法公开为web服务
 *
 * @WebResult 表示方法的返回值
 *      name:返回值的名称
 *      partName:
 *      targetNamespace:
 *      header: 默认是false, 是否将参数放到头信息中,用于保护参数,默认在body中
 *
 * @WebParam
 *       name:接口的参数
 *       partName:
 *       targetNamespace:
 *       header: 默认是false, 是否将参数放到头信息中,用于保护参数,默认在body中
 *       model:WebParam.Mode.IN/OUT/INOUT
 */
@Service
@WebService(serviceName = "userInfoService", targetNamespace = "http://server.webservice.gtp.sinotrans.com", endpointInterface = "com.sinotrans.gtp.webservice.UserInfoService")
@Slf4j
public class UserInfoServiceImpl implements UserInfoService {
    @Override
    public void saveUserInfo(UserInfo userInfo) {
        System.out.println("保存用户信息成功" + userInfo.toString());
    }

    @Override
    public UserInfo getUserInfoById(Long id) {
        UserInfo zhangsan = UserInfo.builder().id(1L).username("zhangsan").password("123456").build();
        log.info(JSON.toJSONString(zhangsan));
        return zhangsan;
    }
}
4.配置类
package com.cxf.config;

import com.cxf.interceptor.WebServiceAuthInterceptor;
import com.cxf.service.UserInfoService;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.xml.ws.Endpoint;

/**
 * @author: zjl
 * @datetime: 2024/3/29
 * @desc:
 */
@Configuration
public class WebServiceConfig {

    @Resource
    private UserInfoService userInfoService;

/*    @Resource
    private AgeInfoService ageInfoService;*/
/*    @Resource
    private WebServiceAuthInterceptor interceptor;*/

    /**
     * Apache CXF 核心架构是以BUS为核心,整合其他组件。
     * Bus是CXF的主干, 为共享资源提供一个可配置的场所,作用类似于Spring的ApplicationContext,这些共享资源包括
     * WSDl管理器、绑定工厂等。通过对BUS进行扩展,可以方便地容纳自己的资源,或者替换现有的资源。默认Bus实现基于Spring架构,
     * 通过依赖注入,在运行时将组件串联起来。BusFactory负责Bus的创建。默认的BusFactory是SpringBusFactory,对应于默认
     * 的Bus实现。在构造过程中,SpringBusFactory会搜索META-INF/cxf(包含在 CXF 的jar中)下的所有bean配置文件。
     * 根据这些配置文件构建一个ApplicationContext。开发者也可以提供自己的配置文件来定制Bus。
     */
    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        return new SpringBus();
    }

    /**
     * 设置WebService访问父路径
     * <p>
     * 此方法作用是改变项目中服务名的前缀名,此处127.0.0.1或者localhost不能访问时,请使用ipconfig查看本机ip来访问
     * 此方法被注释后, 即不改变前缀名(默认是services), wsdl访问地址为 http://127.0.0.1:8080/services/ws/api?wsdl
     * 去掉注释后wsdl访问地址为:http://127.0.0.1:8080/webServices/ws/api?wsdl
     * http://127.0.0.1:8080/soap/列出服务列表 或 http://127.0.0.1:8080/soap/ws/api?wsdl 查看实际的服务
     * 新建Servlet记得需要在启动类添加注解:@ServletComponentScan
     * 如果启动时出现错误:not loaded because DispatcherServlet Registration found non dispatcher servlet dispatcherServlet
     * 可能是springboot与cfx版本不兼容。
     * 同时在spring boot2.0.6之后的版本与xcf集成,不需要在定义以下方法,直接在application.properties配置文件中添加:
     * cxf.path=/service(默认是services)
     */
    @Bean
    public ServletRegistrationBean getRegistrationBean() {
        return new ServletRegistrationBean(new CXFServlet(), "/webServices/*");
    }

    @Bean
    public Endpoint messageEndPoint() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), this.userInfoService);
        endpoint.publish("/userInfoService");
//        endpoint.getInInterceptors().add(this.interceptor);
        return endpoint;
    }

    /*用于发布多个WebService*/
//    @Bean
//    public Endpoint messageEndPoint2() {
//        EndpointImpl endpoint = new EndpointImpl(springBus(), this.ageInfoService);
//        endpoint.publish("/userInfoService");
//        endpoint.getInInterceptors().add(this.interceptor);
//        return endpoint;
//    }
}
5.拦截器
package com.cxf.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.springframework.stereotype.Component;
import org.w3c.dom.NodeList;

import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;

/**
 * @author: zjl
 * @datetime: 2024/3/29
 * @desc:
 */
@Component
@Slf4j
public class WebServiceAuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

    /**
     * 用户名
     */
    private static final String USER_NAME = "kgc";
    /**
     * 密码
     */
    private static final String USER_PASSWORD = "kgc.com";
    private static final String NAME_SPACE_URI = "http://server.service.cxf.com";
    /**
     * 创建拦截器
     */
    private SAAJInInterceptor interceptor = new SAAJInInterceptor();

    public WebServiceAuthInterceptor() {
        super(Phase.PRE_PROTOCOL);
        //添加拦截
        super.getAfter().add(SAAJInInterceptor.class.getName());
    }

    @Override
    public void handleMessage(SoapMessage message) throws Fault {
        //获取指定消息
        SOAPMessage soapMessage = message.getContent(SOAPMessage.class);
        if (null == soapMessage) {
            this.interceptor.handleMessage(message);
            soapMessage = message.getContent(SOAPMessage.class);
        }
        //SOAP头信息
        SOAPHeader header = null;
        try {
            header = soapMessage.getSOAPHeader();
        } catch (SOAPException e) {
            e.printStackTrace();
        }
        if (null == header) {
            throw new Fault(new IllegalAccessException("没有Header信息,无法实现用户认证处理!"));
        }
        //SOAP是基于XML文件结构进行传输的,所以如果要想获取认证信息就必须进行相关的结构约定
        NodeList usernameNodeList = header.getElementsByTagNameNS(NAME_SPACE_URI, "username");
        NodeList passwordNodeList = header.getElementsByTagNameNS(NAME_SPACE_URI, "password");
        if (usernameNodeList.getLength() < 1) {
            throw new Fault(new IllegalAccessException("没有用户信息,无法实现用户认证处理!"));
        }
        if (passwordNodeList.getLength() < 1) {
            throw new Fault(new IllegalAccessException("没有密码信息,无法实现用户认证处理!"));
        }
        String username = usernameNodeList.item(0).getTextContent().trim();
        String password = passwordNodeList.item(0).getTextContent().trim();
        if (USER_NAME.equals(username) && USER_PASSWORD.equals(password)) {
            log.info("用户访问认证成功!");
        } else {
            SOAPException soapException = new SOAPException("用户认证失败!");
            log.info("用户认证失败!");
            throw new Fault(soapException);
        }
    }
}
6.启动
http://localhost:8080/webServices/

在这里插入图片描述点击链接可以查看到具体的接口信息
在这里插入图片描述

客户端

1.引入依赖
		<dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws
            </artifactId>
            <version>3.5.2</version>
        </dependency>
        <!-- 添加 FastJSON依赖 -->
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.9</version>
        </dependency>
2.拦截器
package com.cxf.interceptor;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.headers.Header;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import java.util.List;

/**
 * @author: zjl
 * @datetime: 2024/3/29
 * @desc:
 */
public class ClientLoginInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

    private String username;
    private String password;
    private static final String NAME_SPACE_URI = "http://server.service.cxf.com";

    public ClientLoginInterceptor(String username, String password) {
        super(Phase.PREPARE_SEND);
        this.username = username;
        this.password = password;
    }

    @Override
    public void handleMessage(SoapMessage soapMessage) throws Fault {
        List<Header> headers = soapMessage.getHeaders();
        Document document = DOMUtils.createDocument();
        Element authority = document.createElementNS(NAME_SPACE_URI, "authority");
        Element username = document.createElementNS(NAME_SPACE_URI, "username");
        Element password = document.createElementNS(NAME_SPACE_URI, "password");
        username.setTextContent(this.username);
        password.setTextContent(this.password);
        authority.appendChild(username);
        authority.appendChild(password);
        headers.add(0, new Header(new QName("authority"), authority));
    }
}
3.实体类
package com.cxf.pojo;

import lombok.*;
import lombok.experimental.Accessors;

import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;

/**
 * @author: zjl
 * @datetime: 2024/3/29
 * @desc:
 */
@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XmlRootElement
@Accessors(chain = true)
public class UserInfo implements Serializable {

    private static final long serialVersionUID = 1L;
    private Long id;
    private String username;
    private String password;
}
4.调用类
package com.cxf.webservice;

import com.cxf.interceptor.ClientLoginInterceptor;
import com.cxf.pojo.UserInfo;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.springframework.stereotype.Component;

/**
 * @author: zjl
 * @datetime: 2024/3/29
 * @desc:
 */
@Component
public class UserInfoApiClient {

    private static final String USERNAME = "kgc";
    private static final String PASSWORD = "kgc.com";
    private static final String ADDRESS = "http://localhost:8080/webServices/userInfoService?wsdl";

    /**
     * 使用动态代理
     * @param id
     * @throws Exception
     */
    public String getUserInfoByIdWithDynamic(Long id) throws Exception {
        JaxWsDynamicClientFactory clientFactory = JaxWsDynamicClientFactory.newInstance();
        Client client = clientFactory.createClient(ADDRESS);
        client.getOutInterceptors().add(new ClientLoginInterceptor(USERNAME, PASSWORD));
        Object[] userInfos = client.invoke("getUserInfoById", id);
        String userInfo = JSON.toJSONString(userInfos[0]);
        System.out.println(JSON.toJSON(userInfo));
        return userInfo;
    }
}
5.接口测试
package com.cxf.controller;

import com.cxf.webservice.UserInfoApiClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author: zjl
 * @datetime: 2024/3/29
 * @desc:
 */
@RestController
public class UserInfoController {
    @Resource
    private UserInfoApiClient userInfoApiClient;
    @RequestMapping("/test")
    public Object getUserInfoById(Long id) throws Exception {
        return userInfoApiClient.getUserInfoByIdWithDynamic(1L);
    }
}

在这里插入图片描述

遇到的问题

Unable to create schema compiler] with root cause

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: Unable to create schema compiler] with root cause

java.lang.ClassNotFoundException: com/sun/tools/internal/xjc/api/XJC
	at java.base/java.lang.Class.forName0(Native Method) ~[na:na]
	at java.base/java.lang.Class.forName(Class.java:467) ~[na:na]
	at org.apache.cxf.common.jaxb.JAXBUtils.createSchemaCompiler(JAXBUtils.java:708) ~[cxf-core-3.5.2.jar:3.5.2]
	at org.apache.cxf.common.jaxb.JAXBUtils.createSchemaCompilerWithDefaultAllocator(JAXBUtils.java:722) ~[cxf-core-3.5.2.jar:3.5.2]
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createSchemaCompiler(DynamicClientFactory.java:447) ~[cxf-rt-frontend-simple-3.5.2.jar:3.5.2]
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:327) ~[cxf-rt-frontend-simple-3.5.2.jar:3.5.2]
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:245) ~[cxf-rt-frontend-simple-3.5.2.jar:3.5.2]
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:238) ~[cxf-rt-frontend-simple-3.5.2.jar:3.5.2]
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:192) ~[cxf-rt-frontend-simple-3.5.2.jar:3.5.2]
	at com.kgc.webservice.UserInfoApiClient.getUserInfoWithDynamic(UserInfoApiClient.java:19) ~[classes/:na]
	at com.kgc.controller.UserInfoController.getUserInfoById(UserInfoController.java:22) ~[classes/:na]

因为工程创建的时候是springBoot3.2.4,jdk17,我把SpringBoot和JDK版本都降低了然后写的代码,降低后的JDK是1.8,但是project中的sdk还是17,把sdk换成一致就可以了。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/509994.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

活动回顾丨掘金海外,探寻泛娱乐社交APP出海新风口

3月中旬,Flat Ads携手声网、XMP在广州成功举办“泛娱乐社交APP出海新风口——广州站”的主题线下沙龙活动。 多位大咖与泛娱乐社交APP赛道的行业伙伴汇聚一堂。本次活动邀请到Flat Ads 市场VP 王若策、声网娱乐视频产品负责人 陈际陶、XMP资深产品运营专家 屈俊星等多位行业大…

python ---- %r %s格式输出的区别

在python中&#xff0c; % s和 % r是我们常用的格式符&#xff0c;它们的用法基本一致&#xff0c;但作用却不尽相同&#xff0c;下面简要说明一下两者的区别&#xff1a; 1. % s是将对象 / 变量传递到str()方法中&#xff0c;并将其转化为面向用户的可阅读的格式。 2. % r是将…

ARM 寄存器学习:(前言)七种模式\异常源\向量表\异常返回

一、ARM的七种工作模式 Arm微处理器支持7种工作模式&#xff0c;分别为&#xff1a; 1&#xff0e; 用户模式&#xff08;Usr&#xff09; 用于正常执行程序 2&#xff0e; 系统模式&#xff08;sys&#xff09; 运行均有特权的操作系统任务 3&#…

既然有 HTTP 协议,为什么还要有 RPC?(计算机网络)

使用纯裸 TCP 会有什么问题 TCP 是有三个特点&#xff0c;面向连接、可靠、基于字节流。这里我们需要关注的是基于字节流这一点。 字节流可以理解为一个双向的通道里流淌的数据&#xff0c;这个数据其实就是我们常说的二进制数据&#xff0c;简单来说就是一大堆 01 串。纯裸 T…

物联网行业中,我们如何选择数据库?

在当今数字化潮流中&#xff0c;我们面对的不仅是海量数据&#xff0c;更是时间的涟漪。从生产线的传感器到金融市场的交易记录&#xff0c;时间序列数据成为了理解事物演变和趋势的关键。在面对这样庞大而动态的数据流时&#xff0c;我们需要深入了解一种强大的工具——时序数…

比torchvision更强大,从timm库引用预训练模型和本地加载的方法

1&#xff0c;介绍 torchvision是大家最常用的预训练模型来源&#xff0c;但是其包含的预训练模型种类很少&#xff0c;往往并不能满足研究者们的需求。 而timm库提供了一个更强大的替代选项。 利用如下代码查询 import timmprint(len(timm.list_models())) 输出 1032 可…

【C++】 vector <string> 的超详细解析!!!

目录 一、前言 二、 vector <string> 的个人理解和总结 三、vector <string> 的初始化 四、vector <string> 的输入 \ 输出 五、vector <string> 中的注意事项 六、常考面试题 七、共勉 一、前言 在【C】中&#xff0c;vector 是一个动态数组…

游戏开发各岗位的优势和劣势

在这个充满创意和技术的时代&#xff0c;游戏行业成为众多创新人才追求梦想的热土。对于那些准备踏入这个充满挑战与机遇的领域的新人来说&#xff0c;了解游戏开发的各个岗位及其独特性是至关重要的。游戏程序员、美术设计师和游戏策划——这三个核心岗位不仅构成了游戏创造的…

【SpringBoot整合系列】SpirngBoot整合EasyExcel

目录 背景需求发展 EasyExcel官网介绍优势常用注解 SpringBoot整合EaxyExcel1.引入依赖2.实体类定义实体类代码示例注解解释 3.自定义转换器转换器代码示例涉及的枚举类型 4.Excel工具类5.简单导出接口SQL 6.简单导入接口SQL 7.复杂的导出&#xff08;合并行、合并列&#xff0…

Maplesoft Maple 2024(数学科学计算)mac/win

Maplesoft Maple是一款强大的数学计算软件&#xff0c;提供了丰富的功能和工具&#xff0c;用于数学建模、符号计算、数据可视化等领域的数学分析和解决方案。 Mac版软件下载&#xff1a;Maplesoft Maple 2024 for mac激活版 WIn版软件下载&#xff1a;Maplesoft Maple 2024特别…

Kubernetes中pod的概念

pod pod是什么&#xff1a;pod是k8s中基本的构建模块&#xff0c;一个pod可以包含多个和单个容器&#xff0c;包含多个容器时&#xff0c;这些容器总是运行在同一个工作节点上&#xff0c;因为一个pod绝不会跨多个工作节点。 了解pod&#xff1a; pod将容器绑定在一起&#xf…

浅析扩散模型与图像生成【应用篇】(十五)——SDG

15. More Control for Free! Image Synthesis with Semantic Diffusion Guidance 该文提出一种基于语义引导扩散模型的的图像生成算法&#xff0c;SDG&#xff0c;可使用文本或图像作为引导来指引图像的生成&#xff0c;也可以二者同时使用&#xff0c;实现多模态的引导。增加引…

【Redis】Redis的类型及相关操作

一、常用的key操作命令 keys * 查看当前数据库的键值 ttl key 查看还有多少秒过期&#xff0c;-1表示永不过期&#xff0c;-2表示过期 del / unlink key 同样是删除&#xff0c;unlink是非阻塞删除&#xff0c;del则有可能导致阻塞 select dbindex 切换数据库 flushdb 清空…

微服务(基础篇-007-RabbitMQ部署指南)

目录 05-RabbitMQ快速入门--介绍和安装_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1LQ4y127n4?p65&vd_source60a35a11f813c6dff0b76089e5e138cc 1.单机部署 1.1.下载镜像 1.2.安装MQ 2.集群部署 2.1.集群分类 2.2.设置网络 视频地址&#xff1a; 05-Rab…

《养育男孩》:培养未来男子汉,养育男孩的全方位指南

粉丝福利&#xff1a;公众号内回复4可免费获取本期《养育男孩》的读书音频哦。 作为一名家长&#xff0c;我们深知在孩子成长过程中&#xff0c;尤其是男孩的成长过程中&#xff0c;父母的角色和责任有多么重大。最近阅读了心理学家史蒂夫比达尔夫所著的《养育男孩》一书&…

使用plasmo开发浏览器插件在网页指定位置添加自定义UI

使用plasmo开发浏览器插件的时候&#xff0c;有时候需要在指定网站的指定页面添加自定义的UI内容&#xff0c;如果通过content.js内容脚本去通过js创建的话&#xff0c;可就太麻烦了&#xff0c;要写不少的js代码。不过plasmo已经帮我们实现了这个功能&#xff0c;就是Content …

「51媒体网」媒体邀约现场采访的优势有哪些?

传媒如春雨&#xff0c;润物细无声的&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体邀约现场采访的优势主要表现在以下几个方面&#xff1a; 实时报道与传播&#xff1a;现场采访能够让媒体了解活动的真实性&#xff0c;此外&#xff0c;到场报道媒体可以实时迅速将…

谷粒商城实战(009 缓存-分布式锁)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第158p-第p165的内容 分布式锁 原理和使用 使用下shell对产生的命令进行发送 查看 -> 撰写 -> 撰写栏 idea 选中的代码提取成方法 加锁…

go优雅读取zip压缩包-进阶2

【前言】 看到这里就晓得了&#xff0c;之前那一一篇文章go优雅读取zip压缩包&#xff0c;依旧还是有些问题&#xff0c;接下来&#xff0c;我就开始描述下本文章讲述的内容&#xff1a; 面对需要多次读取多个zip压缩包里的指定文件内容&#xff0c;如何提升读取的速度&#x…

smart link实验配置

相关知识点&#xff1a;stp生成树协议&#xff0c;收敛时间慢会导致丢帧&#xff0c;所以利用samrt link配置 1.分主从端口&#xff0c;正常情况下主端口工作&#xff0c;从端口阻塞&#xff0c;防止回路&#xff0c;主端口出问题&#xff0c;切换从端口&#xff0c;并通过flu…