使用自定义注解发布webservice服务
- 概要
- 代码
- 自定义注解
- WebService接口服务发布配置
- 使用
- 结果
概要
在springboot使用webservice,发布webservice服务的时候,我们经常需要手动在添加一些发布的代码,比如:
@Bean
public Endpoint organizationEndpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, organizationProvider);
endpoint.publish("/organization");
//在服务端添加日志拦截器。
endpoint.getInInterceptors().add(new LoggingInInterceptor());
endpoint.getOutInterceptors().add(new LoggingOutInterceptor());
return endpoint;
}
每写一个服务就要发布一次,上面的代码就要重复一次,如是就想把这重复的代码通过注解的形式来简化,下面是具体实现。
代码
自定义注解
/**
* 自定义发布webservice服务注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface WsEndpoint {
@NotNull
@AliasFor("name")
String value() default "";
}
WebService接口服务发布配置
/**
* 负责发布WebService服务的配置
*
* 该方法通过WsEndpoint自定义注解来进行统一发布webservice服务
* 下方注释部分为正常写法的示例
*/
@Configuration
@Slf4j
public class CxfConfig implements CommandLineRunner, ApplicationContextAware, BeanDefinitionRegistryPostProcessor{
private ApplicationContext applicationContext;
private ConfigurableListableBeanFactory beanFactory;
/*@Autowired
private Bus bus;
@Resource
private OrganizationProvider organizationProvider;
*/
/**
* 发布 机构endpoint
*
* @return
*/
/* @Bean
public Endpoint organizationEndpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, organizationProvider);
endpoint.publish("/organization");
//在服务端添加日志拦截器。后续还有更好的方法。
endpoint.getInInterceptors().add(new LoggingInInterceptor());
endpoint.getOutInterceptors().add(new LoggingOutInterceptor());
return endpoint;
}*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
// 拿到bean工厂对象
this.beanFactory = configurableListableBeanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 拿到上下文对象
this.applicationContext = applicationContext;
}
/**
* 项目启动完成后发布webservice服务,在项目没有启动完成前,
* 由于bean依赖之类的还没有注入,提前从上下文对象中拿到相关bean发布webservice服务可能会引发依赖问题。
* @param args
* @throws Exception
*/
@Override
public void run(String... args) throws Exception {
log.info("===============================.................. springboot启动完成,发布webservice服务 ...");
try {
Bus bus = applicationContext.getBean(Bus.class);
// 拿到标记了webservice注解的bean
String[] beanNamesForAnnotation = applicationContext.getBeanNamesForAnnotation(WebService.class);
if (null == beanNamesForAnnotation || beanNamesForAnnotation.length == 0) {
return;
}
// 需要发布的webservice服务
for (String beanName : beanNamesForAnnotation) {
Object bean = applicationContext.getBean(beanName);
// 解析自定义注解并拿到值
String path = analyzeClassAndInterfaceAnnotation(bean.getClass());
if (StringUtils.isBlank(path)) {
// 没有标记自定义注解的webservice服务不会发布
continue;
}
EndpointImpl endpoint = new EndpointImpl(bus, bean);
endpoint.publish(path);
//在服务端添加日志拦截器。后续还有更好的方法。
endpoint.getInInterceptors().add(new LoggingInInterceptor());
//返回200时,会记录下返回的SOAP报文。但未能返回200时,看上去记录的依然是输入时的SOAP报文
endpoint.getOutInterceptors().add(new LoggingOutInterceptor());
beanFactory.registerSingleton(path, endpoint);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 判断当前类及其实现的接口上是否有自定义注解,并且拿到自定义注解的值
*
* @param aClass
*/
private String analyzeClassAndInterfaceAnnotation(Class<?> aClass) {
// 判断当前类上是否有自定义注解
Annotation[] annotations = aClass.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof WsEndpoint) {
return ((WsEndpoint) annotation).value();
}
}
// 判断实现的接口上是否有自定义注解
Class<?>[] interfaces = aClass.getInterfaces();
if (null == interfaces || interfaces.length == 0) {
return null;
}
for (Class<?> anInterface : interfaces) {
Annotation[] interfaceAnnotations = anInterface.getAnnotations();
if (null == interfaceAnnotations || interfaceAnnotations.length == 0) {
continue;
}
for (Annotation interfaceClassAnnotation : interfaceAnnotations) {
if (interfaceClassAnnotation instanceof WsEndpoint) {
return ((WsEndpoint) interfaceClassAnnotation).value();
}
}
}
return null;
}
}
使用
@WebService(targetNamespace = "http://www.chiss.org.cn/rhin/2015", name = "OrganizationProvider")
@XmlSeeAlso({ObjectFactory.class})
@WsEndpoint("organization") // 使用自定义注解发布webservice服务接口
public interface OrganizationProvider {
/**
* 机构注册
*
* @param message
* @return
* @throws SOAPException
*/
@WebMethod(operationName = "OrganizationFeed", action = "OrganizationFeed")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@WebResult(name = "OrganizationFeedResponse", targetNamespace = "http://www.chiss.org.cn/rhin/2015", partName = "message")
public OrganizationFeedResponse organizationFeed(
@WebParam(partName = "message", name = "OrganizationFeed", targetNamespace = "http://www.chiss.org.cn/rhin/2015")
OrganizationFeed message
) throws SOAPException;
/**
* 机构分页查询
*
* @param message
* @return
*/
@WebMethod(operationName = "OrganizationQuery", action = "OrganizationQuery")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@WebResult(name = "OrganizationQueryResponse", targetNamespace = "http://www.chiss.org.cn/rhin/2015", partName = "message")
public OrganizationQueryResponseMessage organizationQuery(
@WebParam(partName = "message", name = "OrganizationQuery", targetNamespace = "http://www.chiss.org.cn/rhin/2015")
OrganizationQueryRequest message
) throws SOAPException;
}
结果
springboot启动完成后进行webservice服务接口发布
发布后的接口