springboot实现webservice生成wsdl
1.核心技术选型
- springboot 2.7.0
- apache CXF 3.5.0
2.项目结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EpzWPWRb-1667378754339)(java-WSDL服务端.assets\)]
3.项目搭建
搭建工具:maven
搭建步骤:
1.搭建maven项目
2.编写pom导入依赖
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.5.0</version>
</dependency>
</dependencies>
3.编写启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WsApplication {
public static void main(String[] args) {
SpringApplication.run(WsApplication.class, args);
}
}
基本配置
src\resouse目录下创建文件
写入配置:
server:
port: 8888 # 发布端口
spring:
main:
allow-bean-definition-overriding: true
application:
name: chengkz-boot-cxf
cxf:
path: /ws # webservice的发布url路径 例:http://127.0.0.1:8888/ws/....
4.定义要发布的业务接口
在service目录下创建接口,定义方法
public interface FileService {
public byte[] sealValidation( byte[] pdfData, String filename);
}
注意
-
1.方法参数顺序对应发布后第三者调用所需的方法参数顺序
-
2.方法参数类型对应发布后第三者调用所需的参数类型
-
3.方法名对应发布后第三方调用的方法名
5.编写接口的实现类
将逻辑代码写进实现方法
@WebService //必要注解
@Service //必要注解
@Slf4j //日志注解
@AutoPublishWS(publishPath = "FileService") //动态发布配置必要注解,具体作用见下文
public class FileServiceImpl implements FileService {
@Override
@WebMethod //必要注解
@WebResult(name = "fileResult") //自定义服务结果名
public byte[] sealValidation(byte[] pdfData, String filename) {
//在这里模拟接收base64编码的二进制文件
byte[] data = Base64.getDecoder().decode(pdfData);
log.info("处理文件:" + filename);
//返回
return data;
}
}
6.服务的发布与配置
服务的发布有两种方式:
6.1 静态发布
编写cxf配置类 不建议接口服务较多时使用
import com.ckz.ws.service.impl.CalculatorServiceImpl;
import com.ckz.ws.service.impl.MsgServiceImpl;
import com.ckz.ws.service.impl.FileServiceImpl;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;
@Configuration //若采用动态发布请注释掉这个注解
public class CxfConfig {
@Autowired
private Bus bus;
//每有一个webservice接口就需要如下形式
@Autowired
private CalculatorServiceImpl calculatorService;
@Bean
public Endpoint calculatorServer() {
EndpointImpl endpoint = new EndpointImpl(bus,calculatorService);
endpoint.publish("/calculator");//在这里设置发布的地址 http://ip:port/xxx/calculator
return endpoint;
}
//
@Autowired
private FileServiceImpl pdfService;
@Bean
public Endpoint pdfServer() {
EndpointImpl endpoint = new EndpointImpl(bus,msgService);
endpoint.publish("/fileServer");
return endpoint;
}
@Autowired
private MsgServiceImpl msgService;
@Bean
public Endpoint msgServer() {
EndpointImpl endpoint = new EndpointImpl(bus,pdfService);
endpoint.publish("/msgServer");
return endpoint;
}
}
6.2 动态发布
在这里搬运的B站大佬 up主:jinshengyuanok
他的视频有更详细的教学,希望大家给他三连
1.编写自动注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AutoPublishWS {
String publishPath();
}
2.编写自动发布配置类
里面涉及到的自定义注解名要与你自定义的注解名保持一致
写法基本固定写死,注解名未改动可直接使用
package com.ckz.ws.config;
import com.ckz.ws.annotation.AutoPublishWS;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import static org.apache.tomcat.jni.Buffer.address;
@Slf4j
@Component
@Order(1)
public class AutoPublishWSEndpoint implements ApplicationRunner {
//取出WS的根路径
@Value("${}")
public String cxfPath;
//取出AppName
@Value("${}")
public String appName;
//注入CXF Bus
@Autowired
private Bus bus;
//注入Spring Web中Servlet上下文Web容器
@Autowired
private WebApplicationContext webApplicationContext;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("AutoPublishWSEndpoint===发布开始");
//根据注解获取beanNames
String[] beanNames =
webApplicationContext.getBeanNamesForAnnotation(AutoPublishWS.class);
EndpointImpl endpoint;
List<String> cxfPathList = new ArrayList<>();
for (String beanName : beanNames) {
//根据beanName获取属性名
String publishPath =
webApplicationContext.getType(beanName).getAnnotation(AutoPublishWS.class).publishPath();
//发布WebService接口
endpoint = new EndpointImpl(bus,
webApplicationContext.getBean(beanName));
endpoint.publish(publishPath);
cxfPathList.add(publishPath);
log.info(String.format("%s", publishPath));
}
log.info("AutoPublishWSEndpoint===发布结束");
Environment environment = webApplicationContext.getEnvironment();
address(environment, cxfPathList);
}
private void address(Environment environment, List<String> cxfPathList) {
try {
String ip = InetAddress.getLocalHost().getHostAddress();
String port = environment.getProperty("");
String path = environment.getProperty("");
if (path == null) {
path = "";
}
log.info("\n-------------------------------------------------------- --\n\t" +
"Application " + appName + " is running! Access URLs:\n\t" +
"Local: \t\thttp://localhost:" + port + path + "/\n\t" +
"External: \thttp://" + ip + ":" + port + path + "/" + "\n---------------------------------------------------------- ");
if (cxfPathList.size() > 0) {
StringBuilder logStr = new StringBuilder();
logStr.append("\n\tWSDL URLS:\n\t");
String finalPath = path;
cxfPathList.forEach(s -> {
logStr.append("\t\thttp://localhost:" + port + finalPath +
cxfPath + "/" + s + "?wsdl\n\t");
logStr.append("\t\thttp://" + ip + ":" + port + finalPath +
cxfPath + "/" + s + "?wsdl\n\t");
});
log.info(logStr.toString());
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
3.在要发布service实现类加上注解
如上文实现类介绍处
@AutoPublishWS(publishPath = "FileService") //publishPath为你要设置的接口服务url路径
//http:\\ip:port\xxx\FileService?wsdl
7.项目打包
该项目基于springboot
建议使用idea插件mavenHelper打包
打包步骤
右键项目根包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eVVLREWJ-1667378754341)(java-WSDL服务端.assets\)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EluzV98f-1667378754343)(java-WSDL服务端.assets\)]
8.基于原有项目新增wenservice接口
项目(动态发布模式)启动成功后会输出具体url信息 //注意: 注释掉静态发布配置类的@Configuration注解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PV9ShysW-1667378754344)(java-WSDL服务端.assets\)]
8.1 若有新类别webservice服务
在service目录下新建接口
具体操作与注意详见
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bI9i67qt-1667378754345)(java-WSDL服务端.assets\)]
8.2 若只有新webservice方法
1.在对应的webservice接口里声明
2.在对应webservice实现类里实现方法
其注意事项与具体操作详见
8.3 模板接口与模板接口实现类
1.模板接口
package com.ckz.ws.service;
public interface XxxxService { //在这里 "XxxxService" 建议以这种格式自定义
/**
*方法声明
*[returnType] 返回值类型
*[method name] 方法名
*[argType] [arg name] ... 参数类型 参数名 。。。
*/
public [returnType] [method name]( [argType] [arg name], ...);
}
2.实现类接口
package com.ckz.ws.service.impl;
import com.ckz.ws.annotation.AutoPublishWS;
import com.ckz.ws.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebService;
import java.util.Base64;
@WebService
@Service
@Slf4j
@AutoPublishWS(publishPath = "XxxService")
public class FileServiceImpl implements FileService {
@Override
@WebMethod
@WebResult(name = "xxxResult")
public [returnType] [method name]( [argType] [arg name], ...) {
//业务逻辑
//byte[] data = ().decode(pdfData);
//("处理文件:" + filename);
//return data;
}
}
附录
MavenHelper安装
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dylM0ovT-1667378754346)(java-WSDL服务端.assets\)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oSoaykYT-1667378754348)(java-WSDL服务端.assets\)]
最后选择插件压缩包安装
Service {
@Override
@WebMethod
@WebResult(name = “xxxResult”)
public [returnType] [method name]( [argType] [arg name], …) {
//业务逻辑
//byte[] data = ().decode(pdfData);
//(“处理文件:” + filename);
//return data;
}
}
## 附录
### MavenHelper安装
[外链图片转存中...(img-dylM0ovT-1667378754346)]
[外链图片转存中...(img-oSoaykYT-1667378754348)]
最后选择插件压缩包安装