传统的项目开发中业务流程以串行方式,执行了模块1—》模块2–》模块3

  而我们知道,这个执行流程其实对于整个程序来讲是有一定的弊端的,主要有几点:

  (1)整个流程的执行响应等待时间比较长;

  (2)如果某一个模块发生异常,可能会影响其他 模块甚至整个系统的执行流程与结果;

  (3)程序的代码上造成冗余,模块与模块需要进行强通信以及数据的交互,出现问题时难以定位与维护。耦合度过高!

  因此需要进行优化,将强关联的业务模块解耦以及某些模块之间实行异步通信!

  下面我将通过一些实际案例来进行一个介绍

  一、异步记录用户操作日志

  用户操作日志对于每一个系统来说是不可或缺的,并且操作日志应该单独抽取为一个模块业务,不应该与主业务系统之间耦合在一起。

  故而我们需要将其单独抽出并以异步的方式与主模块进行异步通信交互数据。

  要求:采用 RabbitMQ 的 DirectExchange+RoutingKey 消息模型来实现【异步记录用户操作日志】

  前提:SpringBoot与RabbitMQ的整合前面章节已经讲述过了,就不再重述了。

  第一步:创建消息模型:包括 Queue、Exchange、RoutingKey 等的建立

  package com.springboot.rabbitmq.example.demo1.config;

  import org.springframework.amqp.core.Binding;

  import org.springframework.amqp.core.BindingBuilder;

  import org.springframework.amqp.core.DirectExchange;

  import org.springframework.amqp.core.Queue;

  import org.springframework.context.annotation.Bean;

  import org.springframework.context.annotation.Configuration;

  /**

  *

  * Direct Exchange(路由模式)—异步记录用户操作日志

  * @author Mr yi

  * @time 2019年6月19日

  */

  @Configuration

  public class RabbitConfigDemo1 {

  //消息队列名称

  final static String queue = "queue_demo1";

  /**

  * 交换机名称

  */

  final static String exchange = "deom1Exchange";

  @Bean

  public Queue queueDemo1() {

  return new Queue(RabbitConfigDemo1.queue);

  }

  /**

  *

  * @method 声明一个direct类型的交换机

  * @author Mr yi

  * @time 2019年6月19日

  * @return

  */

  @Bean

  DirectExchange exchangeDemo1() {

  return new DirectExchange(RabbitConfigDemo1.exchange);

  }

  /**

  *

  * @method 绑定Queue队列到交换机,并且指定routingKey

  * @author Mr yi

  * @time 2019年6月19日

  * @param queueDemo1 对应注入queueDemo1()方法

  * @param exchangeDemo1 对应exchangeDemo1()

  * @return

  */

  @Bean

  Binding bindingDirectExchangeDemo1(Queue queueDemo1, DirectExchange exchangeDemo1) {

  return BindingBuilder.bind(queueDemo1).to(exchangeDemo1).with("keyDemo1");

  }

  }

  第二步:创建生产者,这里的生产者负责发送用户日志信息到rabbitmq

  其中需要建立User 用户实体类、UserLog用户日志实体类,这里就不介绍了。

  注意一点:rabbitmq消息队列可以接受任何形式的消息数据。

  package com.springboot.rabbitmq.example.demo1.producers;

  import org.springframework.amqp.core.AmqpTemplate;

  import org.springframework.beans.factory.annotation.Autowired;

  import org.springframework.stereotype.Component;

  import com.springboot.rabbitmq.example.demo1.entity.UserLog;

  /**

  *

  * @method 生产者

  * @author Mr yi

  * @time 2019年6月19日

  */

  @Component

  public class ProducersDemo1 {

  @Autowired

  private AmqpTemplate amqpTemplate;

  /**

  *

  * @method 生产者发送消息,direct模式下需要传递一个routingKey

  * @author Mr yi

  * @time 2019年6月19日

  * @throws Exception

  */

  public void send(UserLog userLog) throws Exception {

  System.out.println("发送用户日志信息到rabbitmq: " + userLog.toString());

  this.amqpTemplate.convertAndSend("deom1Exchange", "keyDemo1", userLog);

  }

  }

  第三步:创建消费者,即接受到rabbitmq传过来的消息后进行操作(如持久化用户日志信息)

  我这里只提供了核心代码,如持久化操作模拟执行即可。

  package com.springboot.rabbitmq.example.demo1.consumers;

  import java.util.Date;

  import org.springframework.amqp.rabbit.annotation.RabbitHandler;

  import org.springframework.amqp.rabbit.annotation.RabbitListener;

  import org.springframework.stereotype.Component;

  import com.springboot.rabbitmq.example.demo1.entity.UserLog;

  /**

  *

  * @method 抽离日志系统为一个消费者

  * @author Mr yi

  * @time 2019年6月19日

  */

  @Component

  @RabbitListener(queues = "queue_demo1")

  public class ConsumersLogDemo1 {

  @RabbitHandler

  public void process(UserLog userLog) {

  System.out.println("log_name="+userLog.getLog_name());

  System.out.println("user_name="+userLog.getUser_name());

  System.out.println("log_type="+userLog.getLog_type());

  //将日志信息进行持久化操作(这里没有写操作数据库方法,模拟执行)

  //save(userLog);无锡人流多少钱 http://www.bhnfkyy.com/

  System.out.println("用户日志成功录入!");

  }

  }

  第四步:在 Controller 中执行用户登录逻辑

  我们这里模拟用户登录操作,用户登录后,会发送用户登录操作日志到rabbitmq队列中,由绑定了此队列的消费者(即用户日志模块系统)接受消息

  package com.springboot.rabbitmq.example.demo1.controller;

  import org.springframework.beans.factory.annotation.Autowired;

  import org.springframework.stereotype.Controller;

  import org.springframework.web.bind.annotation.RequestMapping;

  import com.springboot.rabbitmq.example.demo1.entity.UserLog;

  import com.springboot.rabbitmq.example.demo1.producers.ProducersDemo1;

  import lombok.extern.slf4j.Slf4j;

  @Controller

  @Slf4j

  @RequestMapping("/userdemo1")

  public class UserController {

  @Autowired

  private ProducersDemo1 producers;

  @RequestMapping("/login")

  public String login() throws Exception {

  String user_name = "admin";

  String pwd = "123456";

  if(user_name=="admin" && pwd=="123456") {

  log.info("用户登录成功!");

  UserLog userLog = new UserLog();

  userLog.setLog_name("用户登录").setLog_type("login").setUser_name(user_name);

  producers.send(userLog);

  log.info("异步记录用户操作日志!");

  }

  return "success";

  }

  }

  控制台数据结果

  队列

  队列绑定的routing key

  exchange交换机

