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

目錄
前言
最近公司接的項目需要對接第三方服務,這個服務商是用的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