RabbitMQ实战场景(一):异步记录用户操作日志
传统的项目开发中业务流程以串行方式,执行了模块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实战场景(一):异步记录用户操作日志的更多相关文章
- springAOP记录用户操作日志
项目已经开发完成,需要加用户操作日志,如果返回去加也不太现实,所以使用springAOP来完成比较合适. 注解工具类: @Retention(RetentionPolicy.RUNTIME) @Tar ...
- ssm 项目记录用户操作日志和异常日志
借助网上参考的内容,写出自己记录操作日志的心得!! 我用的是ssm项目使用aop记录日志:这里用到了aop的切点 和 自定义注解方式: 1.建好数据表: 数据库记录的字段有: 日志id .操作人.操作 ...
- Spring AOP使用注解记录用户操作日志
最后一个方法:核心的日志记录方法 package com.migu.cm.aspect; import com.alibaba.fastjson.JSON; import com.migu.cm.do ...
- linux 记录用户操作日志
将以下加入到/etc/profile 最后 history USER_IP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]/ ...
- SpringSecurity权限管理系统实战—八、AOP 记录用户、异常日志
目录 SpringSecurity权限管理系统实战-一.项目简介和开发环境准备 SpringSecurity权限管理系统实战-二.日志.接口文档等实现 SpringSecurity权限管理系统实战-三 ...
- mysql颠覆实战笔记(三)-- 用户登录(二):保存用户操作日志的方法
版权声明:笔记整理者亡命小卒热爱自由,崇尚分享.但是本笔记源自www.jtthink.com(程序员在囧途)沈逸老师的<web级mysql颠覆实战课程 >.如需转载请尊重老师劳动,保留沈逸 ...
- 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录
在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...
- 基于SqlSugar的开发框架循序渐进介绍(8)-- 在基类函数封装实现用户操作日志记录
在我们对数据进行重要修改调整的时候,往往需要跟踪记录好用户操作日志.一般来说,如对重要表记录的插入.修改.删除都需要记录下来,由于用户操作日志会带来一定的额外消耗,因此我们通过配置的方式来决定记录那些 ...
- [编码实践]SpringBoot实战:利用Spring AOP实现操作日志审计管理
设计原则和思路: 元注解方式结合AOP,灵活记录操作日志 能够记录详细错误日志为运营以及审计提供支持 日志记录尽可能减少性能影响 操作描述参数支持动态获取,其他参数自动记录. 1.定义日志记录元注解, ...
随机推荐
- 性能测试分析过程(二)cpu 使用率过高的分析方法
Linux 系统下 cpu 使用率过高的分析方法 1.通过 top 命令可以很明显查看出哪个进程耗cpu比较高 2. ps -mp 25147-o THREAD,tid,time\top -Hp pi ...
- Electron 入门第一篇
官网:http://electronjs.org/docs/tutorial/application-architecture 转载:https://blog.csdn.net/qq_33323731 ...
- Nginx 配置 stream SSL 第四层 代理
场景:服务器F针对访问终端需要添加白名单操作,由到终端数量较多,所以用了一台代理服务器 P,在服务F中添加 服务器P IP地址的白名单,所有终端访问服务器P 由于我已经安装过 Nginx 所以只需要添 ...
- docker卷挂载与容器内外互相拷贝数据
一.宿主机与容器的挂载 docker可以支持把一个宿主机上的目录挂载到镜像里.命令如下: docker run -it -v /mydownload:/download nginx:v1 /bin/b ...
- 基于Emit的C#下DataTable转实体类方法,一直报错.
xxxx ;WITH Tab AS ( SELECT CAST(ROW_NUMBER()OVER(ORDER BY CC.CreateTime DESC) AS INT) AS Sequency, ) ...
- 基于EasyNVR摄像机流媒体服务器实现RTSP或Onvif监控摄像头Web无插件化直播监控
前言介绍 随着互联网的发展,尤其是移动互联网基于H5.微信的应用越来越多,企业也更多地想基于H5.微信公众号来快速开发和运营自己的产品,而传统的安防IPC所输出的各种RTSP.GB28181.SDK视 ...
- [LeetCode] 282. Expression Add Operators 表达式增加操作符
Given a string that contains only digits 0-9 and a target value, return all possibilities to add bin ...
- Java之第一个Java程序
编写第一个Java程序 打开文本编辑器,输入以下代码 public class Hello { public static void main(String[] args) { System.out. ...
- Component 'TABCTL32.OCX'错误的处理方法
错误:Component 'TABCTL32.OCX' or one of its dependencies not correctyly registered:a file is missing o ...
- .Net Core 定时任务TimeJob
转载自:https://blog.csdn.net/u013711462/article/details/53449799 定时任务 Pomelo.AspNetCore.TimedJob Pomelo ...