RabbitMQ实战场景(一):异步记录用户操作日志的更多相关文章

  1. springAOP记录用户操作日志

    项目已经开发完成,需要加用户操作日志,如果返回去加也不太现实,所以使用springAOP来完成比较合适. 注解工具类: @Retention(RetentionPolicy.RUNTIME) @Tar ...

  2. ssm 项目记录用户操作日志和异常日志

    借助网上参考的内容,写出自己记录操作日志的心得!! 我用的是ssm项目使用aop记录日志:这里用到了aop的切点 和 自定义注解方式: 1.建好数据表: 数据库记录的字段有: 日志id .操作人.操作 ...

  3. Spring AOP使用注解记录用户操作日志

    最后一个方法:核心的日志记录方法 package com.migu.cm.aspect; import com.alibaba.fastjson.JSON; import com.migu.cm.do ...

  4. linux 记录用户操作日志

    将以下加入到/etc/profile 最后 history USER_IP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]/ ...

  5. SpringSecurity权限管理系统实战—八、AOP 记录用户、异常日志

    目录 SpringSecurity权限管理系统实战-一.项目简介和开发环境准备 SpringSecurity权限管理系统实战-二.日志.接口文档等实现 SpringSecurity权限管理系统实战-三 ...

  6. mysql颠覆实战笔记(三)-- 用户登录(二):保存用户操作日志的方法

    版权声明:笔记整理者亡命小卒热爱自由,崇尚分享.但是本笔记源自www.jtthink.com(程序员在囧途)沈逸老师的<web级mysql颠覆实战课程 >.如需转载请尊重老师劳动,保留沈逸 ...

  7. 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

    在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...

  8. 基于SqlSugar的开发框架循序渐进介绍(8)-- 在基类函数封装实现用户操作日志记录

    在我们对数据进行重要修改调整的时候,往往需要跟踪记录好用户操作日志.一般来说,如对重要表记录的插入.修改.删除都需要记录下来,由于用户操作日志会带来一定的额外消耗,因此我们通过配置的方式来决定记录那些 ...

  9. [编码实践]SpringBoot实战:利用Spring AOP实现操作日志审计管理

    设计原则和思路: 元注解方式结合AOP,灵活记录操作日志 能够记录详细错误日志为运营以及审计提供支持 日志记录尽可能减少性能影响 操作描述参数支持动态获取,其他参数自动记录. 1.定义日志记录元注解, ...

