提交 264c18a3 作者: 方治民

feat: 调整 RabbitMQ 消息订阅及推送实现、数据表集成 BasicEntity 等

上级 cb49a3ae
......@@ -9,8 +9,13 @@ dependencies {
// 本地依赖
implementation fileTree(dir: project.rootDir.getPath() + '\\libs', includes: ['*jar'])
// 文档及参数校验
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation "io.swagger:swagger-annotations:${swaggerAnnotationsVersion}"
// hutool-core
implementation "cn.hutool:hutool-core:${hutoolVersion}"
implementation "cn.hutool:hutool-http:${hutoolVersion}"
// fastjson
implementation "com.alibaba:fastjson:${fastJsonVersion}"
......@@ -19,4 +24,15 @@ dependencies {
// hibernate-types-55
implementation "com.vladmihalcea:hibernate-types-55:${hibernateTypesVersion}"
// ======================= 推送相关 =======================
// 个推 SDK(App 推送)
// https://mvnrepository.com/artifact/com.getui.push/restful-sdk
implementation 'com.getui.push:restful-sdk:1.0.0.6'
// 阿里云短信 SDK(SMS 推送)
// https://mvnrepository.com/artifact/com.aliyun/dysmsapi20170525
implementation 'com.aliyun:dysmsapi20170525:2.0.9'
// 邮件 SDK(EMAIL 推送)
implementation 'org.springframework.boot:spring-boot-starter-mail'
// ======================================================
}
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.push.domain;
import com.alibaba.fastjson.JSON;
import com.vladmihalcea.hibernate.type.json.JsonType;
import com.alibaba.fastjson.JSONObject;
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import com.yiring.common.domain.BasicEntity;
import java.io.Serial;
import java.io.Serializable;
......@@ -34,7 +34,7 @@ import org.hibernate.annotations.TypeDef;
@FieldNameConstants
@FieldDefaults(level = AccessLevel.PRIVATE)
@Entity
@TypeDef(name = "json", typeClass = JsonType.class)
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
@Table(
name = "SYS_PUSH_MESSAGE",
indexes = {
......@@ -73,18 +73,18 @@ public class PushMessage extends BasicEntity implements Serializable {
String content;
@Comment("扩展数据")
@org.hibernate.annotations.Type(type = "json")
@Column(columnDefinition = "json")
JSON extra;
@org.hibernate.annotations.Type(type = "jsonb")
@Column(columnDefinition = "jsonb")
JSONObject extra;
@Comment("消息状态")
@Enumerated(EnumType.STRING)
Status status;
@Comment("推送反馈结果")
@org.hibernate.annotations.Type(type = "json")
@Column(columnDefinition = "json")
JSON result;
@org.hibernate.annotations.Type(type = "jsonb")
@Column(columnDefinition = "jsonb")
JSONObject result;
@Comment("重试次数")
Integer retryCount;
......@@ -94,7 +94,7 @@ public class PushMessage extends BasicEntity implements Serializable {
@SuppressWarnings({ "unused" })
public enum Type {
WS("STOMP WebSocket 消息"),
WEBHOOK("webhook"),
APP("APP 消息"),
SMS("短信消息"),
EMAIL("邮件消息"),
......@@ -113,7 +113,7 @@ public class PushMessage extends BasicEntity implements Serializable {
}
public String queue() {
return String.format("push.%s.queue", this.name());
return String.format("push.%s.queue", this.name().toLowerCase());
}
}
......
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.push.param;
import io.swagger.annotations.ApiModel;
import lombok.*;
import lombok.experimental.FieldDefaults;
/**
* App 推送参数
*
* @author Jim
* @version 0.1
* 2022/4/21 10:27
*/
@ApiModel("A")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class PushAppParam {
String webhook;
}
......@@ -20,14 +20,37 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class PushRabbitConfig {
/**
* 消息交换机
*/
public static final String PUSH_TOPIC_EXCHANGE = "push.topic.exchange";
/**
* WebHook 推送队列
*/
public static final String PUSH_WEBHOOK_QUEUE = "push.webhook.queue";
/**
* App 消息推送队列
*/
public static final String PUSH_APP_QUEUE = "push.app.queue";
public static final String PUSH_WS_QUEUE = "push.ws.queue";
/**
* 短信推送队列
*/
public static final String PUSH_SMS_QUEUE = "push.sms.queue";
public static final String PUSH_EMAIL_QUEUE = "push.email.queue";
/**
* 邮箱推送队列
*/
public static final String PUSH_MAIL_QUEUE = "push.mail.queue";
/**
* TTS 语音电话队列
*/
public static final String PUSH_CALL_TTS_QUEUE = "push.call.tts.queue";
/**
* 语音电话推送队列
*/
public static final String PUSH_CALL_AUDIO_QUEUE = "push.call.audio.queue";
/**
* 设备广播推送队列
*/
public static final String PUSH_DEVICE_TONE_QUEUE = "push.device.tone.queue";
/**
......@@ -52,16 +75,16 @@ public class PushRabbitConfig {
return BindingBuilder.bind(queue).to(exchange).with(PUSH_APP_QUEUE);
}
@Bean(PUSH_WS_QUEUE)
public Queue pushWebSocketQueue() {
@Bean(PUSH_WEBHOOK_QUEUE)
public Queue pushWebHookQueue() {
Map<String, Object> args = new HashMap<>(1);
args.put("x-message-ttl", 30 * 1000);
return new Queue(PUSH_WS_QUEUE, true, false, false, args);
return new Queue(PUSH_WEBHOOK_QUEUE, true, false, false, args);
}
@Bean
Binding bindingExchangeWs(@Qualifier(PUSH_WS_QUEUE) Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(PUSH_WS_QUEUE);
Binding bindingExchangeWebHook(@Qualifier(PUSH_WEBHOOK_QUEUE) Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(PUSH_WEBHOOK_QUEUE);
}
@Bean(PUSH_SMS_QUEUE)
......@@ -76,16 +99,16 @@ public class PushRabbitConfig {
return BindingBuilder.bind(queue).to(exchange).with(PUSH_SMS_QUEUE);
}
@Bean(PUSH_EMAIL_QUEUE)
public Queue pushEmailQueue() {
@Bean(PUSH_MAIL_QUEUE)
public Queue pushMailQueue() {
Map<String, Object> args = new HashMap<>(1);
args.put("x-message-ttl", 60 * 1000);
return new Queue(PUSH_EMAIL_QUEUE, true, false, false, args);
return new Queue(PUSH_MAIL_QUEUE, true, false, false, args);
}
@Bean
Binding bindingExchangeEmail(@Qualifier(PUSH_EMAIL_QUEUE) Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(PUSH_EMAIL_QUEUE);
Binding bindingExchangeMail(@Qualifier(PUSH_MAIL_QUEUE) Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(PUSH_MAIL_QUEUE);
}
@Bean(PUSH_CALL_TTS_QUEUE)
......
......@@ -26,10 +26,61 @@ public class PushRabbitReceiver {
PushMessageRepository repository;
@RabbitHandler
@RabbitListener(queues = PushRabbitConfig.PUSH_WS_QUEUE)
public void receiverWebSocketMessage(Long id) {
log.info("接收到消息: " + id);
@RabbitListener(queues = PushRabbitConfig.PUSH_WEBHOOK_QUEUE)
public void receiverWebHookMessage(Long id) {
log.info("[WebHook] Message: " + id);
repository.findById(id).ifPresent(message -> log.info("{}", message));
// TODO
// 实现调用 WebHook,基于 WebHook API 发起 HTTPs 请求
}
@RabbitHandler
@RabbitListener(queues = PushRabbitConfig.PUSH_APP_QUEUE)
public void receiverAppMessage(Long id) {
log.info("[App] Message: " + id);
// TODO
// 实现推送消息到 App,基于个推 API
// https://github.com/GetuiLaboratory/getui-pushapi-java-client-v2
}
@RabbitHandler
@RabbitListener(queues = PushRabbitConfig.PUSH_SMS_QUEUE)
public void receiverSmsMessage(Long id) {
log.info("[SMS] Message: " + id);
// TODO
// 实现发送短信,基于阿里云短信平台 API
}
@RabbitHandler
@RabbitListener(queues = PushRabbitConfig.PUSH_MAIL_QUEUE)
public void receiverMailMessage(Long id) {
log.info("[Mail] Message: " + id);
// TODO
// 实现发送邮件,基于邮件配置
}
@RabbitHandler
@RabbitListener(queues = PushRabbitConfig.PUSH_CALL_TTS_QUEUE)
public void receiverTtsMessage(Long id) {
log.info("[Phone TTS] Message: " + id);
// TODO
// 实现拨打电话播放 TTS 转语音,基于壹润外呼系统 API
}
@RabbitHandler
@RabbitListener(queues = PushRabbitConfig.PUSH_CALL_AUDIO_QUEUE)
public void receiverAudioMessage(Long id) {
log.info("[Phone Audio] Message: " + id);
// TODO
// 实现拨打电话播放音频文件,基于壹润外呼系统 API
}
@RabbitHandler
@RabbitListener(queues = PushRabbitConfig.PUSH_DEVICE_TONE_QUEUE)
public void receiverToneMessage(Long id) {
log.info("[Device Tone] Message: " + id);
// TODO
// 实现播放设备铃声,基于音柱广播设备 API
// SDK 暂未拿到,设备未采购,未进行联调
}
}
......@@ -3,6 +3,7 @@ package com.yiring.app.push.service;
import com.alibaba.fastjson.JSONObject;
import com.yiring.app.push.domain.PushMessage;
import com.yiring.app.push.param.PushAppParam;
/**
* 推送服务
......@@ -13,4 +14,10 @@ import com.yiring.app.push.domain.PushMessage;
*/
public interface PushService {
void push(PushMessage.Type type, JSONObject raw);
/**
* 推送到 App
* @param param 参数
*/
void app(PushAppParam param);
}
......@@ -4,12 +4,13 @@ package com.yiring.app.push.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.yiring.app.push.domain.PushMessage;
import com.yiring.app.push.domain.PushMessageRepository;
import com.yiring.app.push.param.PushAppParam;
import com.yiring.app.push.rabbitmq.PushRabbitConfig;
import com.yiring.app.push.service.PushService;
import javax.annotation.Resource;
import javax.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
/**
......@@ -29,7 +30,7 @@ public class PushServiceImpl implements PushService {
PushMessageRepository repository;
@Resource
AmqpTemplate amqpTemplate;
RabbitTemplate rabbitTemplate;
@Override
public void push(PushMessage.Type type, JSONObject raw) {
......@@ -37,6 +38,10 @@ public class PushServiceImpl implements PushService {
message.setType(type);
message.setExtra(raw);
repository.saveAndFlush(message);
amqpTemplate.convertAndSend(PushRabbitConfig.PUSH_TOPIC_EXCHANGE, type.queue(), message.getId());
rabbitTemplate.convertAndSend(PushRabbitConfig.PUSH_TOPIC_EXCHANGE, type.queue(), message.getId());
}
@Override
public void app(PushAppParam param) {}
}
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.domain.location;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.vladmihalcea.hibernate.type.json.JsonType;
import com.yiring.auth.domain.user.User;
import java.io.Serial;
......@@ -116,7 +116,7 @@ public class LocationLog implements Serializable {
@Comment("原始数据")
@org.hibernate.annotations.Type(type = "json")
@Column(columnDefinition = "json")
JSON raw;
JSONObject raw;
@Comment("创建时间")
LocalDateTime createTime;
......
......@@ -3,6 +3,7 @@ package com.yiring.app.domain.location;
import com.yiring.auth.domain.user.User;
import com.yiring.common.annotation.FieldMapping;
import com.yiring.common.domain.BasicEntity;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
......@@ -11,10 +12,9 @@ import javax.persistence.*;
import lombok.*;
import lombok.experimental.FieldDefaults;
import lombok.experimental.FieldNameConstants;
import lombok.experimental.SuperBuilder;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.snowflake.SnowflakeId;
/**
* 定位标签
......@@ -30,7 +30,7 @@ import org.hibernate.snowflake.SnowflakeId;
@Getter
@Setter
@ToString
@Builder
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
......@@ -47,17 +47,11 @@ import org.hibernate.snowflake.SnowflakeId;
}
)
@Comment("定位标签")
public class LocationTag implements Serializable {
public class LocationTag extends BasicEntity implements Serializable {
@Serial
private static final long serialVersionUID = 5419734189897829250L;
@Comment("主键")
@Id
@GeneratedValue(generator = SnowflakeId.GENERATOR)
@GenericGenerator(name = SnowflakeId.GENERATOR, strategy = SnowflakeId.Strategy.LONG)
Long id;
/**
* 数据来源于【真源人员定位系统 - 定位标签】
* 作用: 用于双向联动进行数据同步
......@@ -134,7 +128,7 @@ public class LocationTag implements Serializable {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
LocationTag that = (LocationTag) o;
return id != null && Objects.equals(id, that.id);
return getId() != null && Objects.equals(getId(), that.getId());
}
@Override
......
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.rabbit.config;
import javax.annotation.Resource;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
* rabbitmq配置
*
* @author ifzm
* 2019/8/21 15:44
*/
@Configuration
public class RabbitConfig {
@Resource
RabbitProperties rabbitProperties;
private static final String CONNECTION_FACTORY_NAME = "rabbitConnectionFactory";
@Bean(CONNECTION_FACTORY_NAME)
@Primary
public ConnectionFactory connectionFactory() {
return RabbitConfig.connectionFactory(
rabbitProperties.getHost(),
rabbitProperties.getPort(),
rabbitProperties.getUsername(),
rabbitProperties.getPassword(),
rabbitProperties.getVirtualHost()
);
}
@Bean
@Primary
public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(
@Qualifier(CONNECTION_FACTORY_NAME) ConnectionFactory connectionFactory
) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
return factory;
}
@Bean
@Primary
public RabbitTemplate rabbitTemplate(@Qualifier(CONNECTION_FACTORY_NAME) ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
/**
* 创建连接工厂
*
* @param host 主机
* @param port 端口
* @param username 用户名
* @param password 密码
* @param virtualHost 虚拟主机
* @return 连接工厂
*/
public static CachingConnectionFactory connectionFactory(
String host,
int port,
String username,
String password,
String virtualHost
) {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setHost(host);
connectionFactory.setPort(port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualHost);
return connectionFactory;
}
}
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.config.zy;
package com.yiring.app.rabbit.config;
import javax.annotation.Resource;
import lombok.AccessLevel;
......
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.config.zy;
package com.yiring.app.rabbit.config;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
......@@ -43,8 +44,8 @@ public class ZyRabbitConfig {
public static final String MESSAGE_QUEUES_NAME = "tenant_msg_12A14FDC_sc21080400";
@Bean(CONNECTION_FACTORY_NAME)
public CachingConnectionFactory zyConnectionFactory() {
return connectionFactory(
public ConnectionFactory zyConnectionFactory() {
return RabbitConfig.connectionFactory(
rabbitmq.getHost(),
rabbitmq.getPort(),
rabbitmq.getUsername(),
......@@ -54,9 +55,9 @@ public class ZyRabbitConfig {
}
@Bean(LISTENER_FACTORY_NAME)
public SimpleRabbitListenerContainerFactory secondFactory(
public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(
SimpleRabbitListenerContainerFactoryConfigurer configurer,
@Qualifier(CONNECTION_FACTORY_NAME) CachingConnectionFactory connectionFactory
@Qualifier(CONNECTION_FACTORY_NAME) ConnectionFactory connectionFactory
) {
// 检查队列名称是否与配置文件一致,避免监听错误
if (!MESSAGE_QUEUES_NAME.equals(rabbitmq.getQueueName())) {
......@@ -66,31 +67,9 @@ public class ZyRabbitConfig {
}
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
// 最小消费者数量
factory.setConcurrentConsumers(1);
// 最大消费者数量
factory.setMaxConcurrentConsumers(1);
// 预读取一条消息
factory.setPrefetchCount(1);
// 手动确认消息模式
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
configurer.configure(factory, connectionFactory);
return factory;
}
public CachingConnectionFactory connectionFactory(
String host,
int port,
String username,
String password,
String virtualHost
) {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setHost(host);
connectionFactory.setPort(port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualHost);
return connectionFactory;
}
}
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.rabbitmq;
package com.yiring.app.rabbit.receiver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
......
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.rabbitmq.zy;
package com.yiring.app.rabbit.receiver;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import com.yiring.app.config.zy.ZyRabbitConfig;
import com.yiring.app.push.domain.PushMessage;
import com.yiring.app.push.service.PushService;
import com.yiring.app.rabbit.config.ZyRabbitConfig;
import java.io.IOException;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
......@@ -15,6 +14,7 @@ import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
......@@ -30,7 +30,7 @@ import org.springframework.transaction.annotation.Transactional;
@Component
@Configuration
@ConditionalOnProperty(prefix = "zy-config.rabbitmq", value = "enabled", havingValue = "true")
public class ZyRabbitmqReceiver {
public class ZyRabbitReceiver {
// TODO
// 1. 新增消息订阅定时任务,检查是否正常订阅了真源定位系统的消息
......@@ -40,6 +40,9 @@ public class ZyRabbitmqReceiver {
@Resource
PushService pushService;
@Resource
SimpMessagingTemplate simpMessagingTemplate;
/**
* 订阅真源定位系统 RabbitMQ 推送过来的消息(主动订阅的一些消息类别)
* 参见: 定位平台接口规范V3.0.1 - 通用版.pdf #6
......@@ -74,6 +77,8 @@ public class ZyRabbitmqReceiver {
case "deviceStatus" -> processDeviceStatusMessage(data);
// 按键报警
case "keyWarning" -> processKeyWarningMessage(data);
// 围栏报警
case "enclosure" -> log.warn("Ignore Message Type [enclosure]: {}", info);
default -> log.warn("Unknown Message Type: {}", info);
}
} catch (Exception e) {
......@@ -95,9 +100,10 @@ public class ZyRabbitmqReceiver {
// 1. 解析消息内容,进行围栏、出入标识判断等处理,将定位记录录入数据库
// 2. 创建一条需要进行消息推送的记录
// 3. 将记录推送的消息推送模块
// 4. 坚持是否触发围栏告警,记录告警数据,并推送消息
// WebSocket 消息推送
pushService.push(PushMessage.Type.WS, data);
simpMessagingTemplate.convertAndSend("/topic/position", data);
}
/**
......
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.rabbitmq;
import org.springframework.context.annotation.Configuration;
/**
* rabbitmq配置
*
* @author ifzm
* 2019/8/21 15:44
*/
@Configuration
public class RabbitConfig {}
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.stomp;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* RabbitmqProperties
*
* @author ifzm
* @version 0.1
* 2019/9/25 21:31
*/
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Component
@ConfigurationProperties(prefix = "spring.rabbitmq")
public class RabbitmqProperties {
int port;
String host;
String username;
String password;
}
......@@ -5,6 +5,7 @@ import com.yiring.app.constant.RedisKey;
import com.yiring.common.core.Redis;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
......@@ -32,7 +33,7 @@ public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
Redis redis;
@Resource
RabbitmqProperties rabbitmqProperties;
RabbitProperties rabbitProperties;
@Resource
ClientInboundChannelInterceptor clientInboundChannelInterceptor;
......@@ -61,11 +62,11 @@ public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
registry.setApplicationDestinationPrefixes("/app");
registry
.enableStompBrokerRelay("/topic", "/queue")
.setRelayHost(rabbitmqProperties.getHost())
.setClientLogin(rabbitmqProperties.getUsername())
.setClientPasscode(rabbitmqProperties.getPassword())
.setSystemLogin(rabbitmqProperties.getUsername())
.setSystemPasscode(rabbitmqProperties.getPassword());
.setRelayHost(rabbitProperties.getHost())
.setClientLogin(rabbitProperties.getUsername())
.setClientPasscode(rabbitProperties.getPassword())
.setSystemLogin(rabbitProperties.getUsername())
.setSystemPasscode(rabbitProperties.getPassword());
log.info("Init RabbitMQ STOMP MessageBroker Success.");
}
......
/* (C) 2021 YiRing, Inc. */
package com.yiring.app.web;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.yiring.app.constant.Code;
import com.yiring.app.domain.location.LocationTag;
import com.yiring.app.exception.CodeException;
import com.yiring.app.push.domain.PushMessage;
import com.yiring.app.push.service.PushService;
import com.yiring.app.util.GeoUtils;
import com.yiring.auth.domain.user.User;
import com.yiring.common.core.Result;
import com.yiring.common.domain.BasicEntity;
import com.yiring.common.param.PageParam;
import com.yiring.common.vo.PageVo;
import io.swagger.annotations.Api;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.criteria.*;
import javax.validation.Valid;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Point;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -53,11 +61,55 @@ public class HelloController {
return Result.ok(vo);
}
@Resource
SimpMessagingTemplate simpMessagingTemplate;
@GetMapping("test")
public Result<Point> test() {
PushService service = SpringUtil.getBean(PushService.class);
service.push(PushMessage.Type.WS, new JSONObject().fluentPut("msg", "hello"));
Point point = GeoUtils.createPoint(112.1, 23.56);
simpMessagingTemplate.convertAndSend("/topic/position", point);
return Result.ok(point);
}
@Resource
EntityManager em;
@Data
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public static class UserVo {
Long id;
String avatar;
String code;
}
@GetMapping("test2")
public Result<ArrayList<UserVo>> query() {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<UserVo> cq = cb.createQuery(UserVo.class);
Root<User> root = cq.from(User.class);
Expression<Long> id = root.get(BasicEntity.Fields.id);
Expression<String> avatar = root.get(User.Fields.avatar);
// 子查询
Subquery<String> query = cq.subquery(String.class);
Root<LocationTag> tagRoot = query.from(LocationTag.class);
query.select(tagRoot.get(LocationTag.Fields.code));
query.where(cb.equal(tagRoot.get(LocationTag.Fields.user), root));
// 构建查询字段
cq.multiselect(id, avatar, query);
// 查询条件
List<Predicate> predicates = new ArrayList<>();
// 可根据入参判断是否需要查询指定字段
predicates.add(cb.isNotNull(root.get(User.Fields.avatar)));
predicates.add(cb.equal(query, "BTT22222222"));
cq.where(predicates.toArray(new Predicate[0]));
List<UserVo> users = em.createQuery(cq).getResultList();
return Result.ok(new ArrayList<>(users));
}
}
......@@ -26,6 +26,17 @@ spring:
username: admin
password: 123456
virtual-host: /
# 开启发送端确认
publisher-confirm-type: correlated
# 开启接收端确认
publisher-returns: true
template:
# 消息抵达队列,异步回调 confirm
mandatory: true
listener:
simple:
# 手动确认消息
acknowledge-mode: manual
# knife4j
knife4j:
......@@ -56,7 +67,7 @@ zy-config:
host: project.yz-online.com
# RabbitMQ 订阅配置
rabbitmq:
enabled: false
enabled: true
host: ${zy-config.host}
port: 672
username: admin
......
......@@ -27,5 +27,4 @@ dependencies {
// myexcel
implementation "com.github.liaochong:myexcel:${myexcelVersion}"
}
......@@ -16,6 +16,7 @@ import javax.persistence.*;
import lombok.*;
import lombok.experimental.FieldDefaults;
import lombok.experimental.FieldNameConstants;
import lombok.experimental.SuperBuilder;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Comment;
......@@ -29,7 +30,7 @@ import org.hibernate.annotations.Comment;
@Getter
@Setter
@ToString
@Builder
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论