SpringBoot通知机制的实现方式

1. 快速创建maven管理的SpringBoot项目

1、访问 http://start.spring.io/

2、 选择构建工具Maven Project、

Spring Boot版本1.3.6以及一些工程基本信息点击“Switch to the full version.”java版本选择1.7;

3、点击Generate Project下载项目压缩包

4、解压后

使用eclipse,Import -> Existing Maven Projects -> Next ->选择解压后的文件夹-> Finsh,OK done!

使用IDEA的话,按如下步骤导入项目: File -> New -> Project fron Existing Sourses -> 选择解压后的直接包含pom.xml文件的demo文件夹,OK -> 选第二项Import project from external model, 选maven,Next -> Next -> 勾选左下角Open Project Structure after import, Next -> Next -> Finish -> 选Yes -> OK -> 大功告成!

(记录自己踩过的坑:一定要选直接包含pom.xml的demo文件夹,一开始选择直接解压后的demo文件夹,结果找不到可以导入的maven项目。 )

5、 运行刚导入的项目

访问localhost:8080/hello, 看到页面显示Hello World。

6、 在这个demo的基础上进行开发

2. 通知机制的流程

1、客户端向server订阅通知

订阅信息包括通知类型(notificationTypes)、过滤条件(filteringCriteria)、订阅者地址(subscriberUri)和 managerId。

请求数据以json格式发送,因此在服务端用@RequestBody Map request 来处理请求中的json数据,创建JSONObject 对象,从而根据参数名获取请求中传入的参数值。

服务端代码如下:

@RequestMapping("/notifications")
    public void subscribeNotification(@RequestBody Map request, HttpServletResponse response)
            throws ServletException, IOException, JSONException {

        System.out.println("Enter localhost:8083/notifications. " );

        JSONObject jsonObject = new JSONObject(request);
        String subscriptionId = (String) jsonObject.get("subscriptionId");  // 通过JSONObject 对象获取请求中传入的参数值
        String notificationType = (String) jsonObject.get("notificationType");
        String filteringCriteria = (String) jsonObject.get("filteringCriteria");
        String managerId = (String) jsonObject.get("managerId");

        System.out.println("subscriptionId=" + subscriptionId + ", notificationType=" + notificationType + ", filteringCriteria=" + filteringCriteria + ", managerId=" + managerId );

        //  some code...   省略了存数据库的操作

        response.setHeader("Location", "http://localhost:8083/notifications/0101");  // 通过response.setHeader()方法设置响应头
        PrintWriter out = response.getWriter();
        String result = "Success to Subscribe a notification! ";
        out.write(result);
    }

服务端端口设为8083,默认是8080,可以通过在resources 下的application.properties文件里加一条语句server.port=8083 修改为其他端口号。

Postman的接口测试结果如下:

2、服务端将通知发送给客户端

请求信息包括订阅Id(subscriptionId)、通知类型(NotificationType)、发送者Id(producerId)、消息(message)。首先根据subscriptionId 从数据库查找到该订阅的通知类型、过滤条件和订阅者地址,然后判断该通知是否符合订阅条件,符合则将该通知发送给订阅者。

服务端代码如下:

@RequestMapping("/sendNotification")
    public void sendNotification(@RequestBody Map request, HttpServletResponse response)
            throws ServletException, IOException, JSONException {

        System.out.println("request:" + request);

        JSONObject jsonObject = new JSONObject(request);
        System.out.println("jsonObject:" + jsonObject);
        String subscriptionId = (String) jsonObject.get("subscriptionId");
        String notificationType = (String) jsonObject.get("notificationType");
        String producerId = (String) jsonObject.get("producerId");
        String alarmType = (String) jsonObject.getJSONObject("message").get("alarmType");
        System.out.println("subscriptionId=" + subscriptionId + ", notificationType=" + notificationType + ", producerId=" + producerId + ", alarmType=" + alarmType );

        //  some code...  查询数据库(省略)

        // 模拟数据库查询结果
        String getNotificationType = "";
        String getAlarmType = "";
        String getsubscriberUri = "";
        if(subscriptionId.equals("http://localhost:8081/notifications/0101")){
            getNotificationType = "alarm";
            getAlarmType = "01";
            getsubscriberUri = "http://localhost:8081/notifications/001";
        }
        if(subscriptionId.equals("http://localhost:8081/notifications/0102")){
            getNotificationType = "alarm";
            getAlarmType = "02";
            getsubscriberUri = "http://localhost:8082/notifications/001";
        }

        // 判断该通知是否符合订阅条件
        String subscribeURL = "";
        if(notificationType.equals(getNotificationType) && alarmType.equals(getAlarmType)){
            subscribeURL = getsubscriberUri;
        } else return;

        // 建立连接,将通知发送给订阅者
        HttpURLConnection subscribeConnection = null;
        StringBuffer responseBuffer = new StringBuffer();
        try{
            URL getsubscribeURL = new URL(subscribeURL);
            subscribeConnection = (HttpURLConnection) getsubscribeURL.openConnection();  // 建立连接
            subscribeConnection.setDoOutput(true);
            subscribeConnection.setDoInput(true);
            subscribeConnection.setRequestMethod("POST");
            subscribeConnection.setRequestProperty("Accept-Charset", "utf-8");
            subscribeConnection.setRequestProperty("Content-Type", "application/json");
            subscribeConnection.setRequestProperty("Charset", "UTF-8");
            byte[] data = (jsonObject.toString()).getBytes();
            subscribeConnection.setRequestProperty("Content-Length", String.valueOf(data.length));

            // 开始连接请求
            subscribeConnection.connect();
            OutputStream out = subscribeConnection.getOutputStream();
            // 写入请求的字符串
            out.write((jsonObject.toString()).getBytes());  // 发送json数据
            out.flush();
            out.close();
        }catch (IOException e) {
        }
        if (subscribeConnection.getResponseCode() == 200) {    // 若响应码为200,则通知订阅成功
            System.out.println("Success to send the notification." );
            String readLine;
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(
                    subscribeConnection.getInputStream(), "utf-8"));
            while ((readLine = responseReader.readLine()) != null) {
                responseBuffer.append(readLine);
            }
            System.out.println("Http Response:" + responseBuffer);
            subscribeConnection.disconnect();

            PrintWriter out = response.getWriter();
            out.write(responseBuffer.toString());
        }else return;
    }