随机推荐

  1. 011 @Retryable的使用

    一:概述 在调用第三方接口或者使用mq时,会出现网络抖动,连接超时等网络异常,所以需要重试. 为了使处理更加健壮并且不太容易出现故障,后续的尝试操作,有时候会帮助失败的操作最后执行成功. 例如,由于网 ...

  2. thinkphp---404错误页面

    在用thinkphp开发项目的时候,会额外的处理404错误页面,但是我们很多的开发人员,在处理404错误页面的时候,处理方式都是不对的. 普通处理404的操作是通过 $this->error() ...

  3. spring cloud Eureka server 问题 Spring Cloud java.lang.TypeNotPresentException

    版本: spring-cloud.version : Greenwich.SR2 pom配置: <project xmlns="http://maven.apache.org/POM/ ...

  4. SEO前端篇(一)页面布局

    由于工作需要,在此对seo的一些相关知识做一个总结. 首先要了解必要的基础知识,什么是SEO以及搜索引擎的工作原理.这样才能继续下面的话题. 一.SEO定义 SEO全称:Search English ...

  5. matlab学习笔记9 高级绘图命令_2 图形的高级控制_视点控制和图形旋转_色图和颜色映像_光照和着色

    一起来学matlab-matlab学习笔记9 高级绘图命令_2 图形的高级控制_视点控制和图形旋转_色图和颜色映像_光照和着色 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 < ...

  6. matlab学习笔记6--性能剖析

    一起来学matlab-matlab学习笔记6 性能剖析 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等著 感谢张老师的书籍, ...

  7. depth wise CNN

    depth wise cnn相对于传统的CNN,区别在于:它是逐通道做卷积操作! 例子如下: (1)使用传统卷积,输入:H*W*C_in,最终输出h*w*C_out:卷积核尺寸为K*K*C_in*C_ ...

  8. [LeetCode] 741. Cherry Pickup 捡樱桃

    In a N x N grid representing a field of cherries, each cell is one of three possible integers. 0 mea ...

  9. 【计算机视觉】【神经网络与深度学习】YOLO v2 detection训练自己的数据2

    1. 前言 关于用yolo训练自己VOC格式数据的博文真的不少,但是当我按照他们的方法一步一步走下去的时候发现出了其他作者没有提及的问题.这里就我自己的经验讲讲如何训练自己的数据集. 2.数据集 这里 ...

  10. Javaweb的概念与C/S、B/S体系结构

    大家好,乐字节的小乐又来了,今天的文章是接上次<客户端请求服务器端通信, Web 编程发展基础|乐字节>,这次是讲述Javaweb的介绍和C/S.B/S体系结构. 一.Javaweb的概念 ...