最近维护的项目对接第三方需要用到WebService,工作好几年了,实际项目中还是第一次用到,去网上翻了翻,大都是抄来抄去,并且已经过时的版本了,趁这个机会去了解了解,分享出来,希望能帮到大家。
WebService,诞生于SOAP时期,简单来说是一种服务间通讯手段,以下来自百科。
Web服务是一种服务导向架构的技术,通过标准的Web协议提供服务,目的是保证不同平台的应用服务可以互操作。
根据W3C的定义,Web服务(Web service)应当是一个软件系统,用以支持网络间不同机器的互动操作。网络服务通常是许多应用程序接口(API)所组成的,它们透过网络,例如国际互联网(Internet)的远程服务器端,执行客户所提交服务的请求。
尽管W3C的定义涵盖诸多相异且无法介分的系统,不过通常我们指有关于主从式架构(Client-server)之间根据SOAP协议进行传递XML格式消息。无论定义还是实现,Web服务过程中会由服务器提供一个机器可读的描述(通常基于WSDL)以辨识服务器所提供的WEB服务。另外,虽然WSDL不是SOAP服务端点的必要条件,但目前基于Java的主流Web服务开发框架往往需要WSDL实现客户端的源代码生成。一些工业标准化组织,比如WS-I,就在Web服务定义中强制包含SOAP和WSDL。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-web-servicesartifactId>
dependency>
<dependency>
<groupId>org.apache.cxfgroupId>
<artifactId>cxf-spring-boot-starter-jaxwsartifactId>
<version>3.5.2version>
dependency>
@WebService 声明为WebService服务
@WebResult 定义返回值信息 不指定时 默认为 return
@WebParam 定义参数信息 不指定时 默认为 arg0 arg1....
@WebMethod 对指定方法进行个性化设置 如:不向外暴露某个方法
@WebService 实现类上声明
其他的 WebResult WebMethod WebParam 可以生命在接口中也可以声明在实现类中
而且 WebResult WebMethod WebParam 声明所在的类中必须声明 @WebService
默认情况下会将WebService下所有方法暴露为WebService 服务,可以在实现类中 使用 @WebMethod 标记指定方法不对外暴露
一句话总结
- 所有声明在实现类可以
- 接口中声明所有资源 + 实现类中声明 @WebService
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String birthday;
// WebService 对参数类型有限制 无法直接使用 LocalDate
// private LocalDate birthday;
private List<String> hobbies;
}
public interface UserService {
User getById(User User);
}
@Service
@WebService(targetNamespace = "http://springboot.kalpana.top")
public class UserServiceImpl implements UserService {
private final Map<Long, User> userMap = new HashMap<>();
{
User user = new User();
user.setId(1L);
user.setName("张三");
user.setAge(18);
user.setBirthday("1987-12-15");
user.setHobbies(Arrays.asList("吃饭", "睡觉"));
userMap.put(1L, user);
user = new User();
user.setId(2L);
user.setName("李四");
user.setAge(15);
user.setBirthday("1991-03-03");
user.setHobbies(Arrays.asList("游泳", "下棋"));
userMap.put(2L, user);
user = new User();
user.setId(3L);
user.setName("王五");
user.setAge(12);
user.setBirthday("1994-03-03");
user.setHobbies(Arrays.asList("打游戏", "读书"));
userMap.put(3L, user);
}
@Override
// @WebMethod 不对方法单独设置,则无需加此注解,以默认配置暴露该方法
@WebResult(name = "res")
public User getById(@WebParam(name = "req") User user) {
User res = userMap.get(user.getId());
Assert.notNull(res, user.getId() + " 用户不存在");
return res;
}
}
@Configuration
public class WebServiceConfig {
@Autowired
private Bus bus;
@Autowired
private UserService userService;
/**
* 如果有多个服务需要暴露,需定义多个EndpointImpl 的Bean,并关联到对应的 服务 ,绑定到指定路径
* @return
*/
@Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, userService);
// 设置入口拦截器,拦截器实现 org.apache.cxf.interceptor.Interceptor 接口即可
// endpoint.getInInterceptors().add(new CustomInterceptor());
endpoint.publish("/user");
return endpoint;
}
}
cxf:
# 必须以 / 开头
path: /student-service
访问路径为 ip:port/student-service/user?wsdl
http://localhost:8080/student-service/user?wsdl
<dependency>
<groupId>org.apache.cxfgroupId>
<artifactId>cxf-spring-boot-starter-jaxwsartifactId>
<version>3.5.2version>
dependency>
public static void main(String[] args) {
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("http://localhost:8080/student-service/user?wsdl");
// 设置出口拦截器,拦截器实现 org.apache.cxf.interceptor.Interceptor 接口即可
// client.getOutInterceptors().add(new CustomInterceptor());
Object[] objects;
try {
// p1:服务所在命名空间,p2:方法名
QName opName = new QName("http://springboot.kalpana.top", "getById");
User user = new User();
user.setId(3L);
objects = client.invoke(opName, user);
System.out.println("响应 : " + objects[0]);
} catch (java.lang.Exception e) {
e.printStackTrace();
}
}
部分日志
15:22:29.299 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Chain org.apache.cxf.phase.PhaseInterceptorChain@4acc5dff was modified. Current flow:
receive [PolicyInInterceptor, AttachmentInInterceptor]
post-stream [StaxInInterceptor]
read [ReadHeadersInterceptor, SoapActionInInterceptor, StartBodyInterceptor]
pre-protocol [MustUnderstandInterceptor]
post-protocol [CheckFaultInterceptor]
unmarshal [DocLiteralInInterceptor, SoapHeaderInterceptor]
post-logical [WrapperClassInInterceptor]
pre-invoke [StaxInEndingInterceptor, SwAInInterceptor, HolderInInterceptor, PolicyVerificationInInterceptor]
15:22:29.299 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor@3650d4fc
15:22:29.309 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.SoapActionInInterceptor@7e5843db
15:22:29.309 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.StartBodyInterceptor@aaa0f76
15:22:29.309 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor@7a8b9166
15:22:29.309 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor@340a8894
15:22:29.309 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.wsdl.interceptors.DocLiteralInInterceptor@459f703f
15:22:29.324 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.SoapHeaderInterceptor@188ac8a3
15:22:29.324 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.WrapperClassInInterceptor@31dfc6f5
15:22:29.328 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.interceptor.StaxInEndingInterceptor@2264ea32
15:22:29.328 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.SwAInInterceptor@663bb8ef
15:22:29.328 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.HolderInInterceptor@37b52340
15:22:29.328 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.ws.policy.PolicyVerificationInInterceptor@44b29496
15:22:29.328 [main] DEBUG org.apache.cxf.ws.policy.PolicyVerificationInInterceptor - Verified policies for inbound message.
返回数据:User{id=3, name='王五', age=12, birthday='1994-03-03', hobbies=[打游戏, 读书]}
静态调用需预先将webservice翻译成Java代码,然后以本地Java方法的方式调用
<plugin>
<groupId>org.apache.cxfgroupId>
<artifactId>cxf-codegen-pluginartifactId>
<version>3.5.2version>
<executions>
<execution>
<id>generate-sourcesid>
<phase>generate-sourcesphase>
<configuration>
<sourceRoot>src/main/resources/cxfsourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>http://localhost:8080/student-service/user?wsdlwsdl>
wsdlOption>
wsdlOptions>
configuration>
<goals>
<goal>wsdl2javagoal>
goals>
execution>
executions>
plugin>
public static void main(String[] args) {
UserServiceImplService userServiceImplService = new UserServiceImplService();
UserServiceImpl userServiceImplPort = userServiceImplService.getUserServiceImplPort();
User user = new User();
user.setId(3L);
User byId = userServiceImplPort.getById(user);
System.out.println("静态测试返回的数据: " + byId);
}
15:47:56.727 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Chain org.apache.cxf.phase.PhaseInterceptorChain@3ecedf21 was modified. Current flow:
receive [PolicyInInterceptor, AttachmentInInterceptor]
post-stream [StaxInInterceptor]
read [WSDLGetInterceptor, ReadHeadersInterceptor, SoapActionInInterceptor, StartBodyInterceptor]
pre-protocol [MustUnderstandInterceptor]
post-protocol [CheckFaultInterceptor, JAXBAttachmentSchemaValidationHack]
unmarshal [DocLiteralInInterceptor, SoapHeaderInterceptor]
post-logical [WrapperClassInInterceptor]
pre-invoke [StaxInEndingInterceptor, SwAInInterceptor, HolderInInterceptor, PolicyVerificationInInterceptor]
15:47:56.727 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.frontend.WSDLGetInterceptor@3c1e23ff
15:47:56.727 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor@2ba45490
15:47:56.739 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.SoapActionInInterceptor@1bf0f6f6
15:47:56.739 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.StartBodyInterceptor@37ff4054
15:47:56.739 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor@7af707e0
15:47:56.740 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor@894858
15:47:56.740 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.jaxb.attachment.JAXBAttachmentSchemaValidationHack@737edcfa
15:47:56.740 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.wsdl.interceptors.DocLiteralInInterceptor@56bc3fac
15:47:56.760 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.SoapHeaderInterceptor@df4b72
15:47:56.760 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.WrapperClassInInterceptor@18151a14
15:47:56.764 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.interceptor.StaxInEndingInterceptor@4943defe
15:47:56.765 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.SwAInInterceptor@169da7f2
15:47:56.765 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.HolderInInterceptor@64711bf2
15:47:56.765 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.ws.policy.PolicyVerificationInInterceptor@125c082e
15:47:56.765 [main] DEBUG org.apache.cxf.ws.policy.PolicyVerificationInInterceptor - Verified policies for inbound message.
静态测试返回的数据: User{age=15, birthday='1991-03-03', hobbies=[游泳, 下棋], id=2, name='李四'}
Disconnected from the target VM, address: '127.0.0.1:13468', transport: 'socket'