SpringBoot發布webservice服務並調用(hutool yyds)


作者: 故事我忘了
個人微信公眾號: 程序猿的月光寶盒

前言

​ 最近公司接的項目需要對接第三方服務,這個服務商是用的WebService開的接口提供調用

​ 因為是內網項目,所以內網映射外網的服務器還沒提供過來,所以為了自己以后不加班(這是真實存在的嗎?自我安慰叭),所以自己寫了個springboot服務發布WS服務,放到服務器上練練手

​ 上一篇博客(《pringBoot打包到docker(idea+傳統方式)》)其實是這篇博客之后的事兒

​ 本來昨天就得寫的,奈何家里的電腦,只能打游戲,昨天想寫,發現連Typora都沒有.別說圖床,git了,寫個鈎叭~

圖片

另外,蒸汽廠打折了啊,還不買嗎

開干

1.涉及技術點

​ SpringBoot+Webservice+Hutool(主要做一個調用WS的SoapClient)

上一張尷圖先

圖片

都說Hutool用的越早,下班越早,但是不排除我不會用導致的加班

2.整體項目結構

圖片

3.Provider 發布Ws服務端

首先,肯定要修改pom文件

依賴加上
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 小辣椒,簡化代碼 -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
    </dependency>
    
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>

    <!--發布ws需要用到的依賴-->
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-frontend-jaxws</artifactId>
      <version>3.4.5</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http</artifactId>
      <version>3.4.5</version>
    </dependency>
    
    <!-- hutool 的包   -->
    <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.7.14</version>
    </dependency>
  </dependencies>

3.0 因為用對象的形式反參,所以建個對象

UserLoginVO

package com.jinsc.provider.vo;

import lombok.Data;

import java.io.Serializable;

/**
 * 用戶登錄VO
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 * @since Created in 2021/10/21 23:28
 */
@Data
public class UserLoginVO implements Serializable {
    private static final long serialVersionUID = 2673128718180426817L;
    private Integer errorCode;
    private String errMsg;
    private String name;

    public UserLoginVO() {
    }

    public UserLoginVO(Integer errorCode, String errMsg, String name) {
        this.errorCode = errorCode;
        this.errMsg = errMsg;
        this.name = name;
    }
}

3.1 首先寫一個service,正常寫就完事了,唯一不同的就是注解這塊用WS的注解

LoginService

package com.jinsc.provider.service;

import com.jinsc.provider.vo.UserLoginVO;

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

/**
 * ws的登錄接口
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 * @since Created in 2021/10/21 11:01
 */
@WebService(name = "LoginService", //暴露服務名稱
        targetNamespace = "http://jinsc.com" //空間名稱
)
public interface LoginService {
    UserLoginVO userLogin(@WebParam(name = "name") String name);
}

3.2 寫他的實現類

LoginServiceImpl

package com.jinsc.provider.service.impl;

import com.jinsc.provider.service.LoginService;
import com.jinsc.provider.vo.UserLoginVO;
import org.springframework.stereotype.Service;

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

/**
 * ws的登錄接口實現類
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 * @since Created in 2021/10/21 11:05
 */
@WebService(serviceName = "LoginService", // 與接口中的name保持一致
        targetNamespace = "http://jinsc.com", // 與接口中的name保持一致
        endpointInterface = "com.jinsc.provider.service.LoginService" // 接口包路徑
)
// 用於配置類自動注入
@Service
public class LoginServiceImpl implements LoginService {
    @Override
    public UserLoginVO userLogin(@WebParam(name = "name") String name) {
        return new UserLoginVO(500, "登錄失敗~~", name);
    }


}

3.3 寫WS的Cxf配置類

CxfConfig

package com.jinsc.provider.config;

import com.jinsc.provider.service.LoginService;
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;

/**
 * ws的配置類
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 * @since Created in 2021/10/21 11:14
 */
@Configuration
public class CxfConfig {
    @Resource
    private LoginService loginService;

