提交 7db8856e 作者: 方治民

fix: 修复时序表时区 DDL 问题、移除移除 mappedBy 配置、删除重复的 MQ 配置项

上级 7ef29629
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.config.zy;
import javax.annotation.Resource;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 真源配置想
*
* @author ifzm
* @version 0.1
* 2019/9/25 21:31
*/
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Component
@ConfigurationProperties(prefix = "zy-config")
public class ZyConfigProperties {
String host;
@Resource
ZyConfigRabbitmq rabbitmq;
@Resource
ZyConfigOpen open;
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Component
@ConfigurationProperties(prefix = "zy-config.rabbitmq")
public static class ZyConfigRabbitmq {
boolean enabled;
String host;
int port;
String username;
String password;
String virtualHost;
String queueName;
}
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Component
@ConfigurationProperties(prefix = "zy-config.open")
public static class ZyConfigOpen {
String api;
String clientId;
String grantType;
String clientSecret;
String tenant;
}
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Component
@ConfigurationProperties(prefix = "zy-config.proxy")
public static class ZyConfigProxy {
String api;
String tenant;
@Resource
ZyConfigProxyClient client;
@Resource
ZyConfigProxyManage manage;
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Component
@ConfigurationProperties(prefix = "zy-config.proxy.client")
public static class ZyConfigProxyClient {
String username;
String password;
}
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Component
@ConfigurationProperties(prefix = "zy-config.proxy.manage")
public static class ZyConfigProxyManage {
String username;
String password;
}
}
}
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.config.zy;
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.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 真源 RabbitMQ 订阅配置
*
* @author Jim
* @version 0.1
* 2022/4/13 17:05
*/
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "zy-config.rabbitmq", value = "enabled", havingValue = "true")
public class ZyRabbitConfig {
@Resource
ZyConfigProperties.ZyConfigRabbitmq rabbitmq;
@Resource
ConfigurableApplicationContext context;
public static final String CONNECTION_FACTORY_NAME = "zyRabbitConnectionFactory";
public static final String LISTENER_FACTORY_NAME = "zyRabbitListenerFactory";
/**
* 消息队列名称(必须要与配置文件中的 queue-name 完全一致)
* 规则: tenant_msg_${open.client-secret}_${open.client-id}
* 参见文档: 定位平台接口规范V3.0.1 - 通用版.pdf #6
*/
public static final String MESSAGE_QUEUES_NAME = "tenant_msg_12A14FDC_sc21080400";
@Bean(CONNECTION_FACTORY_NAME)
public CachingConnectionFactory zyConnectionFactory() {
return connectionFactory(
rabbitmq.getHost(),
rabbitmq.getPort(),
rabbitmq.getUsername(),
rabbitmq.getPassword(),
rabbitmq.getVirtualHost()
);
}
@Bean(LISTENER_FACTORY_NAME)
public SimpleRabbitListenerContainerFactory secondFactory(
SimpleRabbitListenerContainerFactoryConfigurer configurer,
@Qualifier(CONNECTION_FACTORY_NAME) CachingConnectionFactory connectionFactory
) {
// 检查队列名称是否与配置文件一致,避免监听错误
if (!MESSAGE_QUEUES_NAME.equals(rabbitmq.getQueueName())) {
log.error("队列名称不一致,请检查配置文件");
context.close();
return null;
}
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;
}
}
......@@ -96,7 +96,7 @@ public class LocationBeacon extends BasicEntity implements Serializable {
@Comment("围栏集合")
@Builder.Default
@ManyToMany(mappedBy = "beacons")
@ManyToMany
@ToString.Exclude
Set<LocationFence> fences = new HashSet<>(0);
......
......@@ -34,7 +34,7 @@ import org.locationtech.jts.geom.Geometry;
@FieldNameConstants
@FieldDefaults(level = AccessLevel.PRIVATE)
@Entity
@Table(name = "BS_LOCATION_FENCE", indexes = { @Index(columnList = "linkId"), @Index(columnList = "mode") })
@Table(name = "BS_LOCATION_FENCE", indexes = { @Index(columnList = "mode") })
@Comment("围栏")
public class LocationFence extends BasicEntity implements Serializable {
......@@ -62,7 +62,7 @@ public class LocationFence extends BasicEntity implements Serializable {
@Comment("信标集合")
@Builder.Default
@ManyToMany(mappedBy = "fences")
@ManyToMany
@ToString.Exclude
Set<LocationBeacon> beacons = new HashSet<>(0);
......
......@@ -50,7 +50,7 @@ public class LocationLog implements Serializable {
@Id
@Comment("时间")
@Column(nullable = false)
@Column(nullable = false, columnDefinition = "timestamp without time zone")
@CreationTimestamp
LocalDateTime time;
......
......@@ -18,7 +18,7 @@ import org.hibernate.annotations.TypeDef;
* 真源定位系统实时数据日志
* TODO:
* 1. 实时数据日志的存储结构 TimeScale: 时间粒度,每小时一个分区
* eg: SELECT create_hypertable('zy_realtime_log', 'time', chunk_time_interval => INTERVAL '1 hour')
* eg: SELECT create_hypertable('ZY_REALTIME_LOG', 'time', chunk_time_interval => INTERVAL '1 hour')
* 2. 数据分区压缩
* 3. 定时删除过期分区数据
* 参考:<a href="https://blog.csdn.net/yang_z_1/article/details/111560747">文档</a>
......@@ -47,7 +47,7 @@ public class ZyRealtimeLog implements Serializable {
@Id
@Comment("时间")
@Column(nullable = false)
@Column(nullable = false, columnDefinition = "timestamp without time zone")
@CreationTimestamp
LocalDateTime time;
......
/* (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.rabbitmq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* rabbitmq配置
*
* @author ifzm
* 2019/8/21 16:07
*/
@SuppressWarnings({ "unused" })
@Slf4j
@Component
@Transactional(rollbackFor = Exception.class)
public class RabbitReceiver {}
/* (C) 2022 YiRing, Inc. */
package com.yiring.app.rabbitmq.zy;
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 java.io.IOException;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
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.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* 真源 RabbitMQ 消息监听(消息消费者)
*
* @author Jim
* @version 0.1
* 2022/4/13 17:13
*/
@Slf4j
@Component
@Configuration
@ConditionalOnProperty(prefix = "zy-config.rabbitmq", value = "enabled", havingValue = "true")
public class ZyRabbitmqReceiver {
// TODO
// 1. 新增消息订阅定时任务,检查是否正常订阅了真源定位系统的消息
// 2. 如果没有所需的订阅记录,则发起消息订阅(见接口文档: 6.2)
// 3. 订阅 position(定位数据)、lowPower(低电量报警)、deviceStatus(设备状态)、keyWarning(按键报警)
@Resource
PushService pushService;
/**
* 订阅真源定位系统 RabbitMQ 推送过来的消息(主动订阅的一些消息类别)
* 参见: 定位平台接口规范V3.0.1 - 通用版.pdf #6
* @param msg 消息内容
* @param channel 消息通道
* @param message 消息主体
* @throws IOException 消息确认异常
*/
@RabbitHandler
@RabbitListener(
queues = ZyRabbitConfig.MESSAGE_QUEUES_NAME,
containerFactory = ZyRabbitConfig.LISTENER_FACTORY_NAME
)
public void listen(String msg, Channel channel, Message message) throws IOException {
// 手动确认消息已收到
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
try {
// 将消息转换成 JSON 格式
JSONObject info = JSON.parseObject(msg);
log.info("Receiver Message: {}", info);
// 解构消息内容
JSONObject data = info.getJSONObject("params");
String method = info.getString("method");
switch (method) {
// 实时定位
case "position" -> processPositionMessage(data);
// 设备低电量
case "lowPower" -> processLowPowerMessage(data);
// 设备状态变更
case "deviceStatus" -> processDeviceStatusMessage(data);
// 按键报警
case "keyWarning" -> processKeyWarningMessage(data);
default -> log.warn("Unknown Message Type: {}", info);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
* 处理定位消息
* @param data 消息内容
*/
@Transactional(rollbackFor = Exception.class)
public void processPositionMessage(JSONObject data) {
// TODO
log.info("Position Message: {}", data);
// 包装消息
// TODO
// 1. 解析消息内容,进行围栏、出入标识判断等处理,将定位记录录入数据库
// 2. 创建一条需要进行消息推送的记录
// 3. 将记录推送的消息推送模块
// WebSocket 消息推送
pushService.push(PushMessage.Type.WS, data);
}
/**
* 处理低电量报警消息
* @param data 消息内容
*/
@Transactional(rollbackFor = Exception.class)
public void processLowPowerMessage(JSONObject data) {
// TODO
log.info("LowPower Message: {}", data);
}
/**
* 处理设备状态更新消息
* @param data 消息内容
*/
@Transactional(rollbackFor = Exception.class)
public void processDeviceStatusMessage(JSONObject data) {
// TODO
log.info("DeviceStatus Message: {}", data);
}
/**
* 处理按键报警消息
* @param data 消息内容
*/
@Transactional(rollbackFor = Exception.class)
public void processKeyWarningMessage(JSONObject data) {
// TODO
log.info("KeyWarning Message: {}", data);
}
}
/* (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.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.common.core.Result;
import com.yiring.common.param.PageParam;
import com.yiring.common.vo.PageVo;
......@@ -16,7 +11,6 @@ import java.util.Arrays;
import java.util.List;
import javax.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Point;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -52,12 +46,4 @@ public class HelloController {
PageVo<String> vo = PageVo.build(data, data.size());
return Result.ok(vo);
}
@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);
return Result.ok(point);
}
}
/* (C) 2022 YiRing, Inc. */
package com.yiring.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 跨域设置
* @author tzl
* 2022/4/18 10:29
*/
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
// corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论