【RabbitMQ】显示耗时处理进度
【RabbitMQ】显示耗时处理进度
通过网页提交一个耗时的请求,然后启动处理线程,请求返回。处理线程每完成一部分就给前台推送完成的数量,前端显示进度。
依赖jar
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>rabbitmq-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rabbitmq-service</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>
配置
server.port=
spring.application.name=rabbitmq-service
spring.rabbitmq.host=192.168.226.128
spring.rabbitmq.port=
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
主入口
@SpringBootApplication
public class RabbitmqServiceApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitmqServiceApplication.class, args);
}
}
RabbitMQ配置
package com.example.rabbitmqservice.config; import lombok.Data;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope; @Data
@Configuration
@ConfigurationProperties(prefix = "spring.rabbitmq")
public class RabbitMQConfig {
private String host;
private int port;
private String username;
private String password; @Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host,port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost("/");
connectionFactory.setPublisherConfirms(true);
return connectionFactory;
} @Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate rabbitTemplate() {
return new RabbitTemplate(connectionFactory());
}
}
处理RabbitMQ配置
package com.example.rabbitmqservice.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; @Configuration
public class RabbitMQConfigProcess { public static final String PROCESS_DIRECT_EXCHANGE = "process.direct.exchange";
public static final String PROCESS_QUEUE = "process.queue";
public static final String PROCESS_KEY = "process.key"; @Bean
public DirectExchange processDirectExchange() {
return new DirectExchange(PROCESS_DIRECT_EXCHANGE, true, false);
} @Bean
public Queue processQueue() {
return new Queue(PROCESS_QUEUE, true, false, false);
} @Bean
public Binding processBinding() {
return BindingBuilder.bind(processQueue()).to(processDirectExchange()).with(PROCESS_KEY);
}
}
WebSocket配置
package com.example.rabbitmqservice.config; import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration
@EnableWebSocket
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { public static final String END_POINT = "/websocket"; @Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint(END_POINT)
.setAllowedOrigins("*")
.withSockJS()
.setHeartbeatTime(5000)
.setDisconnectDelay(3000)
.setStreamBytesLimit(512);
}
}
消息接收转发
package com.example.rabbitmqservice.receive; import com.example.rabbitmqservice.config.RabbitMQConfigProcess;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component; @Component
@RabbitListener(queues = RabbitMQConfigProcess.PROCESS_QUEUE)
public class ProcessReceive {
@Autowired
private SimpMessagingTemplate messagingTemplate; @RabbitHandler
public void process(String content) {
System.out.println("收到并转发消息 > " + content);
messagingTemplate.convertAndSend("/direct/process/", content);
}
}
请求处理
package com.example.rabbitmqservice.controller; import com.example.rabbitmqservice.config.RabbitMQConfigProcess;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.time.LocalTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; @RestController
public class ProcessController {
@Autowired
private RabbitTemplate rabbitTemplate; ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 40, 2, TimeUnit.MINUTES, new LinkedBlockingDeque<>()); @RequestMapping("/process/direct")
public Map<String, Object> direct() { Runnable runnable = () -> process();
executor.execute(runnable); Map<String, Object> result = new HashMap<>();
result.put("status", 200);
result.put("message", "开始处理");
return result;
} private void process() {
// 模拟耗时处理
for (int i = 1; i <= 100; i++) {
String msg = String.valueOf(i);
rabbitTemplate.convertAndSend(RabbitMQConfigProcess.PROCESS_DIRECT_EXCHANGE, RabbitMQConfigProcess.PROCESS_KEY , msg,
// 消息到达broker时调用confirm callback。若是cluster则到达所有的broker时调用confirm callback。
message -> {
// 投递模式2
message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
System.out.println("confirm callback");
return message;
}, new CorrelationData("123")); rabbitTemplate.setMandatory(true);//开启强制委托模式
// 没有投递到目标队列时调用return callback
rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
System.out.println("return callback");
System.out.println("没有投递到目标队列");
}); // 模拟耗时
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
}
前端html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="js/sockjs.js"></script>
<script type="text/javascript" src="js/stomp.js"></script>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/axios.min.js"></script>
</head>
<body>
<div id="app">
<span v-text="message"></span>
<button type="button" @click="startMock">开始模拟</button>
<span v-text="process"></span>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
process: '',
message: '点击开始模拟'
},
methods: {
startMock: function() {
var _this = this;
var query = {};
this.requestProcess(query).then(response => {
console.log('返回');
console.dir(response);
}).then(error => {
console.log('出错');
console.dir(error);
});
},
requestProcess(query) {
return new Promise((resolve, reject) => {
axios({
url: 'http://localhost:8088/process/direct',
method: 'get',
params: query
}).then(response => {
resolve(response);
//_this.message = response.data.message;
}).catch(error => {
reject(error);
});
});
},
displayProcess: function() {
var _this = this;
console.log('displayProcess');
var sock = new SockJS("http://localhost:8088/websocket");
var stompClient = Stomp.over(sock);
stompClient.connect({}, function () {
stompClient.subscribe('/direct/process/', function (data) {
console.dir(data);
_this.process = data.body + '%';
}, {precessId: 123});
});
sock.onclose = function () {
console.dir("websocket已经断开连接");
// 断开五秒后重连
setTimeout(function () {
_this.displayProcess();
}, 5000);
}
}
},
mounted: function() {
this.displayProcess();
}
});
</script>
</body>
</html>
【RabbitMQ】显示耗时处理进度的更多相关文章
- 使用afinal下载文件并且在状态栏中显示下载的进度
2013年10月23日,今天是在“我在找你信息服务有限公司”第一天上班,公司给提出了这样一个要求:下载本公司的app,并且在下载的过程中要在状态栏中显示下载的进度,并且,可以暂停和继续下载. 下面是我 ...
- jsp实时显示后台批处理进度 - out分块,简单的长连接方式
这两天在实现一个批处理操作,但是想让前台实时显示后台批处理进度,本想着用复杂一些的框架可以实现异步信息调用 但是鉴于是内部管理系统,且只有一两个人用到这个功能,所以做了一个简单的长连接方式的实时响应 ...
- delphi之完美Splash方案(在TfrmMain.FormCreate里不断调用TfrmSplash显示加载进度文字,并且及时Update显示)
前言:网上有很多介绍delphi创建闪屏的代码,大多只是在程序开启前显示一个闪屏,但是却没有说如何在闪屏上显示程序加载的进度,于是笔者有意思介绍一下这种闪屏方式. 1.创建一个窗体(TfrmSplas ...
- js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面
js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面 , 做手机端开发时,发现一个问题,有些浏览器,在网速比较慢的情况下,js文件没有加载完,后续的调用已经开始调用了, ...
- Asp.Net MVC页面显示后台处理进度问题
这个问题的背景是,用户通过浏览器上传文件或Excel数据到系统中,页面需要时时显示后台处理进度,以增强用户的体验. 在GitHub上找到一个一个项目,基本实现了这个功能,具体效果如下图 代码实现过程大 ...
- [Swift通天遁地]四、网络和线程-(9)上传图片并实时显示上传进度
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 2.WP8.1开发_在顶部显示标题和进度
有时候加载页面的时候,需要在信号那一栏显示进度,或者把信号栏改成标题 1.确保显示状态栏.默认显示.如果不显示,可以在应用程序启动后手动用代码显示,代码如下: //取得状态栏 StatusBar ba ...
- LODOP打印URL显示和隐藏进度条
不建议使用ADD_PRINT_URL:由于Lodop借用IE下载引擎,与非IE浏览器之间目前不能传递Session(Cookies),所以需要安全验证的页面不要用URL方式打印,要用页面已经下载好的内 ...
- uploadify实现七牛云存储 显示上传进度+页面显示
准备: uploadify下载地址: http://www.uploadify.com/download/ 七牛 php-sdk开发指南: http://developer.qiniu.com/doc ...
随机推荐
- Github相关知识
github的提交流程 mkdir 目录名 :创建一个空文件夹 mkdir webs webs代表创建的新文件名称 cd 目录名 :切换到文件夹 cd webs 切换到当前新建的目录下 ...
- mysql初级了解
mysql是一个关系型数据库系统,可以存放若干个数据库,每个数据库中 可以存放若干张表,每张表中可以存放若干条记录 基本代码: 1.查看数据库 show databases: 2.创建数据库 ...
- 反汇编分析objc函数枢纽objc_msgSend
在分析objc_msgSend之前,先来搞清楚另一个问题. 函数是什么?可能会答 void foo(void) {} 像这样就是一个函数.或者函数包括函数原型和函数定义,是一段执行某样功能的机器代码. ...
- 装饰者模式学习:模拟咖啡馆的点单系统来剖析装饰者模式的使用 + 装饰者模式在java I/O 中的应用
通过模拟咖啡馆的点单系统来剖析装饰者模式的使用 参考:https://blog.csdn.net/gududedabai/article/details/81989196 一).传统的点单系统构建,每 ...
- 第一解出的pwn题
虽然题目不难,但是 是我第一次做出的pwn题,得写下. __int64 sub_4007E6() { char s1; // [sp+0h] [bp-30h]@1 memset(&s1, , ...
- Flutter学习笔记(30)--Android原生与Flutter混编
如需转载,请注明出处:Flutter学习笔记(30)--Android原生与Flutter混编 这篇文章旨在学习如何在现有的Android原生项目上集成Flutter,实现Android与Flutte ...
- vue 安装指令
vue init webpack 项目名 创建项目cd 项目名 打开项目 npm install vuex --save 安装vuex在一个模块化的打包系统中,您必须显式地通过 Vue.use() 来 ...
- python--数字灯管
import turtle import time def drawLine(draw): #绘制单段数码管 turtle.pendown() if draw else turtle.penup() ...
- 题解 P2669 【金币】
似乎我这个"蒟蒻"跟各位DALAO想的不太一样 首先,输入n,使用一层循环搞定 具体思路: 使用ans作为累加器,k记录发几枚金币,s负责不断赋值给累加器,sum当这些天数的金币发 ...
- 用IDCNN和CRF做端到端的中文实体识别
实体识别和关系抽取是例如构建知识图谱等上层自然语言处理应用的基础.实体识别可以简单理解为一个序列标注问题:给定一个句子,为句子序列中的每一个字做标注.因为同是序列标注问题,除去实体识别之外,相同的技术 ...