最近由于系统须要接入了一个新的支付通道,通常来讲都是使用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