From 0a229c0af3a72c5cf44f912931e2058c6755fbd6 Mon Sep 17 00:00:00 2001 From: caojianbin <1910336823> Date: Fri, 29 Mar 2024 10:39:09 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=9B=BD=E9=99=85=E5=8C=96,?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=A8=A1=E5=9D=97=E8=AE=BE=E5=A4=87=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/issue/mqtt/AppSingleMqttClient.java | 162 +++++++++++++++++++++ .../common/security/auth/AuthLogic.java | 114 +++++++++++++-- .../system/annotation/ApiRateLimiter.java | 18 +++ .../system/config/ApiRedisConfig.java | 20 +++ .../system/entity/api/ApiTrackInfo.java | 36 +++++ .../service/api/impl/ApiOutwardServiceImpl.java | 21 +++ .../src/main/resources/application-dev.yml | 90 ++++++++++++ 7 files changed, 445 insertions(+), 16 deletions(-) create mode 100644 ecell-internationalize/ecell-internationalize-common/ecell-internationalize-issue/src/main/java/com/ecell/internationalize/common/issue/mqtt/AppSingleMqttClient.java create mode 100644 ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/annotation/ApiRateLimiter.java create mode 100644 ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/config/ApiRedisConfig.java create mode 100644 ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/entity/api/ApiTrackInfo.java create mode 100644 ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/service/api/impl/ApiOutwardServiceImpl.java create mode 100644 ecell-internationalize/ecell-internationalize-system/src/main/resources/application-dev.yml diff --git a/ecell-internationalize/ecell-internationalize-common/ecell-internationalize-issue/src/main/java/com/ecell/internationalize/common/issue/mqtt/AppSingleMqttClient.java b/ecell-internationalize/ecell-internationalize-common/ecell-internationalize-issue/src/main/java/com/ecell/internationalize/common/issue/mqtt/AppSingleMqttClient.java new file mode 100644 index 0000000..48d454e --- /dev/null +++ b/ecell-internationalize/ecell-internationalize-common/ecell-internationalize-issue/src/main/java/com/ecell/internationalize/common/issue/mqtt/AppSingleMqttClient.java @@ -0,0 +1,162 @@ +package com.ecell.internationalize.common.issue.mqtt; + +import com.ecell.internationalize.common.core.utils.StringUtils; +import com.ecell.internationalize.common.issue.callback.CustomMessageCallback; +import com.ecell.internationalize.common.issue.util.RandomUtil; +import org.eclipse.paho.client.mqttv3.*; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author borui + */ +public class AppSingleMqttClient { + private static final Logger logger = LoggerFactory.getLogger(AppSingleMqttClient.class); + private static MqttClient mqttClient=null; + //防止指令重排 + private volatile static AppSingleMqttClient appSingleMqttClient; + + //初始化链接 + private AppSingleMqttClient() { + MqttConnectOptions mqttConnectOptions = getMqttConnectOptions(); + //设置持久化方式 + MemoryPersistence memoryPersistence = new MemoryPersistence(); + //集群就随机 + String clientId ="ecell-internationalize"+ RandomUtil.generateVerCode(6)+System.currentTimeMillis(); + //单实例写死 + //String clientId ="yisai@@@777"; + if (null != clientId) { + try { + //tcp://120.77.209.176:1883 + mqttClient = new MqttClient("tcp://1.13.186.145:1883", clientId, memoryPersistence); + } catch (MqttException e) { + logger.info("创建链接失败:{}",e.getMessage()); + e.printStackTrace(); + } + } + //设置连接和回调 + if (null != mqttClient) { + if (!mqttClient.isConnected()) { + //创建回调函数对象 + // MQTTReceiveCallback MQTTReceiveCallback = new MQTTReceiveCallback(); + //客户端添加回调函数(默认打印) + mqttClient.setCallback(new CustomMessageCallback()); + //创建连接 + try { + logger.info("开始建立链接"); + mqttClient.connect(mqttConnectOptions); + } catch (MqttException e) { + // destroy(); +// try { +// Thread.sleep(100); +// reconnection(); +// } catch (InterruptedException interruptedException) { +// interruptedException.printStackTrace(); +// } +// logger.info("创建链接失败:",e.getMessage()); +// e.printStackTrace(); + } + + } + } + + } + + /** + * 设置参数 + */ + private static MqttConnectOptions getMqttConnectOptions(){ + //初始化连接设置对象 + MqttConnectOptions mqttConnectOptions = new MqttConnectOptions(); + //设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录, + //这里设置为true表示每次连接到服务器都以新的身份连接 + mqttConnectOptions.setCleanSession(true); + //设置连接超时时间,单位是秒 + mqttConnectOptions.setConnectionTimeout(10); + mqttConnectOptions.setUserName("admin"); + mqttConnectOptions.setPassword("public".toCharArray()); + //保留回话 + // mqttConnectOptions.setCleanSession(false); + // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制 + // mqttConnectOptions.setKeepAliveInterval(60); + //自动重连 + // mqttConnectOptions.setAutomaticReconnect(true); + //建立链接 + //setWill方法,如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息 //遗嘱 + // mqttConnectOptions.setWill(mqttConfig.getSubTopic(), "客户端已经下线".getBytes(), 2, true); + return mqttConnectOptions; + } + + public static AppSingleMqttClient getAppSingleMqttClient(){ + logger.info("开始建立链接:{}",appSingleMqttClient); + if (null==appSingleMqttClient){ + synchronized (AppSingleMqttClient.class){ + if (null==appSingleMqttClient){ + appSingleMqttClient= new AppSingleMqttClient(); + } + } + } + return appSingleMqttClient; + } + + public static void destroy(){ + logger.info("释放链接start:{}",mqttClient); + if (null!=mqttClient){ + try { + mqttClient.disconnect(); + mqttClient.close(); + }catch (MqttException e){ + logger.info("释放资源失败:{}",e.getMessage()); + } + } + } + + public static void reconnection(){ + logger.info("重新链接方法被调用:{},{}",appSingleMqttClient,mqttClient,mqttClient.isConnected()); + if (null==appSingleMqttClient){ + logger.info("重新链接"); + AppSingleMqttClient.getAppSingleMqttClient(); + }else { + if (null !=mqttClient){ + try { + MqttConnectOptions mqttConnectOptions = getMqttConnectOptions(); + logger.info("进行重新链接:{}",mqttConnectOptions); + mqttClient.connect(mqttConnectOptions); + } catch (MqttException e) { + e.printStackTrace(); + } + } + } + } + /**自定义发布消息*/ + public static void publishCustomMessage(int qos,String message,String pubTopic) { + logger.info("开始发送的信息是:{}",message); + if(StringUtils.isNotNull(mqttClient) && mqttClient.isConnected()) { + logger.info("发布自定义信息客户端状态:{},id:{},topic:{}",mqttClient.isConnected(),mqttClient.getClientId(),pubTopic); + MqttMessage mqttMessage = new MqttMessage(); + mqttMessage.setQos(qos); + mqttMessage.setPayload(message.getBytes()); + MqttTopic topic = mqttClient.getTopic(pubTopic); + if(null != topic) { + try { + logger.info("发送的信息是:{}",message); + MqttDeliveryToken publish = topic.publish(mqttMessage); + if(!publish.isComplete()) { + System.out.println("消息发布成功"); + } + } catch (MqttException exception) { + logger.info("发送的信息失败:{}",exception.getMessage()); + } + + } + + + }else { + // AppSingleMqttClient.getAppSingleMqttClient(); + //这里可以做重新链接 + logger.info("客户端为null{}",mqttClient); + reconnection(); + } + } +} diff --git a/ecell-internationalize/ecell-internationalize-common/ecell-internationalize-security/src/main/java/com/ecell/internationalize/common/security/auth/AuthLogic.java b/ecell-internationalize/ecell-internationalize-common/ecell-internationalize-security/src/main/java/com/ecell/internationalize/common/security/auth/AuthLogic.java index ae39784..db54e03 100644 --- a/ecell-internationalize/ecell-internationalize-common/ecell-internationalize-security/src/main/java/com/ecell/internationalize/common/security/auth/AuthLogic.java +++ b/ecell-internationalize/ecell-internationalize-common/ecell-internationalize-security/src/main/java/com/ecell/internationalize/common/security/auth/AuthLogic.java @@ -2,6 +2,7 @@ package com.ecell.internationalize.common.security.auth; import com.ecell.internationalize.common.core.domain.LoginUser; import com.ecell.internationalize.common.core.domain.SysUser; +import com.ecell.internationalize.common.core.domain.UserLogin; import com.ecell.internationalize.common.core.exception.auth.NotLoginException; import com.ecell.internationalize.common.core.exception.auth.NotPermissionException; import com.ecell.internationalize.common.core.exception.auth.NotRoleException; @@ -15,6 +16,7 @@ import com.ecell.internationalize.common.security.service.TokenService; import com.ecell.internationalize.common.security.utils.SecurityUtils; import org.springframework.util.PatternMatchUtils; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -92,6 +94,86 @@ public class AuthLogic { return tokenService.getLoginUser(token); } + + + /** + * 获取yisai当前用户缓存信息, 如果未登录,则抛出异常 + * + * @return 用户缓存信息 + */ + + + + public UserLogin getUserLogin() + { + String token = SecurityUtils.getToken(); + if (token == null) + { + throw new NotLoginException("未提供token"); + } + UserLogin loginUser = SecurityUtils.getUserLogin(); + if (loginUser == null) + { + throw new NotLoginException("无效的token"); + } + return loginUser; + } + + + + /** + * 验证用户是否含有指定权限,必须全部拥有 + * + * @param permissions 权限列表 + */ + public void checkPermiAnd(String... permissions) + { + Set permissionList = getYiSaiPermiList(); + System.out.println("查询到的权限:"+permissionList); + System.out.println("接口上设置的权限为:"+ Arrays.toString(permissions)); + for (String permission : permissions) + { + if (!hasPermi(permissionList, permission)) + { + System.out.println("未通过权限校验"); + throw new NotPermissionException(permission); + } + } + } + + + + + /** + * yisai获取当前账号的权限列表 + * + * @return 权限列表 + */ + public Set getYiSaiPermiList() + { + try + { + UserLogin loginUser = getUserLogin(); + return loginUser.getPermissions(); + } + catch (Exception e) + { + return new HashSet<>(); + } + } + + + /** + * 获取yisai当前用户缓存信息, 如果未登录,则抛出异常 + * + * @param token 前端传递的认证信息 + * @return 用户缓存信息 + */ + public UserLogin getUserLogin(String token) + { + return tokenService.getUserLogin(token); + } + /** * 验证当前用户有效期, 如果相差不足120分钟,自动刷新缓存 * @@ -144,22 +226,22 @@ public class AuthLogic { } } - /** - * 验证用户是否含有指定权限,必须全部拥有 - * - * @param permissions 权限列表 - */ - public void checkPermiAnd(String... permissions) - { - Set permissionList = getPermiList(); - for (String permission : permissions) - { - if (!hasPermi(permissionList, permission)) - { - throw new NotPermissionException(permission); - } - } - } +// /** +// * 验证用户是否含有指定权限,必须全部拥有 +// * +// * @param permissions 权限列表 +// */ +// public void checkPermiAnd(String... permissions) +// { +// Set permissionList = getPermiList(); +// for (String permission : permissions) +// { +// if (!hasPermi(permissionList, permission)) +// { +// throw new NotPermissionException(permission); +// } +// } +// } /** * 验证用户是否含有指定权限,只需包含其中一个 diff --git a/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/annotation/ApiRateLimiter.java b/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/annotation/ApiRateLimiter.java new file mode 100644 index 0000000..4c21a3c --- /dev/null +++ b/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/annotation/ApiRateLimiter.java @@ -0,0 +1,18 @@ +package com.ecell.internationalize.system.annotation; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author borui + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ApiRateLimiter { + String key() default "rate_limit:"; + int time() default 60; + int count() default 100; +} diff --git a/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/config/ApiRedisConfig.java b/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/config/ApiRedisConfig.java new file mode 100644 index 0000000..4e8124e --- /dev/null +++ b/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/config/ApiRedisConfig.java @@ -0,0 +1,20 @@ +package com.ecell.internationalize.system.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.core.io.ClassPathResource; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.scripting.support.ResourceScriptSource; + +/** + * @author borui + */ +//@Configuration +public class ApiRedisConfig { + @Bean + public DefaultRedisScript limitScript(){ + DefaultRedisScript script = new DefaultRedisScript<>(); + script.setResultType(Long.class); + script.setScriptSource(new ResourceScriptSource(new ClassPathResource("111.lua"))); + return script; + } +} diff --git a/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/entity/api/ApiTrackInfo.java b/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/entity/api/ApiTrackInfo.java new file mode 100644 index 0000000..0c2d907 --- /dev/null +++ b/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/entity/api/ApiTrackInfo.java @@ -0,0 +1,36 @@ +package com.ecell.internationalize.system.entity.api; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author borui + */ +@Data +@NoArgsConstructor +public class ApiTrackInfo implements Serializable { + private static final long serialVersionUID=1L; + @ApiModelProperty(value = "经度") + private String longitude; + + @ApiModelProperty(value = "纬度") + private String latitude; + + @ApiModelProperty(value = "(定位类型 LBS, GPS,WIFI)") + private String locationType; + + @ApiModelProperty(value = "详细地址") + private String addr; + + @ApiModelProperty(value = "更新日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateTime; + + + +} diff --git a/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/service/api/impl/ApiOutwardServiceImpl.java b/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/service/api/impl/ApiOutwardServiceImpl.java new file mode 100644 index 0000000..746c968 --- /dev/null +++ b/ecell-internationalize/ecell-internationalize-system/src/main/java/com/ecell/internationalize/system/service/api/impl/ApiOutwardServiceImpl.java @@ -0,0 +1,21 @@ +package com.ecell.internationalize.system.service.api.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ecell.internationalize.system.entity.api.ApiOutward; +import com.ecell.internationalize.system.mapper.api.ApiOutwardMapper; +import com.ecell.internationalize.system.service.api.ApiOutwardService; +import org.springframework.stereotype.Service; + +/** + *

+ * + * API对外开放接口表 服务实现类 + *

+ * + * @author ${author} + * @since 2023-03-07 + */ +@Service +public class ApiOutwardServiceImpl extends ServiceImpl implements ApiOutwardService { + +} diff --git a/ecell-internationalize/ecell-internationalize-system/src/main/resources/application-dev.yml b/ecell-internationalize/ecell-internationalize-system/src/main/resources/application-dev.yml new file mode 100644 index 0000000..31b3929 --- /dev/null +++ b/ecell-internationalize/ecell-internationalize-system/src/main/resources/application-dev.yml @@ -0,0 +1,90 @@ +spring: + servlet: + multipart: + max-file-size: 1024MB + max-request-size: 1024MB + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://192.168.0.113:3306/ys-business?serverTimeZone=UTC + username: root + password: 123456 + #数据源的其他配置 + druid: + initial-size: 5 + min-idle: 5 + max-active: 20 + max-wait: 60000 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + validation-query: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxPoolPreparedStatementPerConnectionSize: 20 +# redis: +# host: localhost +# port: 6379 + redis: + host: 120.77.209.176 + port: 6379 + database: 2 + password: Ecell...20201001 + kafka: + bootstrap-servers: 120.77.209.176:8092 #172.18.238.14:9095,172.18.238.13:9095,172.18.238.11:9095 # + producer: + acks: -1 # 应答级别:多少个分区副本备份完成时向生产者发送ack确认(可选0、1、all/-1) + retries: 1 # 重试次数 + batch-size: 1024 # 批量大小 + properties: + linger: + ms: 0 + buffer-memory: 22334455 # 生产端缓冲区大小 + key-serializer: org.apache.kafka.common.serialization.StringSerializer # Kafka提供的序列化和反序列化类(可以不用配置默认就是) + value-serializer: org.apache.kafka.common.serialization.StringSerializer # Kafka提供的序列化和反序列化类(可以不用配置默认就是) + + # 配置国际化资源文件路径 + messages: + basename: i18n/messages + encoding: UTF-8 + #设置静态资源路径,多个以逗号分隔 + web: + resources: + static-locations: classpath:static/ + +mybatis: + #配置SQL映射文件路径 + mapper-locations: classpath:mapper/*.xml + # 搜索指定包别名 + typeAliasesPackage: com.ecell.internationalize.system + #驼峰命名 + configuration: + map-underscore-to-camel-case: true +# feign 配置 +feign: + sentinel: + enabled: true + okhttp: + enabled: true + httpclient: + enabled: false + client: + config: + default: + connectTimeout: 10000 + readTimeout: 10000 + compression: + request: + enabled: true + response: + enabled: true +# 暴露监控端点 +management: + endpoints: + web: + exposure: + include: '*' +logging: + level: + com.ecell.internationalize.system.mapper: debug +