使用自定义注解发布webservice服务

news2025/5/26 12:02:01

使用自定义注解发布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服务接口发布
在这里插入图片描述
发布后的接口
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1027541.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

侯捷老师C++课程:C++2.0 新特性

C 2.0 新特性 第一讲&#xff1a;语言 variatic templates 参数包 在类模板中&#xff0c;模板参数包必须是最后一个模板形参. 而在函数模板中则不必!!! 这个之前提过了&#xff0c;就不细谈了 下面那三个分别对应&#xff1a; typename... Types //模板参数包 const Type…

Linux进程【1】进程概念(超详解哦)

进程概念 引言&#xff08;操作系统如何管理&#xff09;基本概念描述与组织进程查看进程 进程pid与ppidgetpid与getppid 总结 引言&#xff08;操作系统如何管理&#xff09; 在冯诺依曼体系结构中&#xff0c;计算机由输入设备、输出设备、运算器、控制器和存储器组成。我们…

性能测试之使用Jemeter对HTTP接口压测

我们不应该仅仅局限于某一种工具&#xff0c;性能测试能使用的工具非常多&#xff0c;选择适合的就是最好的。笔者已经使用Loadrunner进行多年的项目性能测试实战经验&#xff0c;也算略有小成&#xff0c;任何性能测试&#xff08;如压力测试、负载测试、疲劳强度测试等&#…

【ArcGIS】土地利用变化分析详解(栅格篇)

土地利用变化分析详解-栅格篇 土地利用类型分类1 统计不同土地利用类型的面积/占比1.1 操作步骤 2 统计不同区域各类土地利用类型的面积2.1 操作步骤 3 土地利用变化转移矩阵3.1 研究思路3.2 操作步骤 4 分析不同时期土地利用类型及属性变化4.1 研究思路4.2 操作步骤 参考 土地…

2614. 对角线上的质数-c语言解法

给你一个下标从 0 开始的二维整数数组 nums 。 返回位于 nums 至少一条 对角线 上的最大 质数 。如果任一对角线上均不存在质数&#xff0c;返回 0 。 注意&#xff1a; 如果某个整数大于 1 &#xff0c;且不存在除 1 和自身之外的正整数因子&#xff0c;则认为该整数是一个…

EPICS motor驱动程序实例

本驱动程序是控制https://blog.csdn.net/yuyuyuliang00/article/details/132483050中描述的模拟电机控制器。其余基于字符串通信方式的电机控制器&#xff0c;都可以使用这个模板进行修改&#xff0c;开发对应的EPICS电机驱动程序。 源程序如下&#xff1a; 头文件vm.h&#…

Python实现2048小游戏

简介 《2048》 [1] 是一款比较流行的数字游戏&#xff0c;最早于2014年3月20日发行。原版2048首先在GitHub上发布&#xff0c;原作者是Gabriele Cirulli&#xff0c;后被移植到各个平台。这款游戏是基于《1024》和《小3传奇》的玩法开发而成的新型数字游戏。以下是Python代码…

WPF handyControl 学习样例

​​​​​​​【1.8 HandyControl&#xff1a;80余种控件使用案例】WPF案例代码解析 - 知乎 给大家推荐一个学习handyControl的一个案例&#xff0c;虽然只是一个网站&#xff0c;但里面可以下载源码&#xff0c;&#xff0c; 注意的是&#xff1a;一定要把demo和GalaSoft.M…

G. Best ACMer Solves the Hardest Problem

Problem - G - Codeforces 有一天&#xff0c;一位优秀的ACMer将离开这个领域&#xff0c;面对新的挑战&#xff0c;就像前辈们所做的一样。他们中的一些人接管了家族企业&#xff0c;一些人在失业的边缘挣扎。一些人有勇气展示自己&#xff0c;成为专业的Ingress玩家&#xff…

YMatrix 5 社区版本安装介绍

