导入依赖
<!--rabbitmq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置文件(记得开启手动确认,不然会默认自动确认,导致确认两次报错)
spring.rabbitmq.host=
spring.rabbitmq.port=5672
spring.rabbitmq.username=
spring.rabbitmq.password=
#手动确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#开启交换机确认消息
spring.rabbitmq.publisher-confirm-type=correlated
配置rabbitmq包括交换机,队列;routingKey,以及绑定备份交换机备用。
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMqConfig {
//站内信队列名
public static final String QUEUE_SYSTEM = "queue_system";
//交换机名称
public static final String EXCHANGE_TOPIC = "exchange_topic";
//备份交换机
public static final String BACKUP_EXCHANGE_NAME = "backup_exchange";
//备份队列
public static final String BACKUP_QUEUE_NAME = "backup_queue";
@Bean
public FanoutExchange backupExchange() {
return new FanoutExchange(BACKUP_EXCHANGE_NAME);
}
@Bean
public Queue backupQueue() {
return new Queue(BACKUP_QUEUE_NAME);
}
@Bean("topicExchange")
public TopicExchange topicExchange(){
return ExchangeBuilder.topicExchange(EXCHANGE_TOPIC).withArgument("alternate-exchange",BACKUP_EXCHANGE_NAME).durable(true).build();
}
@Bean("queueSystem")
public Queue queueSystem(){
return new Queue(QUEUE_SYSTEM,true,false,false);
}
@Bean
public Binding queueSystemBindingTopicExchange(@Qualifier("topicExchange") TopicExchange topicExchange,
@Qualifier("queueSystem") Queue queueSystem){
return BindingBuilder.bind(queueSystem).to(topicExchange).with("msgSystem");
}
@Bean
public Binding backupQueueBindingBackupExchange(@Qualifier("backupExchange") FanoutExchange backupExchange,
@Qualifier("backupQueue") Queue backupQueue) {
return BindingBuilder.bind(backupQueue).to(backupExchange);
}
}
配置交换机,队列异步确认
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration
@Slf4j
public class ConfirmCallBack implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostConstruct
public void init() {
//注入这个实现后的这个方法类
rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setReturnsCallback(this);
}
@Override
//异步监听交换机
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack) {
log.info("交换机已经收到id为" + correlationData.getId() + "的消息");
} else {
log.info("交换机未收到id为" + correlationData.getId() + "的消息,原因是:" + cause);
}
}
@Override//异步监听队列,路由失败,不可达目的地则回退
public void returnedMessage(ReturnedMessage returned) {
log.error("消息{},被交换机{}因退回,退回原因:{},路由key:{}",
new String(returned.getMessage().getBody()),
returned.getExchange(),
returned.getReplyText(),//cause
returned.getRoutingKey());
}
}
消息发送service层(发布,回显,写入)
public interface MsgSystemService {
void sendMessage(String msg);
PaginationDTO list(Integer page, Integer size);
void createMessage(Message message);
}
实现类
import life.majiang.community.config.ConfirmCallBack;
import life.majiang.community.config.RabbitMqConfig;
import life.majiang.community.dto.PaginationDTO;
import life.majiang.community.mapper.MessageMapper;
import life.majiang.community.model.Message;
import life.majiang.community.model.MessageExample;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.RowBounds;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
@Service
@Slf4j
public class MsgSystemServiceImp implements MsgSystemService{
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private MessageMapper messageMapper;
@Autowired
private ConfirmCallBack confirmCallBack;
@Override
public void sendMessage(String msg) {
CorrelationData correlationData=new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_TOPIC,"msgSystem", msg,correlationData);
log.info("发送成功,消息内容:{}",msg);
}
@Override
public PaginationDTO list(Integer page, Integer size) {
//泛型
PaginationDTO<Message> paginationDTO = new PaginationDTO<>();
Integer totalPage;
//通知数量
Integer totalCount = (int) messageMapper.countByExample(null);
if (totalCount % size == 0) {
totalPage = totalCount / size;
} else {
totalPage = totalCount / size + 1;
}
if (page < 1) {
page = 1;
}
if (page > totalPage) {
page = totalPage;
}
paginationDTO.setPagination(totalPage, page);
//加分页
Integer offset = size * (page - 1);
MessageExample example = new MessageExample();
//时间倒序输出
example.setOrderByClause("gmt_create desc");
List<Message> messages = messageMapper.selectByExampleWithBLOBsWithRowbounds(example, new RowBounds(offset, size));
//内容做个判断
if (messages.size() == 0) {
return paginationDTO;
}
paginationDTO.setData(messages);
return paginationDTO;
}
@Override
public void createMessage(Message message) {
Message msg = new Message();
msg.setGmtCreate(System.currentTimeMillis());
msg.setMsg(message.getMsg());
messageMapper.insert(msg);
}
}
controller发送
@Controller
@Slf4j
public class MsgSystemController {
@Autowired
private MsgSystemService msgSystemService;
@GetMapping("/sendMessage")
public String SendMessage() {
return "sendMessage";
}
@PostMapping("/sendMessage")
public String doSendMessage(String message,
HttpServletRequest request,
Model model) {
//向所有用户发送消息
User user = (User) request.getSession().getAttribute("user");
if (user.getId() == 1) {
if (message == null || message == "") {
model.addAttribute("error", "信息不能为空");
return "sendMessage";
}
model.addAttribute("message", message);
msgSystemService.sendMessage(message);
}
//发完返回首页
return "redirect:/";
}
}
用户接收(消费并写入数据库)
@Component
@Slf4j
public class MsgSystemConsumer {
@Autowired
private MsgSystemService msgSystemService;
@RabbitListener(queues = RabbitMqConfig.QUEUE_SYSTEM)
public void listenerPMsg(Message message, Channel channel) throws IOException {
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
String msg = new String(message.getBody());
log.info("用户收到站内通知:{}", msg);
channel.basicAck(deliveryTag,false);
//写入数据库
life.majiang.community.model.Message message1 = new life.majiang.community.model.Message();
message1.setMsg(msg);
msgSystemService.createMessage(message1);
}catch (Exception e){
channel.basicReject(deliveryTag,false);
e.printStackTrace();
}
}
}