导入依赖
<!--rabbitmq java客户端依赖-->
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
配置文件
#RabbitMQ
rabbitmq:
#服务器
host: 127.0.0.1
#用户名
username: guest
#密码
password: guest
#虚拟主机
virtual-host: /
#端口
port: 5672
listener:
simple:
#消费者最小数量
concurrency: 10
#消费者最大数量
max-concurrency: 10
#限制消费者每次只能处理一条消息,处理完在继续下一条消息
prefetch: 1
#启动是默认启动容器
auto-startup: true
#被拒绝时重新进入队列
default-requeue-rejected: true
template:
retry:
#发布重试,默认false
enabled: true
#重试时间,默认1000ms
initial-interval: 1000ms
#重试最大次数,默认3次
max-attempts: 3
#最大重试间隔时间
max-interval: 10000ms
#重试的间隔乘数,比如配2.0 第一次等10s 第二次等20s 第三次等40s
multiplier: 1
生产者代码
package com.itheima.producer;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
//简单模式
//发送消息
public class Producer_HelloWorld {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
//2.设置参数
factory.setHost("192.168.101.22");//ip地址 默认localhost
factory.setPort(5672);//端口 默认值5672
factory.setVirtualHost("/itcast");//虚拟机默认值 /虚拟机
factory.setUsername("heima");//用户名 默认guest
factory.setPassword("heima");//密码 默认guest
//3.创建连接 connection
Connection connection = factory.newConnection();
//4.创建信道
Channel channel = connection.createChannel();
/*
*创建交换机
*1.交换机名称
*2.交换机类型,direct,topic,fanout,headers
*3.指定交换机是否需要持久化,如果设置为true,那么交换机的元数据要持久化
*4.指定交换机在没有队列绑定时,是否需要删除,设置false表示不删除
*5.Map<String,Object>类型,用来指定我们交换机其他的一些机构化参数,我们这里直接设置成null
*/
channl.exchangeDeclare("xc_exchange_name",BulitinExchangeType.DIRECT,true,false,null);
//5.创建队列Queue
/*
String queue, boolean durable, boolean exclusive, boolean autoDelete,
Map<String, Object> arguments)
1.queue 队列名称
2.durable 是否持久化,当mq重启之后,还在 —— 这里的持久化只是队列名称等这些元素数据的持久化,不是队列中消息的持久化
3.exclusive:表示队列是不是私有的,如果是私有的,只有创建他的应用程序才能消费消息
*是否独占:只能有一个消费者监听队列
*当connection关闭时,是否删除队列
4.autoDelete: 是否自动删除,当没有消费者订阅的情况下consumer时,自动删除掉
5.arguments: 队列的一些结构化信息,比如声明死信队列,磁盘队列会用到
*/
//如果没有一个名字为hello_world的队列,则会创建队列,如果有则不会创建
channel.queueDeclare("hello_world",true,false,false,null);
/*将队列和交换机绑定
*1.路由键,这里是队列名称
*2.交换机名称
*3.路由键,在直连模式下,可以为我们的队列名称
*/
channel.queueBind("hello_world","xc_exchange_name","hello_world");
//6.发送消息
/*
String exchange, String routingKey, boolean mandatory, byte[] body
参数:
1. exchange:交换机名称,简单模式下交换机会使用默认的 ""
2. 队列名称
3. props: 配置信息
4. body: 发送消息数据
*/
String body="hello rabbitmq----";
channel.basicPublish("xc_exchange_name","hello_world",null,body.getBytes());
//7.释放资源
channel.close();
connection.close();
}
}
消费者
package com.itheima.producer;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
//简单模式
//发送消息
public class Consumer_HelloWorld {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory=new ConnectionFactory();
//2.设置参数
factory.setHost("192.168.101.22");//ip地址 默认localhost
factory.setPort(5672);//端口 默认值5672
factory.setVirtualHost("/itcast");//虚拟机默认值 /虚拟机
factory.setUsername("heima");//用户名 默认guest
factory.setPassword("heima");//密码 默认guest
//3.创建连接 connection
Connection connection = factory.newConnection();
//4.创建信道
Channel channel = connection.createChannel();
//接收消息的回调函数
DeliverCallback deliverCallback = (consumerTage,message) -> {
System.out.println("接收到消息" + new String(message.getBody()));
};
//取消消息的回调函数
CancelCallback cancelCallback = consumerTage -> {
System.out.println("消费消息被中断");
};
/*
*消费消息
*1.消费哪个队列
*2.消费成功之后是否需要自动应答,true:自动应答
*3.接受消息的回调函数
*4.取消消息的回调函数
*/
channel.basicConsume("hello_world",true,deliverCallback,cancelCallback);
}
}
交换机类型
direct
同一个key (路由键) 可以绑定多个queue队列,当匹配到key1时,与key1绑定的queue1和queue2都可以接收到消息
fanout
Fanout,扇出类型交换机,此种交换机,会将消息发布给所有绑定了此交换机的队列,此时RoutingKey (路由键参数)无效
topic
主题类型交换机,与direct类似,也是需要routingkey路由键进行匹配分发,区别在于topic可以进行模糊匹配,direct是精确匹配
- 将routingkey通过" . "分为多个部分
- " * "代表一个部分
- " # "代表0个或多个部分(如果绑定的路由键为 " # " 时,则接收所有消息,因为路由键所有都匹配)
Headers
与direct交换机完全一致,但是性能差很多不用了
package com.example.seckilldemo.rabbitmq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 消息发送者
*
* @author: LC
* @date 2022/3/7 7:42 下午
* @ClassName: MQSender
*/
@Service
@Slf4j
public class MQSender {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送秒杀信息
* @author LiChao
* @operation add
* @date 6:44 下午 2022/3/8
* @param message
* @return void
**/
public void sendSeckillMessage(String message) {
log.info("发送消息" + message);
rabbitTemplate.convertAndSend("seckillExchange", "seckill.message", message);
}
public void send(Object msg) {
log.info("发送消息:" + msg);
// rabbitTemplate.convertAndSend("queue", msg);
rabbitTemplate.convertAndSend("fanoutExchange", "", msg);
}
//
//
// public void send01(Object msg) {
// log.info("发送red" + msg);
// rabbitTemplate.convertAndSend("directExchange", "queue.red", msg);
// }
//
// public void send02(Object msg) {
// log.info("发送red" + msg);
// rabbitTemplate.convertAndSend("directExchange", "queue.green", msg);
// }
//
//
// public void send03(Object msg) {
// log.info("发送消息(QUEUE01接收):" + msg);
// rabbitTemplate.convertAndSend("topicExchange", "queue.red.message", msg);
// }
//
//
// public void send04(Object msg) {
// log.info("发送消息(QUEUE02接收):" + msg);
// rabbitTemplate.convertAndSend("topicExchange", "green.queue.green.message", msg);
// }
//
//
// public void send05(String msg) {
// log.info("发送消息(QUEUE01和QUEUE02接收):" + msg);
// MessageProperties properties = new MessageProperties();
// properties.setHeader("color", "red");
// properties.setHeader("speed", "fast");
// Message message = new Message(msg.getBytes(), properties);
// rabbitTemplate.convertAndSend("headersExchange", "", message);
// }
//
// public void send06(String msg) {
// log.info("发送消息(QUEUE01接收):" + msg);
// MessageProperties properties = new MessageProperties();
// properties.setHeader("color", "red");
// properties.setHeader("speed", "normal");
// Message message = new Message(msg.getBytes(), properties);
// rabbitTemplate.convertAndSend("headersExchange", "", message);
// }
}
package com.example.seckilldemo.rabbitmq;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.seckilldemo.entity.TSeckillOrder;
import com.example.seckilldemo.entity.TUser;
import com.example.seckilldemo.service.ITGoodsService;
import com.example.seckilldemo.service.ITOrderService;
import com.example.seckilldemo.service.ITSeckillOrderService;
import com.example.seckilldemo.utils.JsonUtil;
import com.example.seckilldemo.vo.GoodsVo;
import com.example.seckilldemo.vo.RespBean;
import com.example.seckilldemo.vo.RespBeanEnum;
import com.example.seckilldemo.vo.SeckillMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
/**
* 消息消费者
*
* @author: LC
* @date 2022/3/7 7:44 下午
* @ClassName: MQReceiver
*/
@Service
@Slf4j
public class MQReceiver {
@Autowired
private ITGoodsService itGoodsServicel;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private ITOrderService itOrderService;
/**
* 下单操作
*
* @param
* @return void
* @author LiChao
* @operation add
* @date 6:48 下午 2022/3/8
**/
@RabbitListener(queues = "seckillQueue")
public void receive(String message) {
log.info("接收消息:" + message);
SeckillMessage seckillMessage = JsonUtil.jsonStr2Object(message, SeckillMessage.class);
Long goodsId = seckillMessage.getGoodsId();
TUser user = seckillMessage.getTUser();
GoodsVo goodsVo = itGoodsServicel.findGoodsVobyGoodsId(goodsId);
if (goodsVo.getStockCount() < 1) {
return;
}
//判断是否重复抢购
TSeckillOrder tSeckillOrder = (TSeckillOrder) redisTemplate.opsForValue().get("order:" + user.getId() + ":" + goodsId);
if (tSeckillOrder != null) {
return;
}
//下单操作
itOrderService.secKill(user, goodsVo);
}
// @RabbitListener(queues = "queue")
// public void receive(Object msg) {
// System.out.println("接收到的消息" + msg);
// }
//
//
// @RabbitListener(queues = "queue_fanout01")
// public void receive01(Object msg) {
// log.info("QUEUE01接收消息" + msg);
// }
//
// @RabbitListener(queues = "queue_fanout02")
// public void receive02(Object msg) {
// log.info("QUEUE02接收消息" + msg);
// }
//
// @RabbitListener(queues = "queue_direct01")
// public void receive03(Object msg) {
// log.info("QUEUE01接收消息" + msg);
// }
//
// @RabbitListener(queues = "queue_direct02")
// public void receive04(Object msg) {
// log.info("QUEUE02接收消息" + msg);
// }
//
// @RabbitListener(queues = "queue_topic01")
// public void receive05(Object msg) {
// log.info("QUEUE01接收消息" + msg);
// }
//
// @RabbitListener(queues = "queue_topic02")
// public void receive06(Object msg) {
// log.info("QUEUE02接收消息" + msg);
// }
//
// @RabbitListener(queues = "queue_header01")
// public void receive07(Message message) {
// log.info("QUEUE01接收消息 message对象" + message);
// log.info("QUEUE01接收消息" + new String(message.getBody()));
// }
//
// @RabbitListener(queues = "queue_header02")
// public void receive08(Message message) {
// log.info("QUEUE02接收消息 message对象" + message);
// log.info("QUEUE02接收消息" + new String(message.getBody()));
// }
}
package com.example.seckilldemo.controller;
import com.example.seckilldemo.entity.TUser;
import com.example.seckilldemo.rabbitmq.MQSender;
import com.example.seckilldemo.service.ITUserService;
import com.example.seckilldemo.utils.MD5Util;
import com.example.seckilldemo.vo.RespBean;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* 用户表 前端控制器
* </p>
*
* @author LiChao
* @since 2022-03-02
*/
@RestController
@RequestMapping("/user")
@Api(value = "用户表", tags = "用户表")
public class TUserController {
@Autowired
private ITUserService tUserService;
@Autowired
private MQSender mqSender;
@RequestMapping(value = "/info", method = RequestMethod.GET)
@ResponseBody
@ApiOperation("返回用户信息")
public RespBean info(TUser user) {
return RespBean.success(user);
}
//测试发送RabbitMQ消息
@RequestMapping(value = "/mq", method = RequestMethod.GET)
@ResponseBody
public void mq() {
mqSender.send("Hello");
}
//
// @RequestMapping(value = "/mq/fanout", method = RequestMethod.GET)
// @ResponseBody
// public void mqFanout() {
// mqSender.send("Hello");
// }
//
// @RequestMapping(value = "/mq/direct01", method = RequestMethod.GET)
// @ResponseBody
// public void mqDirect01() {
// mqSender.send01("Hello Red");
// }
//
// @RequestMapping(value = "/mq/direct02", method = RequestMethod.GET)
// @ResponseBody
// public void mqDirect02() {
// mqSender.send02("Hello Green");
// }
//
// @RequestMapping(value = "/mq/topic01", method = RequestMethod.GET)
// @ResponseBody
// public void mqtopic01() {
// mqSender.send03("Hello Red");
// }
//
// @RequestMapping(value = "/mq/topic02", method = RequestMethod.GET)
// @ResponseBody
// public void mqtopic02() {
// mqSender.send04("Hello Green");
// }
//
// @RequestMapping(value = "/mq/header01", method = RequestMethod.GET)
// @ResponseBody
// public void header01() {
// mqSender.send05("Hello 01");
// }
//
// @RequestMapping(value = "/mq/header02", method = RequestMethod.GET)
// @ResponseBody
// public void header02() {
// mqSender.send06("Hello 02");
// }
@GetMapping("/createuser")
@ApiOperation("压测创建配置文件")
public void CreateUser() throws IOException {
List<TUser> list = new ArrayList<>();
//生成用户
// for (int i = 0; i < 100; i++) {
// TUser tUser = new TUser();
// tUser.setId(1233L + i);
// tUser.setNickname("user" + i);
// tUser.setSalt("1a2b3c");
// tUser.setPassword("05314c6fbe1d0cdb5eab4e80f1bda30a");
// list.add(tUser);
// }
// tUserService.saveBatch(list);
// System.out.println("create user");
//读取用户
list = tUserService.list();
//登录,生成UserTicket
String urlString = "http://localhost:8080/login/doLogin";
File file = new File("/Users/lichao/Downloads/config.txt");
if (file.exists()) {
file.delete();
}
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
randomAccessFile.seek(0);
for (int i = 0; i < list.size(); i++) {
TUser tUser = list.get(i);
URL url = new URL(urlString);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
OutputStream outputStream = httpURLConnection.getOutputStream();
String params = "mobile=" + tUser.getId() + "&password=c38dc3dcb8f0b43ac8ea6a70b5ec7648";
outputStream.write(params.getBytes());
outputStream.flush();
InputStream inputStream = httpURLConnection.getInputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len = 0;
while ((len = inputStream.read(buff)) >= 0) {
byteArrayOutputStream.write(buff, 0, len);
}
inputStream.close();
byteArrayOutputStream.close();
String respone = new String(byteArrayOutputStream.toByteArray());
ObjectMapper mapper = new ObjectMapper();
RespBean respBean = mapper.readValue(respone, RespBean.class);
String userTicket = (String) respBean.getObject();
System.out.println("create userTicket:" + tUser.getId());
String row = tUser.getId() + "," + userTicket;
randomAccessFile.seek(randomAccessFile.length());
randomAccessFile.write(row.getBytes());
randomAccessFile.write("\r\n".getBytes());
System.out.println("write to file :" + tUser.getId());
}
randomAccessFile.close();
System.out.println();
}
}