本文描述YMatrix 5.1版本的安装过程&#xff0c;由于使用的操作系统为CentOS 7&#xff0c;具体步骤参考官网https://www.ymatrix.cn/doc/5.0/install/mx5_cluster/mx5_cluster_centos7 一. 安装准备 1 下载YMatrix社区版安装包 下载地址&#xff1a;https://www.ymatrix.cn…

视频播放器的技术组成

Qt视频播放器实现(目录) 什么是视频 我们这里讲的视频,通常也包括了音频。因为没有声音的画面播放几乎是不可接受的。 这样暗含了一个事实,那就是视频总是包括视频数据和音频数据两部分。 Video 表示视频; Audio 表示音频; 视频播放器播放什么 如同本专栏介绍描述…

python+nodejs+php+springboot+vue 基于数据元标准的教材征订管理系统

教材征订管理系统主要实现角色有管理员和用户,管理员在后台管理学院模块、学生模块、用户表模块、token表模块、教材选定模块、教材入库模块、教材分配模块、教材订购模块、教材模块、配置文件模块、出版社模块。 拟开发的教材征订管理系统通过测试,确保在最大负载的情况下稳定…

比特币 ZK 赏金系列:第 1 部分——支付解密密钥

以前&#xff0c;我们使用零知识赏金 (ZKB) 来支付比特币上的数独解决方案。在本系列中&#xff0c;我们将使用 ZKB 来解决范围更广的更实际的问题。 在第 1 部分中&#xff0c;我们应用 ZKB 来支付解密密钥。假设 Alice 使用对称密钥 K 加密她的文件。为了安全起见&#xff0…

行为树的基本概念和C++库

一 说明 行为树是计算机科学、机器人技术、控制系统和视频游戏中使用的计划执行的数学模型。它们以模块化方式描述一组有限任务之间的切换。他们的优势来自于他们能够创建由简单任务组成的非常复杂的任务&#xff0c;而不用担心简单任务是如何实现的。行为树与分层状​​态机有…

nuxt使用echarts

直接在页面写 bug1&#xff1a;安装包报错&#xff0c;就更换版本 bug2&#xff1a;图表出不来&#xff1a;需要定义宽高 bug3&#xff1a;需要resize大小 安装 npm install echarts4.9.0 plugins文件夹下新建echarts.js import Vue from vue import echarts from echarts /…

Windows 下 MySQL 8.1 图形化界面安装、配置详解

首先我们下载安装包 官方下载链接&#xff1a; MySQL :: Begin Your Download 网盘链接: https://pan.baidu.com/s/1FOew6-93XpknB-bYDhDYPw 提取码: brys 外网下载慢的同学可以使用上述网盘链接 下载完成后我们双击安装包即可进入安装界面 点击next 勾选同意协议&#…

【AIGC】图片生成的原理与应用

前言 近两年 AI 发展非常迅速&#xff0c;其中的 AI 绘画也越来越火爆&#xff0c;AI 绘画在很多应用领域有巨大的潜力&#xff0c;AI 甚至能模仿各种著名艺术家的风格进行绘画。 目前比较有名商业化的 AI 绘画软件有 Midjourney、DALLE2、以及百度出品的文心一格&#xff1a;…

解锁前端Vue3宝藏级资料 第五章 Vue 组件应用 4 ( provide 和 inject )

5.5 provide 和 inject 前面的知识告诉我们vue中组件之间传递值需要使用props来完成&#xff0c;但是props也有一定局限性。这个时候在vue3中还有另外的解决方法。那就是使用 provide 和 inject 允许父组件将数据传递给所有后代组件&#xff0c;而不管组件层次结构有多深。你要…

【linux基础(八)】计算机体系结构--冯诺依曼系统操作系统的再理解

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; 计算机体系结构 1. 前言2. 冯…

eBPF深度探索: 高效DNS监控实现

eBPF可以灵活扩展Linux内核机制&#xff0c;本文通过实现一个DNS监控工具为例&#xff0c;介绍了怎样开发实际的eBPF应用。原文: A Deep Dive into eBPF: Writing an Efficient DNS Monitoring eBPF[1]是内核内置的虚拟机&#xff0c;在Linux内核内部提供了高层库、指令集以及执…