订阅者(8081端口)接收通知,代码如下:

@RequestMapping("/notifications/001")
    public void receiveNotification(@RequestBody Map request, HttpServletResponse response)
            throws ServletException, IOException{
        System.out.println("Receive a new notification." );
        System.out.println("request:" + request);

        PrintWriter out = response.getWriter();
        String result = "Success to Subscribe a notification! ";
        out.write(result);
    }

3. 运行过程及结果

首先,用Postman 向服务端(8083端口)发送通知:

服务端结果如下:

订阅者(8081端口)结果如下:

附上demo源码地址: https://github.com/bupt-lxl/SpringBoot-Notification

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot事件机制相关知识点汇总

    要"监听"事件,我们总是可以将"监听器"作为事件源中的另一个方法写入事件,但这将使事件源与监听器的逻辑紧密耦合. 对于实际事件,我们比直接方法调用更灵活.我们可以根据需要动态注册和注销某些事件的侦听器.我们还可以为同一事件设置多个侦听器. 本教程概述了如何发布和侦听自定义事件,并解释了 Spring Boot 的内置事件. 为什么我应该使用事件而不是直接方法调用? 事件和直接方法调用都适合于不同的情况.使用方法调用,就像断言一样-无论发送和接收模块的状态如何,他们都

  • 详解在spring boot中消息推送系统设计与实现

    推送系统作为通用的组件,存在的价值主要有以下几点 会被多个业务项目使用,推送系统独立维护可降低维护成本 推送系统一般都是调用三方api进行推送,三方api一般会有调用频率/次数限制,被推送的消息需要走队列来合理调用三方api,控制调用的频率和次数 业务无关,一般推送系统设计成不需要关心业务逻辑 核心技术 消息队列 三方服务api调用 安卓app推送 苹果app推送 微信小程序推送 邮件推送 钉钉推送 短信推送 消息队列选用阿里云提供的rocketmq,官方文档:https://help.aliy

  • Spring的事件监听机制示例详解

    前言 最近公司在重构广告系统,其中核心的打包功由广告系统调用,即对apk打包的调用和打包完成之后的回调,需要提供相应的接口给广告系统.因此,为了将apk打包的核心流程和对接广告系统的业务解耦,利用了spring的事件监听特性来满足需求.以下说明spring的事件机制的相关内容. 首先spring事件分为事件发布者(EventPublisher).事件监听者(EventListener),还包括一个事件广播者(这个是spring实现相关,这一节不讨论).使用spring事件机制,需要自定义事件发布

  • springBoot的事件机制GenericApplicationListener用法解析

    什么是ApplicationContext? 它是Spring的核心,Context我们通常解释为上下文环境,但是理解成容器会更好些. ApplicationContext则是应用的容器. Spring把Bean(object)放在容器中,需要用就通过get方法取出来. ApplicationEvent 是个抽象类,里面只有一个构造函数和一个长整型的timestamp. springboot的event的类型: ApplicationStartingEvent ApplicationEnviro

  • SpringBoot+LayIM+t-io 实现好友申请通知流程

    前言 在上一篇 Spring boot + LayIM + t-io 文件上传. 监听用户状态的实现 中,已经介绍了两个小细节:用户的在离线状态和群人数的状态变化.今天的主要内容就是用户加好友的实现. 简介 加好友,大家用过QQ都知道,无非是发起好友申请,对方收到消息通知,然后处理.不过,本篇只讲前半部分,消息通知的处理留到下一篇去讲.因为内容有点多,怕是一时半会消化不了.在介绍主体流程之前,先给大家介绍一下准备工作. 准备工作 首先,为了让数据更贴近实战,所以我用了比较"真实"的用户

  • 基于springboot 长轮询的实现操作

    springboot 长轮询实现 基于 @EnableAsync , @Sync @SpringBootApplication @EnableAsync public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } @RequestMapping("/async") @RestControlle

  • SpringBoot通知机制的实现方式

    1. 快速创建maven管理的SpringBoot项目 1.访问 http://start.spring.io/ 2. 选择构建工具Maven Project. Spring Boot版本1.3.6以及一些工程基本信息点击"Switch to the full version."java版本选择1.7: 3.点击Generate Project下载项目压缩包 4.解压后 使用eclipse,Import -> Existing Maven Projects -> Next

  • SpringBoot 工程中的异常处理方式

    背景分析 在项目的开发中,不管是对底层的数据逻辑操作过程,还是业务逻辑的处理过程,还是控制逻辑的处理过程,都不可避免会遇到各种可预知的.不可预知的异常.处理好异常对系统有很好的保护作用,同时会大大提高用户的体验. 异常处理分析 概述 Java项目中处理异常方式无非两种,要么执行trycatch操作,要么执行throw操作(抛给其它对象处理),无论采用哪种方式,其目的是让我们的系统对异常要有反馈.但现在的问题是我们如何让这种反馈代码的编写即简单又直观.友好. 处理规范 我们在处理异常的过程中通常要

  • iOS中的通知机制

    网上经常说iOS的通知机制是使用了观察者模式,里面有两个角色,其一是poster(发送者),另一个是observer(接受信息的订阅者).但我认为重要的角色是通知中心,它是整个通知机制的核心,有poster发送者发送的消息必定要到达通知中心,再由通知中心根据这个消息被哪些observer订阅者订阅过,就把消息往那些订阅者去分发.整体可以与现在的电子邮件结构作类比的. 但要额外说明一下,iOS的通知虽然也叫Notification通知,但是与Android中的通知是不一样的,在Android中的通

  • 使用ASP.NET MVC 4 Async Action+jQuery实现消息通知机制的实现代码

    这两天在使用Asp.net MVC 4开发COMET消息通知机制,在后端使用异步线程对消息进行订阅,客户端通过AJAX长连接请求MVC中的ACTION,如:http://localhost/event/imageSet,即表示获取ImageSet对象的变更消息(新增,更新和删除消息). 1.事件消息的类IEventEntity<TEntity>类的定义 复制代码 代码如下: public interface IEntityEvent<TEntity>    {        //变

  • SpringBoot Jpa分页查询配置方式解析

    这篇文章主要介绍了SpringBoot Jpa分页查询配置方式解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 这是已经被废弃的接口 Sort sort = new Sort(Sort.Direction.DESC,"bean类中字段"); //创建时间降序排序 Pageable pageable = new PageRequest(pageNumber,pageSize,sort); 上面的用法在最新的SpringBoot中已经不

  • 关于Springboot日期时间格式化处理方式总结

    项目中使用LocalDateTime系列作为DTO中时间的数据类型,但是SpringMVC收到参数后总报错,为了配置全局时间类型转换,尝试了如下处理方式. 注:本文基于Springboot2.x测试,如果无法生效可能是spring版本较低导致的.PS:如果你的Controller中的LocalDate类型的参数啥注解(RequestParam.PathVariable等)都没加,也是会出错的,因为默认情况下,解析这种参数是使用ModelAttributeMethodProcessor进行处理,而

  • 手把手教你SpringBoot过滤器N种注册方式

    要说在 Spring Boot 中注册过滤器有三种方式,你都能想到哪些呢?今天松哥就来和大家聊一聊 Spring Boot 中注册过滤器的三种方式! 其实本来是想和大家聊 Spring Security 过滤器链的问题的,结果看源码看着看着就跑题了,索性就先和大家聊一聊 Spring Boot 中注册过滤器的三种方式,算是给 后面的 Spring Security 打一点基础. 1.@WebFilter 通过 @WebFilter 注解来标记一个过滤器,这种方式相信大家很容易想到.这是将 Ser

  • springboot+quartz以持久化的方式实现定时任务的代码

    这篇文章给大家介绍springboot+quartz以持久化的方式实现定时任务,详情如下所示: 篇幅较长,耐心的人总能得到最后的答案小生第一次用quartz做定时任务,不足之处多多谅解. 首先 在springboot项目里做定时任务是比较简单的,最简单的实现方式是使用**@Scheduled注解,然后在application启动类上使用@EnableScheduling**开启定时任务. 示例 @SpringBootApplication @EnableScheduling public cla

  • java(包括springboot)读取resources下文件方式实现

    本文主要介绍了java(包括springboot)读取resources下文件方式实现,分享给大家,具体如下: 1.使用项目内路径读取,该路径只在开发工具中显示,类似:src/main/resources/resource.properties.只能在开发工具中使用,部署之后无法读取.(不通用) File file = new File("src/main/resources/resource.properties"); @Test public void testReadFile2(

  • springBoot加入thymeleaf模板的方式

    1.新建springBoot项目 在前面有两种方式 2.加入thymeleaf模板引擎 SpringBoot推荐使用thymeleaf模板引擎 语法简单,功能更强大 要想引入thymeleaf,只需要在pom,xml文件中加入如下依赖就可以了 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifa

随机推荐