    /**
     * 用於注冊CXFServlet的
     * 地址/webservice/*
     * * 通配符 更上接口地址
     *
     * @return org.springframework.boot.web.servlet.ServletRegistrationBean<org.apache.cxf.transport.servlet.CXFServlet>
     * @author 金聖聰
     * @email jinshengcong@163.com
     * Modification History:
     * Date         Author        Description        version
     * --------------------------------------------------------*
     * 2021/10/21 11:25    金聖聰     修改原因            1.0
     */
    @Bean
    public ServletRegistrationBean<CXFServlet> dispatcherServlet2() {
        // 這里就是發布服務的跟路徑,后面 * 是通配符,表示跟什么都行
        return new ServletRegistrationBean<>(new CXFServlet(), "/webservice/*");
    }

    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        return new SpringBus();
    }

    @Bean
    public Endpoint endpoint() {
        // 建立一個端點 ,第一個參數是 springBus 對象,第二個參數是剛才的接口實現類(因為在實現類中用了@service,所以這里可以自動注入)
        // PS: 要是有多個service,這個方法對象多寫幾個就行
        EndpointImpl endpoint = new EndpointImpl(springBus(), loginService);
        // 這里就是發布的這個接口的地址
        endpoint.publish("/loginApi");
        return endpoint;
    }
}

這樣,這個WS就可以發布了

地址是

ip:端口/webservice/loginApi?wsdl

本機啟動就是

http://localhost:8080/webservice/loginApi?wsdl

圖片

以上,發布成功

4.consumer 調用Ws端所以我稱之為消費端

同樣,給上pom依賴

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 小辣椒簡化代碼   -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>

    <!-- hutool的包   -->
    <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.7.14</version>
    </dependency>
  </dependencies>

4.0 因為用對象形式解析參數所以創建對象

UserLoginDto

package com.jinsc.consumer.dto;

import lombok.Data;

import java.io.Serializable;

/**
 * 用戶登錄Dto
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 * @since Created in 2021/10/21 23:36
 */
@Data
public class UserLoginDto implements Serializable {
    private static final long serialVersionUID = 1292974846576856351L;
    private String errMsg;
    private String name;
    private String errorCode;
}

4.1 創建個客戶端去調用ws服務就ojbk了啊

不過在此之前,我們用SoapUI去解析下剛才的ws地址

圖片

由上,我們可以得到

命名空間: http://jinsc.com

方法名 : jin:userLogin

入參: name

所以我們可以創建SoapClient

TestWsConnect

package com.jinsc.consumer.client;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.webservice.SoapClient;
import com.jinsc.consumer.dto.UserLoginDto;
import org.w3c.dom.Document;

import javax.xml.xpath.XPathConstants;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * 測試ws連接
 *
 * @author 金聖聰
 * @version v1.0
 * @email jinshengcong@163.com
 * @since Created in 2021/10/21 23:35
 */
public class TestWsConnect {
    public static void main(String[] args) {
        // 新建客戶端
        SoapClient client = SoapClient.create("http://localhost:8080/webservice/loginApi?wsdl")
        // SoapClient client = SoapClient.create("http://服務器端口地址/webservice/loginApi?wsdl")
                // 設置要請求的方法,此接口方法前綴為web,傳入對應的命名空間
                .setMethod("jin:userLogin", "http://jinsc.com")
            	// 設置參數,此處自動添加方法的前綴:jin
            	// false的意思就是沒有前綴
                .setParam("name", "jinshengcong3080ti", false);
        

        // 發送請求,參數true表示返回一個格式化后的XML內容
        // 返回內容為XML字符串,可以配合XmlUtil解析這個響應
        String send = client.send(true);
        Console.log(send);
        // 把send返回的xml內容轉換成document對象
        Document document = XmlUtil.parseXml(send);
        List<String> nameList = Arrays.asList("errMsg", "errorCode", "name");
        HashMap<String, String> resultMap = new HashMap<>();
        nameList.forEach(e -> {
            // 循環上面的nameList列表,每個元素都是return后面的標簽,得標簽里面的值
            String result = (String) XmlUtil.getByXPath("//return/" + e, document, XPathConstants.STRING);
            // 然后給結果map賦值,key是name,value是標簽中的值
            resultMap.put(e, result);
        });
        // 得到結果map
        Console.log(resultMap);
        // map轉Dto,其中屬性要一致
        UserLoginDto convert = Convert.convert(UserLoginDto.class, resultMap);
        Console.log(convert);

    }
}

這樣就可以了

運行一下康康~

圖片

好了,ojbk


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM