最近由於系統須要接入了一個新的支付通道,通常來講都是使用RestApi
來接入,可是本次接入的支付通道爲境外支付,使用的WebService,對於WS咱們在實際業務中基本上不會用到,因此查閱了一些資料,記錄一下本身項目中使用的WS。java
XML和XSD
、SOAP
、WSDL
、UDDI
,詳細內容請參閱百度百科:Web Service接下來,咱們以一個簡單的示例來演示下,如何發佈服務及如何進行服務調用。git
spring-boot-cxf-service
<dependencies>
<!--spring-boot-starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--lombok懶人依賴 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--test依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--cxf依賴 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.2.5</version>
</dependency>
<!--commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
複製代碼
NBAPlayer.java
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class NBAPlayer {
String name;
String team;
List<String> teams;
String description;
Position position;
@Override
public String toString() {
return "NBA現役球員" + name + ",司職" + position.value + "現效力於" + team + ",曾效力球隊" + teams.toString();
}
}
複製代碼
2.Positon.java
public enum Position {
FORWARD("小前鋒"),
SHOOTING("控球後衛");
String value;
Position(String value) {
this.value = value;
}
public String value() {
return value;
}
public static Position fromValue(String v) {
for (Position c : Position.values()) {
if (c.value.equals(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
}
複製代碼
3.NBAPlayerSoapService.java
@WebService(targetNamespace = WsConst.NAMESPACE_URI, name = "NBAPlayerSoap")
public interface NBAPlayerSoapService {
/** * description 根據姓名獲取球員信息 * date 2019/10/15 * * @param NBAPlayerName * @param NBAPlayerName * @return cn.forward.springboot.cxf.service.entity.NBAPlayer */
@WebMethod(operationName = "getNBAPlayerByName")
NBAPlayer getNBAPlayerByName(@WebParam(name = "NBAPlayerName") String NBAPlayerName);
/** * description 獲取球員列表 * date 2019/10/15 * * @return java.util.List<cn.forward.springboot.cxf.service.entity.NBAPlayer> */
@WebMethod
List<NBAPlayer> getNBAPlayerList();
}
複製代碼
4.NBAPlayerSoapImpl.java
@WebService(
targetNamespace = WsConst.NAMESPACE_URI, //wsdl命名空間
name = "NBAPlayerSoap", //portType名稱 客戶端生成代碼時 爲接口名稱
serviceName = "NBAPlayerSoapService", //服務name名稱
portName = "NBAPlayerPortName", //port名稱
endpointInterface = "cn.forward.springboot.cxf.service.service.NBAPlayerSoapService")
public class NBAPlayerSoapImpl implements NBAPlayerSoapService {
@Override
public NBAPlayer getNBAPlayerByName(String name) {
List<NBAPlayer> nbaPlayers = getNBAPlayerList();
AtomicReference<NBAPlayer> player = new AtomicReference<>(nbaPlayers.get(new Random().nextInt(2)));
nbaPlayers.forEach(nbaPlayer -> {
if (nbaPlayer.getName().equals(name)) {
player.set(nbaPlayer);
}
});
return player.get();
}
@Override
public List<NBAPlayer> getNBAPlayerList() {
return generatorList();
}
public List<NBAPlayer> generatorList() {
List<NBAPlayer> resultList = new ArrayList<>();
NBAPlayer LBJ = new NBAPlayer();
LBJ.setName("勒布朗·詹姆斯");
LBJ.setTeam("洛杉磯湖人");
LBJ.setTeams(Arrays.asList("克里夫蘭騎士(2003−2010)", "邁阿密熱火(2010−2014)"));
LBJ.setPosition(Position.FORWARD);
LBJ.setDescription(LBJ.toString());
resultList.add(LBJ);
NBAPlayer WS = new NBAPlayer();
WS.setName("羅素·威斯布魯克");
WS.setTeam("休斯頓火箭");
WS.setTeams(Arrays.asList("奧克拉荷馬雷霆 (2008-2019)"));
WS.setPosition(Position.SHOOTING);
WS.setDescription(WS.toString());
resultList.add(WS);
return resultList;
}
}
複製代碼
5.WsConst.java
public class WsConst {
public static final String NAMESPACE_URI = "http://www.lqdev.cn/webservice";
}
複製代碼
6.CxfWebServiceConfig.java
@Configuration
public class CxfWebServiceConfig {
//這裏須要注意 因爲springmvc 的核心類 爲DispatcherServlet
//此處若不重命名此bean的話 本來的mvc就被覆蓋了。可查看配置類:DispatcherServletAutoConfiguration
//一種方法是修改方法名稱 或者指定bean名稱
//這裏須要注意 若beanName命名不是 cxfServletRegistration 時,會建立兩個CXFServlet的。
//具體可查看下自動配置類:Declaration org.apache.cxf.spring.boot.autoconfigure.CxfAutoConfiguration
//也能夠不設置此bean 直接經過配置項 cxf.path 來修改訪問路徑的
@Bean("cxfServletRegistration")
public ServletRegistrationBean dispatcherServlet() {
//註冊servlet 攔截/ws 開頭的請求 不設置 默認爲:/services/*
return new ServletRegistrationBean(new CXFServlet(), "/NBA/*");
}
/** * 申明業務處理類 固然也能夠直接 在實現類上標註 @Service * @author oKong */
@Bean
public NBAPlayerSoapService authorService() {
return new NBAPlayerSoapImpl();
}
/** * 非必要項 */
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
SpringBus springBus = new SpringBus();
return springBus;
}
/** * 發佈endpoint */
@Bean
public Endpoint endpoint(NBAPlayerSoapService NBAPlayerSoap) {
EndpointImpl endpoint = new EndpointImpl(springBus(), NBAPlayerSoap);
//發佈地址
endpoint.publish("/player");
return endpoint;
}
}
複製代碼
注意事項: 配置ServletRegistrationBean時,須要注意設置方法的名稱或者bean的名稱時,不要和默認的DispatcherServlet類重名了,會致使原先的mvc接口沒法使用,由於被覆蓋了。 修改訪問的路徑能夠經過設置ServletRegistrationBean來修改,但同時,要注意須要設置bean的名稱爲cxfServletRegistration,否則會形成註冊多個CXFServlet的。具體緣由可查看自動配置類:org.apache.cxf.spring.boot.autoconfigure.CxfAutoConfiguration。@SpringBootApplication
@Slf4j
public class SpringBootCxfServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootCxfServiceApplication.class, args);
log.info("spring-boot-cxf-service啓動!");
}
}
複製代碼
查看輸入日誌github
2019-10-15 15:49:17.964 INFO 16100 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2019-10-15 15:49:17.967 INFO 16100 --- [ main] .f.s.c.s.SpringBootCxfServiceApplication : Started SpringBootCxfServiceApplication in 3.35 seconds (JVM running for 4.454) 2019-10-15 15:49:17.969 INFO 16100 --- [ main] .f.s.c.s.SpringBootCxfServiceApplication : spring-boot-cxf-service啓動! 複製代碼
spring-boot-cxf-client
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.17</version>
</dependency>
</dependencies>
複製代碼
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- cxf-codegen-plugin -->
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.2.5</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.basedir}/src/main/java</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>src/main/resources/wsdl/player.wsdl</wsdl>
<wsdlLocation>classpath:wsdl/player.wsdl</wsdlLocation>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
複製代碼
提示:
將wsdl文件,放入main/resources/wsdl目錄下。以後執行:mvn generate-sources命令,就會自動建立相應的類文件了。拷貝相應的類文件至src/java目錄下便可。或者直接指定sourceRoot也是能夠的WsCont.java
public class WsConst {
public static final String SERVICE_ADDRESS= "http://localhost:8080/NBA/player?wsdl";
}
複製代碼
CxfClientConfig.java
@Configuration
public class CxfClientConfig {
/** * 採用代理方式 * * @return NBAPlayerSoap */
@Bean
public NBAPlayerSoap createAuthorPortTypeProxy() {
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
jaxWsProxyFactoryBean.setServiceClass(NBAPlayerSoap.class);
jaxWsProxyFactoryBean.setAddress(WsConst.SERVICE_ADDRESS);
return (NBAPlayerSoap) jaxWsProxyFactoryBean.create();
}
/** * 採用動態工廠方式 不須要指定服務接口 */
@Bean
public Client createDynamicClient() {
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient(WsConst.SERVICE_ADDRESS);
return client;
}
}
複製代碼
NBAPlayerController.java
@RestController
@RequestMapping("/nba/player")
public class NBAPlayerController {
@Resource
NBAPlayerSoap nbaPlayerSoap;
/** * description 根據球員名稱獲取球員信息 * date 2019/10/15 * * @param nbaPlayerName * @return cn.lqdev.webservice.NbaPlayer */
@GetMapping("/getNBAPlayerByName")
public NbaPlayer getNBAPlayerByName(@RequestParam("nbaPlayerName") String nbaPlayerName) {
return nbaPlayerSoap.getNBAPlayerByName(nbaPlayerName);
}
/** * description 獲取所有球員信息 * date 2019/10/15 * @return java.util.List<cn.lqdev.webservice.NbaPlayer> */
@GetMapping("/getNBAPlayerList")
public List<NbaPlayer> getNBAPlayerList() {
return nbaPlayerSoap.getNBAPlayerList();
}
}
複製代碼
@SpringBootApplication
@Slf4j
public class SpringBootCxfClientApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootCxfClientApplication.class, args);
log.info("spring-boot-cxf-client啓動!");
}
}
複製代碼
訪問: http://localhost:8081/nba/player/getNBAPlayerByName?nbaPlayerName=勒布朗·詹姆斯{
description: "NBA現役球員勒布朗·詹姆斯,司職小前鋒現效力於洛杉磯湖人,曾效力球隊[克里夫蘭騎士(2003−2010), 邁阿密熱火(2010−2014)]",
name: "勒布朗·詹姆斯",
position: "FORWARD",
team: "洛杉磯湖人",
teams: [
"克里夫蘭騎士(2003−2010)",
"邁阿密熱火(2010−2014)"
]
}
複製代碼
6.參考文章web
本次文章主要是分享了springboot基於CXF構建WebService服務的過程。spring