From 3dadd51018b621bbb5b3abcde94df6d8fa9fbf6b Mon Sep 17 00:00:00 2001
From: ‘liusuyi’ <1951119284@qq.com>
Date: Wed, 23 Aug 2023 14:36:34 +0800
Subject: [PATCH] 重构minio工具类 配置文件区分生产环境和开发环境

---
 src/main/java/com/ard/utils/minio/MinioUtils.java                                 |  592 ++++++++++++++++++++
 src/main/java/com/ard/utils/spring/SpringUtils.java                               |  158 +++++
 src/main/java/com/ard/alarm/apponekey/controller/ArdAlarmApponekeyController.java |   12 
 src/main/java/com/ard/utils/mqtt/MqttConsumerCallback.java                        |    4 
 src/main/resources/application-prod.yml                                           |   67 ++
 src/main/java/com/ard/utils/hiksdk/service/impl/HikClientUtil.java                |   11 
 /dev/null                                                                         |   56 -
 src/main/java/com/ard/utils/minio/MinioConfig.java                                |   33 +
 src/main/java/com/ard/utils/udp/NettyUdpHandler.java                              |    4 
 src/main/java/com/ard/utils/hiksdk/service/impl/FMSGCallBack.java                 |   18 
 src/main/resources/application-dev.yml                                            |   70 ++
 src/main/java/com/ard/utils/mqtt/MqttConsumer.java                                |   31 
 src/main/java/com/ard/utils/other/StringUtils.java                                |  577 +++++++++++++++++++
 src/main/resources/application.yml                                                |   63 --
 14 files changed, 1,548 insertions(+), 148 deletions(-)

diff --git a/src/main/java/com/ard/alarm/apponekey/controller/ArdAlarmApponekeyController.java b/src/main/java/com/ard/alarm/apponekey/controller/ArdAlarmApponekeyController.java
index eb9295d..c9428ee 100644
--- a/src/main/java/com/ard/alarm/apponekey/controller/ArdAlarmApponekeyController.java
+++ b/src/main/java/com/ard/alarm/apponekey/controller/ArdAlarmApponekeyController.java
@@ -1,12 +1,12 @@
 package com.ard.alarm.apponekey.controller;
 
-import com.ard.utils.hiksdk.util.minio.MinioUtils;
 import com.ard.utils.http.AjaxResult;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ard.utils.minio.MinioUtils;
 import org.springframework.web.bind.annotation.*;
 import com.ard.alarm.apponekey.domain.ArdAlarmApponekey;
 import com.ard.alarm.apponekey.service.IArdAlarmApponekeyService;
 import org.springframework.web.multipart.MultipartFile;
+import javax.annotation.Resource;
 
 
 /**
@@ -18,16 +18,16 @@
 @RestController
 @RequestMapping("/alarm/apponekey")
 public class ArdAlarmApponekeyController {
-    @Autowired
+    @Resource
     private IArdAlarmApponekeyService ardAlarmApponekeyService;
-
-
+    @Resource
+    private MinioUtils minioUtil;
     /**
      * 新增app一键报警
      */
     @PostMapping
     public AjaxResult add(String userId,String name, Double longitude,Double latitude,Double altitude,MultipartFile file) {
-        String url = MinioUtils.putObjectAndGetUrl("record", file);
+        String url = minioUtil.putObjectAndGetUrl("record", file);
         ArdAlarmApponekey ardAlarmApponekey =new ArdAlarmApponekey();
         ardAlarmApponekey.setUserId(userId);
         ardAlarmApponekey.setName(name);
diff --git a/src/main/java/com/ard/config/MinioClientSingleton.java b/src/main/java/com/ard/config/MinioClientSingleton.java
deleted file mode 100644
index 3cdbd35..0000000
--- a/src/main/java/com/ard/config/MinioClientSingleton.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.ard.config;
-
-import com.ard.utils.other.SpringTool;
-import io.minio.MinioClient;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.annotation.Bean;
-import org.springframework.integration.channel.DefaultHeaderChannelRegistry;
-import org.springframework.integration.channel.PublishSubscribeChannel;
-import org.springframework.stereotype.Component;
-
-/**
- * @Description:
- * @ClassName: MinioClientSingleton
- * @Author: 刘苏义
- * @Date: 2023年05月18日9:32
- * @Version: 1.0
- **/
-
-@Slf4j(topic = "minio")
-@Component
-public class MinioClientSingleton {
-
-    public static String domainUrl;
-    private static String accessKey;
-    private static String secretKey;
-
-    private volatile static MinioClient minioClient;
-
-    static {
-        domainUrl = SpringTool.getYmlInfo("minio.endpoint");
-        accessKey = SpringTool.getYmlInfo("minio.accessKey");
-        secretKey = SpringTool.getYmlInfo("minio.secretKey");
-        log.debug("minio信息:" + domainUrl + "(" + accessKey + "/" + secretKey + ")");
-    }
-
-    /**
-     * 获取minio客户端实例
-     *
-     * @return {@link MinioClient}
-     */
-    public static MinioClient getMinioClient() {
-        if (minioClient == null) {
-            synchronized (MinioClientSingleton.class) {
-                if (minioClient == null) {
-                    minioClient = MinioClient.builder()
-                            .endpoint(domainUrl)
-                            .credentials(accessKey, secretKey)
-                            .build();
-                }
-            }
-        }
-        return minioClient;
-    }
-
-
-    @Bean
-    public PublishSubscribeChannel errorChannel() {
-        return new PublishSubscribeChannel();
-    }
-    @Bean
-    public DefaultHeaderChannelRegistry integrationHeaderChannelRegistry() {
-        return new DefaultHeaderChannelRegistry();
-    }
-}
-
diff --git a/src/main/java/com/ard/utils/hiksdk/service/impl/FMSGCallBack.java b/src/main/java/com/ard/utils/hiksdk/service/impl/FMSGCallBack.java
index 68eda58..d0cae9d 100644
--- a/src/main/java/com/ard/utils/hiksdk/service/impl/FMSGCallBack.java
+++ b/src/main/java/com/ard/utils/hiksdk/service/impl/FMSGCallBack.java
@@ -6,17 +6,16 @@
 import com.ard.alarm.camera.service.IArdCamerasService;
 import com.ard.alarm.external.domain.ArdEquipExternal;
 import com.ard.alarm.external.service.IArdEquipExternalService;
-import com.ard.config.MinioClientSingleton;
+import com.ard.utils.minio.MinioUtils;
 import com.ard.utils.other.ByteUtils;
 import com.ard.utils.hiksdk.common.GlobalVariable;
 import com.ard.utils.hiksdk.domain.AccessControlHostEventInfo;
 import com.ard.utils.hiksdk.domain.CameraEventInfo;
 import com.ard.utils.hiksdk.domain.ExternalAlarmEventInfo;
 import com.ard.utils.hiksdk.util.hikSdkUtil.HCNetSDK;
-import com.ard.utils.hiksdk.util.minio.MinioUtils;
 import com.ard.utils.other.DateUtils;
-import com.ard.utils.other.SpringTool;
 import com.ard.utils.mqtt.MqttConsumer;
+import com.ard.utils.spring.SpringUtils;
 import com.ard.utils.uuid.IdUtils;
 import com.sun.jna.Pointer;
 import lombok.extern.slf4j.Slf4j;
@@ -61,7 +60,7 @@
                 ArdCameras ardCameras = new ArdCameras();
                 ardCameras.setIp(sDeviceIP);
                 ardCameras.setPort(wLinkPort);
-                IArdCamerasService ardCamerasService = SpringTool.getApplicationContext().getBean(IArdCamerasService.class);
+                IArdCamerasService ardCamerasService = SpringUtils.getBean(IArdCamerasService.class);
                 ArdCameras camera = ardCamerasService.selectArdCamerasList(ardCameras).get(0);
                 HCNetSDK.NET_DVR_ALARMINFO_V30 netDvrAlarminfoV30 = new HCNetSDK.NET_DVR_ALARMINFO_V30();
                 netDvrAlarminfoV30.write();
@@ -95,7 +94,7 @@
                 ardCameras = new ArdCameras();
                 ardCameras.setIp(sDeviceIP);
                 ardCameras.setPort(wLinkPort);
-                ardCamerasService = SpringTool.getApplicationContext().getBean(IArdCamerasService.class);
+                ardCamerasService = SpringUtils.getBean(IArdCamerasService.class);
                 ArdCameras ardCamera = ardCamerasService.selectArdCamerasList(ardCameras).get(0);
 
                 HCNetSDK.NET_VCA_RULE_ALARM strVcaAlarm = new HCNetSDK.NET_VCA_RULE_ALARM();
@@ -190,7 +189,7 @@
                 ArdEquipExternal ardEquipExternal = new ArdEquipExternal();
                 ardEquipExternal.setIp(sDeviceIP);
                 ardEquipExternal.setPort(wLinkPort);
-                IArdEquipExternalService ardEquipExternalService = SpringTool.getApplicationContext().getBean(IArdEquipExternalService.class);
+                IArdEquipExternalService ardEquipExternalService = SpringUtils.getBean(IArdEquipExternalService.class);
                 ardEquipExternal = ardEquipExternalService.selectArdEquipExternal(ardEquipExternal);
 
 
@@ -276,7 +275,7 @@
                 ArdEquipExternal accessControlHost = new ArdEquipExternal();
                 accessControlHost.setIp(sDeviceIP);
                 accessControlHost.setPort(wLinkPort);
-                ardEquipExternalService = SpringTool.getApplicationContext().getBean(IArdEquipExternalService.class);
+                ardEquipExternalService = SpringUtils.getBean(IArdEquipExternalService.class);
                 accessControlHost = ardEquipExternalService.selectArdEquipExternal(accessControlHost);
 
                 HCNetSDK.NET_DVR_ACS_ALARM_INFO strACSInfo = new HCNetSDK.NET_DVR_ACS_ALARM_INFO();
@@ -322,9 +321,10 @@
                         InputStream input = new ByteArrayInputStream(bytes);
                         String bucketName = "pic";
                         String objectName = "alarm/" + IdUtils.simpleUUID() + ".jpeg";
-                        boolean uploadObject = MinioUtils.uploadObject(bucketName, objectName, input, "image/JPEG");
+                        MinioUtils minioUtil = SpringUtils.getBean(MinioUtils.class);
+                        boolean uploadObject = minioUtil.uploadObject(bucketName, objectName, input,input.available(), "image/JPEG");
                         if (uploadObject) {
-                            url = MinioClientSingleton.domainUrl + "/" + bucketName + "/" + objectName;
+                            url = minioUtil.getBucketObjectUrl(bucketName, objectName);
                             //log.debug("上传文件成功!" + url);
                         }
                     } catch (Exception e) {
diff --git a/src/main/java/com/ard/utils/hiksdk/service/impl/HikClientUtil.java b/src/main/java/com/ard/utils/hiksdk/service/impl/HikClientUtil.java
index 92b0b37..2bb03b3 100644
--- a/src/main/java/com/ard/utils/hiksdk/service/impl/HikClientUtil.java
+++ b/src/main/java/com/ard/utils/hiksdk/service/impl/HikClientUtil.java
@@ -3,12 +3,12 @@
 import com.ard.alarm.camera.domain.ArdCameras;
 import com.ard.alarm.camera.domain.CameraCmd;
 import com.ard.alarm.external.domain.ArdEquipExternal;
-import com.ard.config.MinioClientSingleton;
+import com.ard.utils.minio.MinioUtils;
 import com.ard.utils.other.ByteUtils;
 import com.ard.utils.hiksdk.common.GlobalVariable;
 import com.ard.utils.hiksdk.domain.DeviceInfo;
 import com.ard.utils.hiksdk.util.hikSdkUtil.HCNetSDK;
-import com.ard.utils.hiksdk.util.minio.MinioUtils;
+import com.ard.utils.spring.SpringUtils;
 import com.sun.jna.Native;
 import com.sun.jna.Platform;
 import com.sun.jna.Pointer;
@@ -434,11 +434,10 @@
             InputStream input = new ByteArrayInputStream(array);
             String url = "";
             try {
-                boolean b = MinioUtils.uploadObject(cmd.getBucketName(), cmd.getObjectName(), input, ContentType);
+                MinioUtils minioUtil = SpringUtils.getBean(MinioUtils.class);
+                boolean b = minioUtil.uploadObject(cmd.getBucketName(), cmd.getObjectName(), input,input.available(), ContentType);
                 if (b) {
-                    // url = MinioUtils.getBucketObjectUrl(cmd.getBucketName(), cmd.getObjectName());
-                    // url = url.indexOf('?') != -1 ? url.substring(0, url.indexOf('?')) : url;
-                    url = MinioClientSingleton.domainUrl + "/" + cmd.getBucketName() + "/" + cmd.getObjectName();
+                    url = minioUtil.getBucketObjectUrl(cmd.getBucketName(), cmd.getObjectName());
                    // log.debug("上传文件成功!" + url);
                 }
             } catch (Exception ex) {
diff --git a/src/main/java/com/ard/utils/hiksdk/util/minio/MinioUtils.java b/src/main/java/com/ard/utils/hiksdk/util/minio/MinioUtils.java
deleted file mode 100644
index 0e600e0..0000000
--- a/src/main/java/com/ard/utils/hiksdk/util/minio/MinioUtils.java
+++ /dev/null
@@ -1,477 +0,0 @@
-package com.ard.utils.hiksdk.util.minio;
-
-import com.ard.config.MinioClientSingleton;
-import io.minio.*;
-import io.minio.http.Method;
-import io.minio.messages.Bucket;
-import io.minio.messages.DeleteError;
-import io.minio.messages.DeleteObject;
-import io.minio.messages.Item;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.multipart.MultipartFile;
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-
-/**
- * @Description: Minio客户端工具类
- * @ClassName: MinioUtils
- * @Author: 刘苏义
- * @Date: 2023年05月18日9:34
- * @Version: 1.0
- **/
-@SuppressWarnings("ALL")
-@Slf4j(topic = "minio")
-public class MinioUtils {
-
-    /**
-     * 判断桶是否存在
-     */
-    public static boolean exitsBucket(String bucketName) {
-        boolean found = false;
-        try {
-            BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build();
-            found = MinioClientSingleton.getMinioClient().bucketExists(bucketExistsArgs);
-        } catch (Exception ex) {
-            log.error("minio判断桶存在异常:", ex.getMessage());
-        }
-        return found;
-    }
-
-    /**
-     * 创建桶,并设置桶策略为公共
-     */
-    public static boolean createBucket(String bucketName) {
-        try {
-            /*创建桶*/
-            MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();
-            MinioClientSingleton.getMinioClient().makeBucket(makeBucketArgs);
-            /*设置策略*/
-            String sb = "{\"Version\":\"2012-10-17\"," +
-                    "\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":" +
-                    "{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"," +
-                    "\"s3:GetBucketLocation\"],\"Resource\":[\"arn:aws:s3:::" + bucketName +
-                    "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\"],\"Resource\":[\"arn:aws:s3:::" +
-                    bucketName + "/*\"]}]}";
-            SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs.builder()
-                    .bucket(bucketName)
-                    .config(sb)
-                    .build();
-            MinioClientSingleton.getMinioClient().setBucketPolicy(setBucketPolicyArgs);
-            return true;
-        } catch (Exception ex) {
-            log.error("minio创建桶异常:", ex.getMessage());
-            return false;
-        }
-    }
-
-    /**
-     * 删除一个桶
-     *
-     * @param bucket 桶名称
-     */
-    public static boolean removeBucket(String bucket) {
-        try {
-            boolean found = exitsBucket(bucket);
-            if (found) {
-                Iterable<Result<Item>> myObjects = MinioClientSingleton.getMinioClient().listObjects(ListObjectsArgs.builder().bucket(bucket).build());
-                for (Result<Item> result : myObjects) {
-                    Item item = result.get();
-                    //有对象文件,则删除失败
-                    if (item.size() > 0) {
-                        return false;
-                    }
-                }
-                // 删除`bucketName`存储桶,注意,只有存储桶为空时才能删除成功。
-                MinioClientSingleton.getMinioClient().removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
-                found = exitsBucket(bucket);
-                return !found;
-            }
-        } catch (Exception ex) {
-            log.error("删除桶异常:" + ex.getMessage());
-        }
-        return false;
-    }
-
-    /**
-     * 查询所有桶文件
-     *
-     * @return
-     */
-    public static List<Bucket> getListBuckets() {
-        try {
-            return MinioClientSingleton.getMinioClient().listBuckets();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return Collections.emptyList();
-    }
-
-    /**
-     * 生成一个GET请求的带有失效时间的分享链接。
-     * 失效时间默认是7天。
-     *
-     * @param bucketName 存储桶名称
-     * @param objectName 存储桶里的对象名称
-     * @param expires    失效时间(以秒为单位),默认是7天,不得大于七天
-     * @return
-     */
-    public static String getObjectWithExpired(String bucketName, String objectName, Integer expires, TimeUnit timeUnit) {
-        String url = "";
-        if (exitsBucket(bucketName)) {
-            try {
-                GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
-                        .method(Method.GET)
-                        .bucket(bucketName)
-                        .object(objectName)
-                        .expiry(expires, timeUnit)
-                        .build();
-                url = MinioClientSingleton.getMinioClient().getPresignedObjectUrl(getPresignedObjectUrlArgs);
-            } catch (Exception ex) {
-                log.error("minio生成失效url异常", ex.getMessage());
-            }
-        }
-        return url;
-    }
-
-    /**
-     * @描述 上传MultipartFile文件返回url
-     * @参数 [bucketName, file]
-     * @返回值 java.lang.String
-     * @创建人 刘苏义
-     * @创建时间 2023/5/18 12:16
-     * @修改人和其它信息
-     */
-    public static String putObjectAndGetUrl(String bucketName, MultipartFile file) {
-        //判断文件是否为空
-        if (null == file || 0 == file.getSize()) {
-            log.error("上传minio文件服务器错误,上传文件为空");
-        }
-        boolean exsit = exitsBucket(bucketName);
-        if (!exsit) {
-            log.error(bucketName + "-桶不存在");
-        }
-        //文件名
-        String originalFilename = file.getOriginalFilename();
-        //新的文件名
-        String fileName = UUID.randomUUID().toString().replace("-", "") +"_"+ originalFilename;
-        try {
-            InputStream inputStream = file.getInputStream();
-            /*上传对象*/
-            PutObjectArgs putObjectArgs = PutObjectArgs
-                    .builder()
-                    .bucket(bucketName)
-                    .object(fileName)
-                    .stream(inputStream, file.getSize(), -1)
-                    .contentType(file.getContentType())
-                    .build();
-            MinioClientSingleton.getMinioClient().putObject(putObjectArgs);
-            inputStream.close();
-            /*获取url*/
-            GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs
-                    .builder()
-                    .method(Method.GET)
-                    .bucket(bucketName)
-                    .object(fileName)
-                    .build();
-            String presignedObjectUrl = MinioClientSingleton.getMinioClient().getPresignedObjectUrl(getPresignedObjectUrlArgs);
-            String ObjectUrl  = presignedObjectUrl.substring(0, presignedObjectUrl.indexOf("?"));
-            return ObjectUrl;
-        } catch (Exception ex) {
-            log.error("上传对象返回url异常:" + ex.getMessage());
-        }
-        return "";
-    }
-
-    /**
-     * 删除文件
-     *
-     * @param bucket     桶名称
-     * @param objectName 对象名称
-     * @return boolean
-     */
-    public static boolean removeObject(String bucket, String objectName) {
-        try {
-            boolean exsit = exitsBucket(bucket);
-            if (exsit) {
-                RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(objectName).build();
-                MinioClientSingleton.getMinioClient().removeObject(removeObjectArgs);
-                return true;
-            }
-        } catch (Exception e) {
-            log.error("removeObject", e);
-        }
-        return false;
-    }
-
-    /**
-     * 批量删除文件
-     *
-     * @param objectNames 对象名称
-     * @return boolean
-     */
-    public static boolean removeObjects(String bucket, List<String> objectNames) {
-        if (exitsBucket(bucket)) {
-            try {
-                List<DeleteObject> objects = new LinkedList<>();
-                for (String str : objectNames) {
-                    objects.add(new DeleteObject(str));
-                }
-                RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder().bucket(bucket).objects(objects).build();
-                Iterable<Result<DeleteError>> results = MinioClientSingleton.getMinioClient().removeObjects(removeObjectsArgs);
-                /*删除完遍历结果,否则删不掉*/
-                for (Result<DeleteError> result : results) {
-                    DeleteError error = result.get();
-                    log.error("Error in deleting object " + error.objectName() + "; " + error.message());
-                }
-
-                return true;
-            } catch (Exception ex) {
-                log.error("minio批量删除文件异常", ex.getMessage());
-            }
-        }
-        return false;
-    }
-
-    /**
-     * 获取单个桶中的所有文件对象名称
-     *
-     * @param bucket 桶名称
-     * @return {@link List}<{@link String}>
-     */
-    public static List<String> getBucketObjectName(String bucket) {
-        boolean exsit = exitsBucket(bucket);
-        if (exsit) {
-            List<String> listObjetcName = new ArrayList<>();
-            try {
-                ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder().bucket(bucket).build();
-                Iterable<Result<Item>> myObjects = MinioClientSingleton.getMinioClient().listObjects(listObjectsArgs);
-                for (Result<Item> result : myObjects) {
-                    Item item = result.get();
-                    listObjetcName.add(item.objectName());
-                }
-                return listObjetcName;
-            } catch (Exception ex) {
-                log.error("minio获取桶下对象异常:" + ex.getMessage());
-            }
-        }
-        return null;
-    }
-
-    /**
-     * 获取某个桶下某个对象的URL
-     *
-     * @param bucket     桶名称
-     * @param objectName 对象名 (文件夹名 + 文件名)
-     * @return
-     */
-    public static String getBucketObjectUrl(String bucketName, String objectName) {
-        try {
-            if (!exitsBucket(bucketName)) {
-                return "";
-            }
-            GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs
-                    .builder()
-                    .bucket(bucketName)
-                    .object(objectName)
-                    .method(Method.GET)
-                    .build();
-            return MinioClientSingleton.getMinioClient().getPresignedObjectUrl(getPresignedObjectUrlArgs);
-        } catch (Exception ex) {
-            log.error("minio获取对象URL异常" + ex.getMessage());
-        }
-        return "";
-    }
-
-    /**
-     * 上传对象-stream
-     *
-     * @param bucketName  bucket名称
-     * @param objectName  ⽂件名称
-     * @param stream      ⽂件流
-     * @param size        ⼤⼩
-     * @param contextType 类型 Image/jpeg 浏览器可以直接打开,否则下载
-     */
-    public static boolean uploadObject(String bucketName, String objectName, InputStream stream, String contextType) {
-        try {
-            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
-                    .bucket(bucketName)
-                    .object(objectName)
-                    .stream(stream, stream.available(), -1)
-                    .contentType(contextType)
-                    .build();
-            ObjectWriteResponse objectWriteResponse = MinioClientSingleton.getMinioClient().putObject(putObjectArgs);
-            return true;
-        } catch (Exception ex) {
-            log.error("minio上传文件(通过stream)异常" + ex.getMessage());
-            return false;
-        }
-    }
-
-    /**
-     * 上传对象-File
-     *
-     * @param bucketName  bucket名称
-     * @param objectName  ⽂件名称
-     * @param file        ⽂件
-     * @param contextType 类型 Image/jpeg 浏览器可以直接打开,否则下载
-     */
-    public static boolean uploadObject(String bucketName, String objectName, File file, String contextType) {
-        try {
-            FileInputStream fileInputStream = new FileInputStream(file);
-            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
-                    .bucket(bucketName)
-                    .object(objectName)
-                    .stream(fileInputStream, file.length(), -1)
-                    .contentType(contextType)
-                    .build();
-            ObjectWriteResponse objectWriteResponse = MinioClientSingleton.getMinioClient().putObject(putObjectArgs);
-            return true;
-        } catch (Exception ex) {
-            log.error("minio上传文件(通过File)异常" + ex.getMessage());
-            return false;
-        }
-    }
-
-    /**
-     * 上传对象-MultipartFile
-     *
-     * @param bucketName    bucket名称
-     * @param objectName    ⽂件名称
-     * @param MultipartFile ⽂件
-     * @param contextType   类型 Image/jpeg 浏览器可以直接打开,否则下载
-     */
-    public static boolean uploadObject(String bucketName, String objectName, MultipartFile multipartFile, String contextType) {
-        try {
-            if (bucketName.isEmpty()) {
-                log.error("bucket名称为空");
-                return false;
-            }
-            if (objectName.isEmpty()) {
-                log.error("对象名称为空");
-                return false;
-            }
-            InputStream inputStream = multipartFile.getInputStream();
-            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
-                    .bucket(bucketName)
-                    .object(objectName)
-                    .stream(inputStream, multipartFile.getSize(), -1)
-                    .contentType(contextType)
-                    .build();
-            ObjectWriteResponse objectWriteResponse = MinioClientSingleton.getMinioClient().putObject(putObjectArgs);
-            return true;
-        } catch (Exception ex) {
-            log.error("minio上传文件(通过File)异常" + ex.getMessage());
-            return false;
-        }
-    }
-
-    /**
-     * 上传对象,用multipartFile名称作为对象名
-     *
-     * @param bucketName    bucket名称
-     * @param objectName    ⽂件名称
-     * @param MultipartFile ⽂件
-     * @param contextType   类型 Image/jpeg 浏览器可以直接打开,否则下载
-     */
-    public static boolean uploadObject(String bucketName, MultipartFile multipartFile, String contextType) {
-        try {
-            if (multipartFile == null) {
-                log.error("上传文件为空");
-                return false;
-            }
-            String objectName = multipartFile.getOriginalFilename();
-            InputStream inputStream = multipartFile.getInputStream();
-            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
-                    .bucket(bucketName)
-                    .object(objectName)
-                    .stream(inputStream, multipartFile.getSize(), -1)
-                    .contentType(contextType)
-                    .build();
-            MinioClientSingleton.getMinioClient().putObject(putObjectArgs);
-            return true;
-        } catch (Exception ex) {
-            log.error("minio上传文件(通过File)异常" + ex.getMessage());
-            return false;
-        }
-    }
-
-    /**
-     * 上传对象-通过本地路径
-     *
-     * @param bulkName
-     * @param objectName
-     * @param localFilePathName
-     * @return
-     */
-    public static boolean uploadObject(String bulkName, String objectName, String localFilePathName, String contextType) {
-        try {
-            if (!exitsBucket(bulkName)) {
-                log.debug(bulkName + "不存在");
-                return false;
-            }
-            File file = new File(localFilePathName);
-            if (!file.exists()) {
-                log.debug("文件不存在");
-                return false;
-            }
-            UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder()
-                    .bucket(bulkName)
-                    .object(objectName)
-                    .filename(localFilePathName)
-                    .contentType(contextType)
-                    .build();
-            ObjectWriteResponse objectWriteResponse = MinioClientSingleton.getMinioClient().uploadObject(uploadObjectArgs);
-            return true;
-        } catch (Exception e) {
-            log.error("minio upload object file error " + e.getMessage());
-            return false;
-        }
-    }
-    /**
-     *@描述 获取桶中所有对象
-     *@参数 [bucketName]
-     *@返回值 java.lang.Iterable<io.minio.Result<io.minio.messages.Item>>
-     *@创建人 刘苏义
-     *@创建时间 2023/2/6 10:32
-     *@修改人和其它信息
-     */
-    public static Iterable<Result<Item>> getObjectsByBucket(String bucketName)  {
-        Iterable<Result<Item>> listObjects = MinioClientSingleton.getMinioClient().listObjects(ListObjectsArgs.builder()
-                .bucket(bucketName)
-                .recursive(true)
-                .build());
-        return listObjects;
-    }
-
-    public static void main(String[] args) {
-        //        /*删除桶*/
-        //        boolean b = removeBucket("lsy");
-        //        log.info(String.valueOf(b));
-        //        /*创建桶*/
-        //        boolean lsy = createBucket("lsy");
-        //        log.info(String.valueOf(lsy));
-        //        /*判断桶是否存在*/
-        //        boolean pic = exitsBucket("lsy");
-        //        log.info(String.valueOf(pic));
-        /*查询所有桶*/
-        //        List<Bucket> listBuckets = getListBuckets();
-        //        for (Bucket bucket : listBuckets) {
-        //            log.info(bucket.name());
-        //        }
-        String bucket = "lsy";
-        String filename = UUID.randomUUID().toString().replace("-", "") + "pic.jpeg";
-        String fileFullPath = "C:\\Users\\Administrator\\Desktop\\微信截图_20230518102605.png";
-        //        uploadObject(bucket, filename, fileFullPath, "Image/jpeg");
-        //        String url = getObjectWithExpired(bucket, filename, 10, SECONDS);
-        //        System.out.println(url);
-        boolean b = removeBucket(bucket);
-        System.out.println(b);
-        //        boolean b = uploadObjectBylocalPath(bucket, filename, fileFullPath);
-        //        System.out.println(b);
-        //String url = getObjectWithExpired(bucket, filename, 10000);
-        //
-        //String url = getBucketObject(bucket, filename);
-        //      System.out.println(url); package com.example.minio;
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/com/ard/utils/minio/MinioConfig.java b/src/main/java/com/ard/utils/minio/MinioConfig.java
new file mode 100644
index 0000000..d5dada5
--- /dev/null
+++ b/src/main/java/com/ard/utils/minio/MinioConfig.java
@@ -0,0 +1,33 @@
+package com.ard.utils.minio;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Description:
+ * @ClassName: MinioClientSingleton
+ * @Author: 刘苏义
+ * @Date: 2023年05月18日9:32
+ * @Version: 1.0
+ **/
+@Slf4j(topic = "minio")
+@Component
+public class MinioConfig {
+    @Value("${spring.minio.endpoint}")
+    private  String endpoint;
+    @Value("${spring.minio.accessKey}")
+    private  String accessKey;
+    @Value("${spring.minio.secretKey}")
+    private  String secretKey;
+
+    @Bean
+    public io.minio.MinioClient getMinioClient() {
+        return io.minio.MinioClient.builder()
+                .endpoint(endpoint)
+                .credentials(accessKey, secretKey)
+                .build();
+    }
+}
+
diff --git a/src/main/java/com/ard/utils/minio/MinioUtils.java b/src/main/java/com/ard/utils/minio/MinioUtils.java
new file mode 100644
index 0000000..d7e5e27
--- /dev/null
+++ b/src/main/java/com/ard/utils/minio/MinioUtils.java
@@ -0,0 +1,592 @@
+package com.ard.utils.minio;
+
+import com.ard.utils.other.StringUtils;
+import com.ard.utils.uuid.IdUtils;
+import io.minio.*;
+import io.minio.http.Method;
+import io.minio.messages.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+import javax.annotation.Resource;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Description: Minio客户端工具类
+ * @ClassName: MinioUtils
+ * @Author: 刘苏义
+ * @Date: 2023年05月18日9:34
+ * @Version: 1.0
+ **/
+@SuppressWarnings("ALL")
+@Slf4j(topic = "minio")
+@Component
+public class MinioUtils {
+
+    @Resource
+    MinioClient minioClient;
+
+    /**
+     * 判断桶是否存在
+     */
+    public boolean exitsBucket(String bucketName) {
+        boolean found = false;
+        try {
+            if (StringUtils.isEmpty(bucketName)) {
+                return false;
+            }
+            BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build();
+            found = minioClient.bucketExists(bucketExistsArgs);
+
+        } catch (Exception ex) {
+            log.error("minio判断桶存在异常:", ex.getMessage());
+        }
+        return found;
+    }
+
+    /**
+     * 创建桶,并设置桶策略为公共
+     */
+    public boolean createBucket(String bucketName) {
+        try {
+            if (StringUtils.isEmpty(bucketName)) {
+                return false;
+            }
+            /*创建桶*/
+            MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();
+            minioClient.makeBucket(makeBucketArgs);
+            /*设置策略*/
+            String sb = "{\"Version\":\"2012-10-17\"," +
+                    "\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":" +
+                    "{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"," +
+                    "\"s3:GetBucketLocation\"],\"Resource\":[\"arn:aws:s3:::" + bucketName +
+                    "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\"],\"Resource\":[\"arn:aws:s3:::" +
+                    bucketName + "/*\"]}]}";
+            SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs.builder()
+                    .bucket(bucketName)
+                    .config(sb)
+                    .build();
+            /*设置通知mqtt*/
+            //设置mqtt主题
+            NotificationConfiguration config = new NotificationConfiguration();
+            List<QueueConfiguration> queueConfigurations = new ArrayList<>();
+            QueueConfiguration queueConfiguration = new QueueConfiguration();
+            queueConfiguration.setQueue("arn:minio:sqs::_:mqtt");
+
+            //设置事件
+            List<EventType> events = new ArrayList<>();
+            events.add(EventType.OBJECT_REMOVED_ANY);
+            events.add(EventType.OBJECT_CREATED_ANY);
+            queueConfiguration.setEvents(events);
+
+            queueConfigurations.add(queueConfiguration);
+            config.setQueueConfigurationList(queueConfigurations);
+            SetBucketNotificationArgs setBucketNotificationArgs = SetBucketNotificationArgs.builder()
+                    .bucket(bucketName)
+                    .config(config).build();
+            minioClient.setBucketPolicy(setBucketPolicyArgs);
+            minioClient.setBucketNotification(setBucketNotificationArgs);
+
+            return true;
+        } catch (Exception ex) {
+            log.error("minio创建桶异常:", ex.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 删除一个桶
+     *
+     * @param bucket 桶名称
+     */
+    public boolean removeBucket(String bucket) {
+        try {
+            boolean found = exitsBucket(bucket);
+            if (found) {
+                Iterable<Result<Item>> myObjects = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucket).build());
+                for (Result<Item> result : myObjects) {
+                    Item item = result.get();
+                    //有对象文件,则删除失败
+                    if (item.size() > 0) {
+                        return false;
+                    }
+                }
+                // 删除`bucketName`存储桶,注意,只有存储桶为空时才能删除成功。
+                minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
+                found = exitsBucket(bucket);
+                return !found;
+            }
+        } catch (Exception ex) {
+            log.error("删除桶异常:" + ex.getMessage());
+        }
+        return false;
+    }
+
+    /**
+     * 查询所有桶文件
+     *
+     * @return
+     */
+    public List<Bucket> getListBuckets() {
+        try {
+            return minioClient.listBuckets();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * 生成一个GET请求的带有失效时间的分享链接。
+     * 失效时间默认是7天。
+     *
+     * @param bucketName 存储桶名称
+     * @param objectName 存储桶里的对象名称
+     * @param expires    失效时间(以秒为单位),默认是7天,不得大于七天
+     * @return
+     */
+    public String getObjectWithExpired(String bucketName, String objectName, Integer expires, TimeUnit timeUnit) {
+        String url = "";
+        if (exitsBucket(bucketName)) {
+            try {
+                GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
+                        .method(Method.GET)
+                        .bucket(bucketName)
+                        .object(objectName)
+                        .expiry(expires, timeUnit)
+                        .build();
+                url = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
+            } catch (Exception ex) {
+                log.error("minio生成失效url异常", ex.getMessage());
+            }
+        } else {
+            createBucket(bucketName);
+        }
+        return url;
+    }
+
+    /**
+     * @描述 上传MultipartFile文件返回url
+     * @参数 [bucketName, file]
+     * @返回值 java.lang.String
+     * @创建人 刘苏义
+     * @创建时间 2023/5/18 12:16
+     * @修改人和其它信息
+     */
+    public String putObjectAndGetUrl(String bucketName, MultipartFile file) {
+        if (!exitsBucket(bucketName)) {
+            createBucket(bucketName);
+        }
+        //判断文件是否为空
+        if (null == file || 0 == file.getSize()) {
+            log.error("上传minio文件服务器错误,上传文件为空");
+        }
+        boolean exsit = exitsBucket(bucketName);
+        if (!exsit) {
+            boolean bucket = createBucket(bucketName);
+            if (bucket) {
+                log.info(bucketName + "-桶不存在,成功创建桶");
+            }
+        }
+        //文件名
+        String originalFilename = file.getOriginalFilename();
+        //新的文件名
+        String fileName = IdUtils.fastSimpleUUID() + "_" + originalFilename;
+        try {
+            InputStream inputStream = file.getInputStream();
+            /*上传对象*/
+            PutObjectArgs putObjectArgs = PutObjectArgs
+                    .builder()
+                    .bucket(bucketName)
+                    .object(fileName)
+                    .stream(inputStream, file.getSize(), -1)
+                    .contentType(file.getContentType())
+                    .build();
+            minioClient.putObject(putObjectArgs);
+            inputStream.close();
+            /*获取url*/
+            GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs
+                    .builder()
+                    .bucket(bucketName)
+                    .object(fileName)
+                    .method(Method.GET)
+                    .build();
+            String presignedObjectUrl = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
+            String ObjectUrl = presignedObjectUrl.substring(0, presignedObjectUrl.indexOf("?"));
+            return ObjectUrl;
+        } catch (Exception ex) {
+            log.error("上传对象返回url异常:" + ex.getMessage());
+        }
+        return "";
+    }
+
+    /**
+     * @描述 上传MultipartFile文件返回url
+     * @参数 [bucketName, file]
+     * @返回值 java.lang.String
+     * @创建人 刘苏义
+     * @创建时间 2023/5/18 12:16
+     * @修改人和其它信息
+     */
+    public String putObjectAndGetUrl(String bucketName, String folder, MultipartFile file) {
+        if (!exitsBucket(bucketName)) {
+            createBucket(bucketName);
+        }
+        //判断文件是否为空
+        if (null == file || 0 == file.getSize()) {
+            log.error("上传minio文件服务器错误,上传文件为空");
+        }
+        boolean exsit = exitsBucket(bucketName);
+        if (!exsit) {
+            boolean bucket = createBucket(bucketName);
+            if (bucket) {
+                log.info(bucketName + "-桶不存在,成功创建桶");
+            }
+        }
+        //文件名
+        String originalFilename = file.getOriginalFilename();
+        //新的文件名
+        String fileName = folder + "/" + IdUtils.fastSimpleUUID() + "_" + originalFilename;
+        try {
+            InputStream inputStream = file.getInputStream();
+            /*上传对象*/
+            PutObjectArgs putObjectArgs = PutObjectArgs
+                    .builder()
+                    .bucket(bucketName)
+                    .object(fileName)
+                    .stream(inputStream, file.getSize(), -1)
+                    .contentType(file.getContentType())
+                    .build();
+            minioClient.putObject(putObjectArgs);
+            inputStream.close();
+            /*获取url*/
+            GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs
+                    .builder()
+                    .bucket(bucketName)
+                    .object(fileName)
+                    .method(Method.GET)
+                    .build();
+            String presignedObjectUrl = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
+            String ObjectUrl = presignedObjectUrl.substring(0, presignedObjectUrl.indexOf("?"));
+            return ObjectUrl;
+        } catch (Exception ex) {
+            log.error("上传对象返回url异常:" + ex.getMessage());
+        }
+        return "";
+    }
+
+    /**
+     * 删除文件
+     *
+     * @param bucket     桶名称
+     * @param objectName 对象名称
+     * @return boolean
+     */
+    public boolean removeObject(String bucket, String objectName) {
+        try {
+            boolean exsit = exitsBucket(bucket);
+            if (exsit) {
+                RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(objectName).build();
+                minioClient.removeObject(removeObjectArgs);
+                return true;
+            }
+        } catch (Exception e) {
+            log.error("removeObject", e);
+        }
+        return false;
+    }
+
+    /**
+     * 批量删除文件
+     *
+     * @param objectNames 对象名称
+     * @return boolean
+     */
+    public boolean removeObjects(String bucket, List<String> objectNames) {
+        if (exitsBucket(bucket)) {
+            try {
+                List<DeleteObject> objects = new LinkedList<>();
+                for (String str : objectNames) {
+                    objects.add(new DeleteObject(str));
+                }
+                RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder().bucket(bucket).objects(objects).build();
+                Iterable<Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs);
+                /*删除完遍历结果,否则删不掉*/
+                for (Result<DeleteError> result : results) {
+                    DeleteError error = result.get();
+                    log.error("Error in deleting object " + error.objectName() + "; " + error.message());
+                }
+
+                return true;
+            } catch (Exception ex) {
+                log.error("minio批量删除文件异常", ex.getMessage());
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 获取单个桶中的所有文件对象名称
+     *
+     * @param bucket 桶名称
+     * @return {@link List}<{@link String}>
+     */
+    public List<String> getBucketObjectName(String bucket) {
+        boolean exsit = exitsBucket(bucket);
+        if (exsit) {
+            List<String> listObjetcName = new ArrayList<>();
+            try {
+                ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder().bucket(bucket).build();
+                Iterable<Result<Item>> myObjects = minioClient.listObjects(listObjectsArgs);
+                for (Result<Item> result : myObjects) {
+                    Item item = result.get();
+                    listObjetcName.add(item.objectName());
+                }
+                return listObjetcName;
+            } catch (Exception ex) {
+                log.error("minio获取桶下对象异常:" + ex.getMessage());
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 获取单个桶中的所有文件对象名称
+     * @param [bucket,prefix]
+     * @return {@link List}<{@link String}>
+     */
+    public List<String> getBucketObjectName(String bucket, String prefix) {
+        boolean exsit = exitsBucket(bucket);
+        if (exsit) {
+            List<String> listObjetcName = new ArrayList<>();
+            try {
+                ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder().prefix(prefix).bucket(bucket).build();
+                Iterable<Result<Item>> myObjects = minioClient.listObjects(listObjectsArgs);
+                for (Result<Item> result : myObjects) {
+                    Item item = result.get();
+                    listObjetcName.add(item.objectName());
+                }
+                return listObjetcName;
+            } catch (Exception ex) {
+                log.error("minio获取桶下对象异常:" + ex.getMessage());
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 获取某个桶下某个对象的URL
+     *
+     * @param bucket     桶名称
+     * @param objectName 对象名 (文件夹名 + 文件名)
+     * @return
+     */
+    public String getBucketObjectUrl(String bucketName, String objectName) {
+        try {
+            if (!exitsBucket(bucketName)) {
+                return "";
+            }
+            GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs
+                    .builder()
+                    .bucket(bucketName)
+                    .object(objectName)
+                    .method(Method.GET)
+                    .build();
+            String presignedObjectUrl = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
+            String ObjectUrl = presignedObjectUrl.substring(0, presignedObjectUrl.indexOf("?"));
+            return ObjectUrl;
+        } catch (Exception ex) {
+            log.error("minio获取对象URL异常" + ex.getMessage());
+        }
+        return "";
+    }
+
+    /**
+     * 上传对象-stream
+     *
+     * @param bucketName  bucket名称
+     * @param objectName  ⽂件名称
+     * @param stream      ⽂件流
+     * @param size        ⼤⼩
+     * @param contextType 类型 Image/jpeg 浏览器可以直接打开,否则下载
+     */
+    public boolean uploadObject(String bucketName, String objectName, InputStream stream, long size, String contextType) {
+        try {
+            if (!exitsBucket(bucketName)) {
+                createBucket(bucketName);
+            }
+            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
+                    .bucket(bucketName)
+                    .object(objectName)
+                    .stream(stream, size, -1)
+                    .contentType(contextType)
+                    .build();
+            ObjectWriteResponse objectWriteResponse = minioClient.putObject(putObjectArgs);
+            return true;
+        } catch (Exception ex) {
+            log.error("minio上传文件(通过stream)异常" + ex.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 上传对象-File
+     *
+     * @param bucketName  bucket名称
+     * @param objectName  ⽂件名称
+     * @param file        ⽂件
+     * @param contextType 类型 Image/jpeg 浏览器可以直接打开,否则下载
+     */
+    public boolean uploadObject(String bucketName, String objectName, File file, String contextType) {
+        try {
+            if (!exitsBucket(bucketName)) {
+                createBucket(bucketName);
+            }
+            FileInputStream fileInputStream = new FileInputStream(file);
+            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
+                    .bucket(bucketName)
+                    .object(objectName)
+                    .stream(fileInputStream, file.length(), -1)
+                    .contentType(contextType)
+                    .build();
+            ObjectWriteResponse objectWriteResponse = minioClient.putObject(putObjectArgs);
+            return true;
+        } catch (Exception ex) {
+            log.error("minio上传文件(通过File)异常" + ex.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 上传对象-MultipartFile
+     *
+     * @param bucketName    bucket名称
+     * @param objectName    ⽂件名称
+     * @param MultipartFile ⽂件
+     * @param contextType   类型 Image/jpeg 浏览器可以直接打开,否则下载
+     */
+    public boolean uploadObject(String bucketName, String objectName, MultipartFile multipartFile, String contextType) {
+        try {
+            if (!exitsBucket(bucketName)) {
+                createBucket(bucketName);
+            }
+            InputStream inputStream = multipartFile.getInputStream();
+            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
+                    .bucket(bucketName)
+                    .object(objectName)
+                    .stream(inputStream, multipartFile.getSize(), -1)
+                    .contentType(contextType)
+                    .build();
+            ObjectWriteResponse objectWriteResponse = minioClient.putObject(putObjectArgs);
+            return true;
+        } catch (Exception ex) {
+            log.error("minio上传文件(通过File)异常" + ex.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 上传对象,用multipartFile名称作为对象名
+     *
+     * @param bucketName    bucket名称
+     * @param objectName    ⽂件名称
+     * @param MultipartFile ⽂件
+     * @param contextType   类型 Image/jpeg 浏览器可以直接打开,否则下载
+     */
+    public boolean uploadObject(String bucketName, MultipartFile multipartFile, String contextType) {
+        try {
+            if (!exitsBucket(bucketName)) {
+                createBucket(bucketName);
+            }
+            if (multipartFile == null) {
+                log.error("上传文件为空");
+                return false;
+            }
+            String objectName = multipartFile.getOriginalFilename();
+            InputStream inputStream = multipartFile.getInputStream();
+            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
+                    .bucket(bucketName)
+                    .object(objectName)
+                    .stream(inputStream, multipartFile.getSize(), -1)
+                    .contentType(contextType)
+                    .build();
+            minioClient.putObject(putObjectArgs);
+            return true;
+        } catch (Exception ex) {
+            log.error("minio上传文件(通过File)异常" + ex.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 上传对象-通过本地路径
+     *
+     * @param bulkName
+     * @param objectName
+     * @param localFilePathName
+     * @return
+     */
+    public boolean uploadObject(String bucketName, String objectName, String localFilePathName, String contextType) {
+        try {
+            if (!exitsBucket(bucketName)) {
+                createBucket(bucketName);
+            }
+            File file = new File(localFilePathName);
+            if (!file.exists()) {
+                log.debug("文件不存在");
+                return false;
+            }
+            UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder()
+                    .bucket(bucketName)
+                    .object(objectName)
+                    .filename(localFilePathName)
+                    .contentType(contextType)
+                    .build();
+            ObjectWriteResponse objectWriteResponse = minioClient.uploadObject(uploadObjectArgs);
+            return true;
+        } catch (Exception e) {
+            log.error("minio upload object file error " + e.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * @描述 获取桶中所有对象
+     * @参数 [bucketName]
+     * @返回值 java.lang.Iterable<io.minio.Result < io.minio.messages.Item>>
+     * @创建人 刘苏义
+     * @创建时间 2023/2/6 10:32
+     * @修改人和其它信息
+     */
+    public Iterable<Result<Item>> getObjectsByBucket(String bucketName) {
+        Iterable<Result<Item>> listObjects = minioClient.listObjects(ListObjectsArgs.builder()
+                .bucket(bucketName)
+                .recursive(true)
+                .build());
+        return listObjects;
+    }
+
+    /**
+     * @描述 获取桶中所有对象
+     * @参数 [bucketName,prefix]
+     * @返回值 java.lang.Iterable<io.minio.Result < io.minio.messages.Item>>
+     * @创建人 刘苏义
+     * @创建时间 2023/2/6 10:32
+     * @修改人和其它信息
+     */
+    public Iterable<Result<Item>> getObjectsByBucket(String bucketName, String prefix) {
+        Iterable<Result<Item>> listObjects = minioClient.listObjects(ListObjectsArgs.builder()
+                .bucket(bucketName)
+                .prefix(prefix)
+                .recursive(true)
+                .build());
+        return listObjects;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ard/utils/mqtt/MqttConsumer.java b/src/main/java/com/ard/utils/mqtt/MqttConsumer.java
index 6c80d29..fc03b39 100644
--- a/src/main/java/com/ard/utils/mqtt/MqttConsumer.java
+++ b/src/main/java/com/ard/utils/mqtt/MqttConsumer.java
@@ -4,6 +4,7 @@
 import org.apache.commons.lang3.StringUtils;
 import org.eclipse.paho.client.mqttv3.*;
 import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.ApplicationArguments;
 import org.springframework.boot.ApplicationRunner;
 import org.springframework.core.annotation.Order;
@@ -23,13 +24,29 @@
 @Slf4j(topic = "mqtt")
 @Order(1)
 public class MqttConsumer implements ApplicationRunner {
+    @Value("${spring.mqtt.enabled}")
+    private Boolean MQTT_ENABLED;
+    @Value("${spring.mqtt.topic}")
+    private String MQTT_TOPIC;
+    @Value("${spring.mqtt.host}")
+    private String MQTT_HOST;
+    @Value("${spring.mqtt.clientId}")
+    private String MQTT_CLIENT_ID;
+    @Value("${spring.mqtt.username}")
+    private String MQTT_USER_NAME;
+    @Value("${spring.mqtt.password}")
+    private String MQTT_PASSWORD;
+    @Value("${spring.mqtt.timeout}")
+    private int MQTT_TIMEOUT;
+    @Value("${spring.mqtt.keepalive}")
+    private int MQTT_KEEP_ALIVE;
 
     private static MqttClient client;
 
     @Override
     public void run(ApplicationArguments args) {
         log.debug("初始化并启动mqtt......");
-        if (PropertiesUtil.MQTT_ENABLED) {
+        if (MQTT_ENABLED) {
             this.connect();
         }
     }
@@ -43,7 +60,7 @@
             getClient();
             // 2 设置配置
             MqttConnectOptions options = getOptions();
-            String[] topic = PropertiesUtil.MQTT_TOPIC.split(",");
+            String[] topic = MQTT_TOPIC.split(",");
             // 3 消息发布质量
             int[] qos = getQos(topic.length);
             // 4 最后设置
@@ -59,7 +76,7 @@
     public void getClient() {
         try {
             if (null == client) {
-                client = new MqttClient(PropertiesUtil.MQTT_HOST, PropertiesUtil.MQTT_CLIENT_ID, new MemoryPersistence());
+                client = new MqttClient(MQTT_HOST, MQTT_CLIENT_ID, new MemoryPersistence());
             }
             log.debug("--创建mqtt客户端");
         } catch (Exception e) {
@@ -73,12 +90,12 @@
     public MqttConnectOptions getOptions() {
         MqttConnectOptions options = new MqttConnectOptions();
         //设置用户名密码
-        options.setUserName(PropertiesUtil.MQTT_USER_NAME);
-        options.setPassword(PropertiesUtil.MQTT_PASSWORD.toCharArray());
+        options.setUserName(MQTT_USER_NAME);
+        options.setPassword(MQTT_PASSWORD.toCharArray());
         // 设置超时时间
-        options.setConnectionTimeout(PropertiesUtil.MQTT_TIMEOUT);
+        options.setConnectionTimeout(MQTT_TIMEOUT);
         // 设置会话心跳时间
-        options.setKeepAliveInterval(PropertiesUtil.MQTT_KEEP_ALIVE);
+        options.setKeepAliveInterval(MQTT_KEEP_ALIVE);
         // 是否清除session
         options.setCleanSession(true);
         log.debug("--生成mqtt配置对象");
diff --git a/src/main/java/com/ard/utils/mqtt/MqttConsumerCallback.java b/src/main/java/com/ard/utils/mqtt/MqttConsumerCallback.java
index 20e9f7c..b0ee239 100644
--- a/src/main/java/com/ard/utils/mqtt/MqttConsumerCallback.java
+++ b/src/main/java/com/ard/utils/mqtt/MqttConsumerCallback.java
@@ -81,10 +81,10 @@
             if (null != topic && null != qos) {
                 if (client.isConnected()) {
                     client.subscribe(topic, qos);
-                    log.debug("mqtt连接成功,客户端ID:" + PropertiesUtil.MQTT_CLIENT_ID);
+                    log.debug("mqtt连接成功");
                     log.debug("--订阅主题::" + Arrays.toString(topic));
                 } else {
-                    log.debug("mqtt连接失败,客户端ID:" + PropertiesUtil.MQTT_CLIENT_ID);
+                    log.debug("mqtt连接失败");
                 }
             }
         } catch (Exception e) {
diff --git a/src/main/java/com/ard/utils/mqtt/PropertiesUtil.java b/src/main/java/com/ard/utils/mqtt/PropertiesUtil.java
deleted file mode 100644
index d53dc88..0000000
--- a/src/main/java/com/ard/utils/mqtt/PropertiesUtil.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.ard.utils.mqtt;
-
-import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-import org.springframework.stereotype.Component;
-
-import java.util.Objects;
-import java.util.Properties;
-
-/**
- * @Description: 获取配置信息
- * @ClassName: PropertiesUtil
- * @Author: 刘苏义
- * @Date: 2023年06月06日9:40
- * @Version: 1.0
- **/
-@Component
-public class PropertiesUtil {
-
-    public static String MQTT_HOST;
-    public static String MQTT_CLIENT_ID;
-    public static String MQTT_USER_NAME;
-    public static String MQTT_PASSWORD;
-    public static String MQTT_TOPIC;
-    public static Integer MQTT_TIMEOUT;
-    public static Integer MQTT_KEEP_ALIVE;
-    public static Boolean MQTT_ENABLED;
-    static {
-        MQTT_HOST = getYmlNew("spring.mqtt.host");
-        MQTT_CLIENT_ID = getYmlNew("spring.mqtt.clientId");
-        MQTT_USER_NAME = getYmlNew("spring.mqtt.username");
-        MQTT_PASSWORD = getYmlNew("spring.mqtt.password");
-        MQTT_TOPIC = getYmlNew("spring.mqtt.topic");
-        MQTT_TIMEOUT = Integer.valueOf(Objects.requireNonNull(getYmlNew("spring.mqtt.timeout")));
-        MQTT_KEEP_ALIVE = Integer.valueOf(Objects.requireNonNull(getYmlNew("spring.mqtt.keepalive")));
-        MQTT_ENABLED = Boolean.valueOf(getYmlNew("spring.mqtt.enabled"));
-    }
-
-    public static String getYmlNew(String key) {
-        Resource resource = new ClassPathResource("application.yml");
-        Properties properties;
-        try {
-            YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
-            yamlFactory.setResources(resource);
-            properties = yamlFactory.getObject();
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-        assert properties != null;
-        return properties.get(key).toString();
-    }
-}
diff --git a/src/main/java/com/ard/utils/other/SpringTool.java b/src/main/java/com/ard/utils/other/SpringTool.java
deleted file mode 100644
index 1c0844d..0000000
--- a/src/main/java/com/ard/utils/other/SpringTool.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.ard.utils.other;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-import org.springframework.stereotype.Component;
-
-import java.util.Properties;
-
-/**
- * @Description:
- * @ClassName: SpringTool
- * @Author: 刘苏义
- * @Date: 2023年06月06日9:14
- * @Version: 1.0
- **/
-@Component
-public class SpringTool implements ApplicationContextAware {
-
-    private static ApplicationContext applicationContext = null;
-
-    @Override
-    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
-        if (SpringTool.applicationContext == null) {
-            SpringTool.applicationContext = applicationContext;
-        }
-    }
-
-    //该方法用于外界获取ApplicationContext对象
-    public static ApplicationContext getApplicationContext() {
-        return applicationContext;
-    }
-
-    //该方法用于外界通过bean的名字获取Bean对象
-    public static Object getBean(String name) {
-        return getApplicationContext().getBean(name);
-    }
-
-    /*yml配置信息获取*/
-    public static String getYmlInfo(String key) {
-        Resource resource = new ClassPathResource("application.yml");
-        Properties properties = null;
-        try {
-            YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
-            yamlFactory.setResources(resource);
-            properties = yamlFactory.getObject();
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-        return properties.get(key).toString();
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/com/ard/utils/other/StringUtils.java b/src/main/java/com/ard/utils/other/StringUtils.java
new file mode 100644
index 0000000..0980747
--- /dev/null
+++ b/src/main/java/com/ard/utils/other/StringUtils.java
@@ -0,0 +1,577 @@
+package com.ard.utils.other;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.springframework.util.AntPathMatcher;
+
+/**
+ * 字符串工具类
+ * 
+ * @author ruoyi
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+    /** 空字符串 */
+    private static final String NULLSTR = "";
+
+    /** 下划线 */
+    private static final char SEPARATOR = '_';
+
+    /**
+     * 获取参数不为空值
+     * 
+     * @param value defaultValue 要判断的value
+     * @return value 返回值
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 判断一个Collection是否为空, 包含List,Set,Queue
+     * 
+     * @param coll 要判断的Collection
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 判断一个Collection是否非空,包含List,Set,Queue
+     * 
+     * @param coll 要判断的Collection
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Collection<?> coll)
+    {
+        return !isEmpty(coll);
+    }
+
+    /**
+     * * 判断一个对象数组是否为空
+     * 
+     * @param objects 要判断的对象数组
+     ** @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Object[] objects)
+    {
+        return isNull(objects) || (objects.length == 0);
+    }
+
+    /**
+     * * 判断一个对象数组是否非空
+     * 
+     * @param objects 要判断的对象数组
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Object[] objects)
+    {
+        return !isEmpty(objects);
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     * 
+     * @param map 要判断的Map
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     * 
+     * @param map 要判断的Map
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Map<?, ?> map)
+    {
+        return !isEmpty(map);
+    }
+
+    /**
+     * * 判断一个字符串是否为空串
+     * 
+     * @param str String
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(String str)
+    {
+        return isNull(str) || NULLSTR.equals(str.trim());
+    }
+
+    /**
+     * * 判断一个字符串是否为非空串
+     * 
+     * @param str String
+     * @return true:非空串 false:空串
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return !isEmpty(str);
+    }
+
+    /**
+     * * 判断一个对象是否为空
+     * 
+     * @param object Object
+     * @return true:为空 false:非空
+     */
+    public static boolean isNull(Object object)
+    {
+        return object == null;
+    }
+
+    /**
+     * * 判断一个对象是否非空
+     * 
+     * @param object Object
+     * @return true:非空 false:空
+     */
+    public static boolean isNotNull(Object object)
+    {
+        return !isNull(object);
+    }
+
+    /**
+     * * 判断一个对象是否是数组类型(Java基本型别的数组)
+     * 
+     * @param object 对象
+     * @return true:是数组 false:不是数组
+     */
+    public static boolean isArray(Object object)
+    {
+        return isNotNull(object) && object.getClass().isArray();
+    }
+
+    /**
+     * 去空格
+     */
+    public static String trim(String str)
+    {
+        return (str == null ? "" : str.trim());
+    }
+
+    /**
+     * 截取字符串
+     * 
+     * @param str 字符串
+     * @param start 开始
+     * @return 结果
+     */
+    public static String substring(final String str, int start)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (start > str.length())
+        {
+            return NULLSTR;
+        }
+
+        return str.substring(start);
+    }
+
+    /**
+     * 截取字符串
+     * 
+     * @param str 字符串
+     * @param start 开始
+     * @param end 结束
+     * @return 结果
+     */
+    public static String substring(final String str, int start, int end)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (end < 0)
+        {
+            end = str.length() + end;
+        }
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (end > str.length())
+        {
+            end = str.length();
+        }
+
+        if (start > end)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (end < 0)
+        {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+
+
+
+    /**
+     * 字符串转set
+     * 
+     * @param str 字符串
+     * @param sep 分隔符
+     * @return set集合
+     */
+    public static final Set<String> str2Set(String str, String sep)
+    {
+        return new HashSet<String>(str2List(str, sep, true, false));
+    }
+
+    /**
+     * 字符串转list
+     * 
+     * @param str 字符串
+     * @param sep 分隔符
+     * @param filterBlank 过滤纯空白
+     * @param trim 去掉首尾空白
+     * @return list集合
+     */
+    public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
+    {
+        List<String> list = new ArrayList<String>();
+        if (StringUtils.isEmpty(str))
+        {
+            return list;
+        }
+
+        // 过滤空白字符串
+        if (filterBlank && StringUtils.isBlank(str))
+        {
+            return list;
+        }
+        String[] split = str.split(sep);
+        for (String string : split)
+        {
+            if (filterBlank && StringUtils.isBlank(string))
+            {
+                continue;
+            }
+            if (trim)
+            {
+                string = string.trim();
+            }
+            list.add(string);
+        }
+
+        return list;
+    }
+
+    /**
+     * 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
+     *
+     *
+     * @param array 给定的数组
+     * @return boolean 结果
+     */
+    public static boolean containsAny(Collection<String> collection, String... array)
+    {
+        if (isEmpty(collection) || isEmpty(array))
+        {
+            return false;
+        }
+        else
+        {
+            for (String str : array)
+            {
+                if (collection.contains(str))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
+     *
+     * @param cs 指定字符串
+     * @param searchCharSequences 需要检查的字符串数组
+     * @return 是否包含任意一个字符串
+     */
+    public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
+    {
+        if (isEmpty(cs) || isEmpty(searchCharSequences))
+        {
+            return false;
+        }
+        for (CharSequence testStr : searchCharSequences)
+        {
+            if (containsIgnoreCase(cs, testStr))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 驼峰转下划线命名
+     */
+    public static String toUnderScoreCase(String str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        // 前置字符是否大写
+        boolean preCharIsUpperCase = true;
+        // 当前字符是否大写
+        boolean curreCharIsUpperCase = true;
+        // 下一字符是否大写
+        boolean nexteCharIsUpperCase = true;
+        for (int i = 0; i < str.length(); i++)
+        {
+            char c = str.charAt(i);
+            if (i > 0)
+            {
+                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+            }
+            else
+            {
+                preCharIsUpperCase = false;
+            }
+
+            curreCharIsUpperCase = Character.isUpperCase(c);
+
+            if (i < (str.length() - 1))
+            {
+                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+            }
+
+            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 是否包含字符串
+     * 
+     * @param str 验证字符串
+     * @param strs 字符串组
+     * @return 包含返回true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs)
+    {
+        if (str != null && strs != null)
+        {
+            for (String s : strs)
+            {
+                if (str.equalsIgnoreCase(trim(s)))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
+     * 
+     * @param name 转换前的下划线大写方式命名的字符串
+     * @return 转换后的驼峰式命名的字符串
+     */
+    public static String convertToCamelCase(String name)
+    {
+        StringBuilder result = new StringBuilder();
+        // 快速检查
+        if (name == null || name.isEmpty())
+        {
+            // 没必要转换
+            return "";
+        }
+        else if (!name.contains("_"))
+        {
+            // 不含下划线,仅将首字母大写
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+        }
+        // 用下划线将原始字符串分割
+        String[] camels = name.split("_");
+        for (String camel : camels)
+        {
+            // 跳过原始字符串中开头、结尾的下换线或双重下划线
+            if (camel.isEmpty())
+            {
+                continue;
+            }
+            // 首字母大写
+            result.append(camel.substring(0, 1).toUpperCase());
+            result.append(camel.substring(1).toLowerCase());
+        }
+        return result.toString();
+    }
+
+    /**
+     * 驼峰式命名法 例如:user_name->userName
+     */
+    public static String toCamelCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        s = s.toLowerCase();
+        StringBuilder sb = new StringBuilder(s.length());
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            if (c == SEPARATOR)
+            {
+                upperCase = true;
+            }
+            else if (upperCase)
+            {
+                sb.append(Character.toUpperCase(c));
+                upperCase = false;
+            }
+            else
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
+     * 
+     * @param str 指定字符串
+     * @param strs 需要检查的字符串数组
+     * @return 是否匹配
+     */
+    public static boolean matches(String str, List<String> strs)
+    {
+        if (isEmpty(str) || isEmpty(strs))
+        {
+            return false;
+        }
+        for (String pattern : strs)
+        {
+            if (isMatch(pattern, str))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 判断url是否与规则配置: 
+     * ? 表示单个字符; 
+     * * 表示一层路径内的任意字符串,不可跨层级; 
+     * ** 表示任意层路径;
+     * 
+     * @param pattern 匹配规则
+     * @param url 需要匹配的url
+     * @return
+     */
+    public static boolean isMatch(String pattern, String url)
+    {
+        AntPathMatcher matcher = new AntPathMatcher();
+        return matcher.match(pattern, url);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T cast(Object obj)
+    {
+        return (T) obj;
+    }
+
+    /**
+     * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
+     * 
+     * @param num 数字对象
+     * @param size 字符串指定长度
+     * @return 返回数字的字符串格式,该字符串为指定长度。
+     */
+    public static final String padl(final Number num, final int size)
+    {
+        return padl(num.toString(), size, '0');
+    }
+
+    /**
+     * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
+     * 
+     * @param s 原始字符串
+     * @param size 字符串指定长度
+     * @param c 用于补齐的字符
+     * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
+     */
+    public static final String padl(final String s, final int size, final char c)
+    {
+        final StringBuilder sb = new StringBuilder(size);
+        if (s != null)
+        {
+            final int len = s.length();
+            if (s.length() <= size)
+            {
+                for (int i = size - len; i > 0; i--)
+                {
+                    sb.append(c);
+                }
+                sb.append(s);
+            }
+            else
+            {
+                return s.substring(len - size, len);
+            }
+        }
+        else
+        {
+            for (int i = size; i > 0; i--)
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ard/utils/spring/SpringUtils.java b/src/main/java/com/ard/utils/spring/SpringUtils.java
new file mode 100644
index 0000000..a71757e
--- /dev/null
+++ b/src/main/java/com/ard/utils/spring/SpringUtils.java
@@ -0,0 +1,158 @@
+package com.ard.utils.spring;
+
+import com.ard.utils.other.StringUtils;
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * spring工具类 方便在非spring管理环境中获取bean
+ * 
+ * @author ruoyi
+ */
+@Component
+public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware 
+{
+    /** Spring应用上下文环境 */
+    private static ConfigurableListableBeanFactory beanFactory;
+
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException 
+    {
+        SpringUtils.beanFactory = beanFactory;
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
+    {
+        SpringUtils.applicationContext = applicationContext;
+    }
+
+    /**
+     * 获取对象
+     *
+     * @param name
+     * @return Object 一个以所给名字注册的bean的实例
+     * @throws BeansException
+     *
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) throws BeansException
+    {
+        return (T) beanFactory.getBean(name);
+    }
+
+    /**
+     * 获取类型为requiredType的对象
+     *
+     * @param clz
+     * @return
+     * @throws BeansException
+     *
+     */
+    public static <T> T getBean(Class<T> clz) throws BeansException
+    {
+        T result = (T) beanFactory.getBean(clz);
+        return result;
+    }
+
+    /**
+     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean containsBean(String name)
+    {
+        return beanFactory.containsBean(name);
+    }
+
+    /**
+     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
+     *
+     * @param name
+     * @return boolean
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.isSingleton(name);
+    }
+
+    /**
+     * @param name
+     * @return Class 注册对象的类型
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getType(name);
+    }
+
+    /**
+     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
+     *
+     * @param name
+     * @return
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getAliases(name);
+    }
+
+    /**
+     * 获取aop代理对象
+     * 
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker)
+    {
+        return (T) AopContext.currentProxy();
+    }
+
+    /**
+     * 获取当前的环境配置,无配置返回null
+     *
+     * @return 当前的环境配置
+     */
+    public static String[] getActiveProfiles()
+    {
+        return applicationContext.getEnvironment().getActiveProfiles();
+    }
+
+    /**
+     * 获取当前的环境配置,当有多个环境配置时,只获取第一个
+     *
+     * @return 当前的环境配置
+     */
+    public static String getActiveProfile()
+    {
+        final String[] activeProfiles = getActiveProfiles();
+        return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
+    }
+
+    /**
+     * 获取配置文件中的值
+     *
+     * @param key 配置文件的key
+     * @return 当前的配置文件的值
+     *
+     */
+    public static String getRequiredProperty(String key)
+    {
+        return applicationContext.getEnvironment().getRequiredProperty(key);
+    }
+}
diff --git a/src/main/java/com/ard/utils/udp/NettyUdpHandler.java b/src/main/java/com/ard/utils/udp/NettyUdpHandler.java
index c3bb951..5e2160b 100644
--- a/src/main/java/com/ard/utils/udp/NettyUdpHandler.java
+++ b/src/main/java/com/ard/utils/udp/NettyUdpHandler.java
@@ -1,7 +1,7 @@
 package com.ard.utils.udp;
 
 import com.ard.alarm.tube.service.TubeAlarmService;
-import com.ard.utils.other.SpringTool;
+import com.ard.utils.spring.SpringUtils;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandlerContext;
@@ -20,7 +20,7 @@
             ByteBuf byteBuf = packet.content();
             String str = byteBuf.toString(Charset.forName("GBK"));
             log.info("udp收到数据: " + str);
-            TubeAlarmService tubeAlarmService = (TubeAlarmService) SpringTool.getApplicationContext().getBean("tubeAlarmService");
+            TubeAlarmService tubeAlarmService = SpringUtils.getBean(TubeAlarmService.class);
             tubeAlarmService.alarmHandler(str);
             String resStr = "ok";
             byte[] resBytes = resStr.getBytes(Charset.forName("GBK"));
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..bbc7292
--- /dev/null
+++ b/src/main/resources/application-dev.yml
@@ -0,0 +1,70 @@
+# 开发环境
+server:
+  port: 8088
+# spring配置
+spring:
+  servlet:
+    multipart:
+      enabled: true
+      max-file-size: 30MB
+      max-request-size: 30MB
+  datasource:
+      #  使用druid数据库连接池
+    druid:
+        #开启druid监控web
+      stat-view-servlet:
+        enabled: true
+      driver-class-name: org.postgresql.Driver
+      url: jdbc:postgresql://192.168.1.15:5432/ry-vue?stringtype=unspecified
+      username: postgres
+      password: postgres
+      #最大连接数
+      maxActive: 30
+      #最小连接数
+      minIdle: 5
+      #获取连接的最大等待时间
+      maxWait: 10000
+      #解决mysql8小时的问题
+      validation-query: SELECT 'X'
+      #空闲连接的检查时间间隔
+      timeBetweenEvictionRunsMillis: 60000
+      #空闲连接最小空闲时间
+      minEvictableIdleTimeMillis: 300000
+  # netty配置
+  netty:
+    udp:
+      port: 40000
+      enabled: true
+    tcp:
+      enabled: true
+  # mqtt配置
+  mqtt:
+    host: tcp://192.168.1.15:1883
+    clientId: cc3
+    username: admin
+    password: xzx12345
+    topic: tube
+    timeout: 100
+    keepalive: 60
+    enabled: true
+  # 盗电接口地址
+  stealelec:
+    url: http://iot.zhdk.net:8090/Warning/GetWarning?userName=cy4oil
+  # minio配置
+  minio:
+    endpoint: http://192.168.1.15:9001
+    accessKey: admin
+    secretKey: xzx12345
+# mybatis配置
+mybatis:
+  typeAliasesPackage: com.ard.alarm.**.domain
+  mapperLocations: classpath:/mapper/*.xml
+# 日志等级配置
+logging:
+  level:
+    hikSdk: debug
+    mqtt: info
+    netty: info
+    external: info
+    camera: info
+    tube: info
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
new file mode 100644
index 0000000..c74b5f0
--- /dev/null
+++ b/src/main/resources/application-prod.yml
@@ -0,0 +1,67 @@
+#生产环境
+spring:
+  servlet:
+    multipart:
+      enabled: true
+      max-file-size: 30MB
+      max-request-size: 30MB
+  datasource:
+      #  使用druid数据库连接池
+    druid:
+        #开启druid监控web
+      stat-view-servlet:
+        enabled: true
+      driver-class-name: org.postgresql.Driver
+      url: jdbc:postgresql://112.98.126.2:35432/ry-vue?stringtype=unspecified
+      username: postgres
+      password: Yykj.2017
+      #最大连接数
+      maxActive: 30
+      #最小连接数
+      minIdle: 5
+      #获取连接的最大等待时间
+      maxWait: 10000
+      #解决mysql8小时的问题
+      validation-query: SELECT 'X'
+      #空闲连接的检查时间间隔
+      timeBetweenEvictionRunsMillis: 60000
+      #空闲连接最小空闲时间
+      minEvictableIdleTimeMillis: 300000
+  # netty配置
+  netty:
+    udp:
+      port: 40000
+      enabled: true
+    tcp:
+      enabled: true
+  # minio配置
+  minio:
+    endpoint: http://127.0.0.1:9001
+    accessKey: admin
+    secretKey: xzx12345
+  # mqtt配置
+  mqtt:
+    host: tcp://192.168.1.15:1883
+    clientId: cc3
+    username: admin
+    password: xzx12345
+    topic: tube
+    timeout: 100
+    keepalive: 60
+    enabled: true
+  stealelec:
+    url: http://iot.zhdk.net:8090/Warning/GetWarning?userName=cy4oil
+mybatis:
+  typeAliasesPackage: com.ard.alarm.**.domain
+  mapperLocations: classpath:/mapper/*.xml
+
+server:
+  port: 8088
+logging:
+  level:
+    hikSdk: debug
+    mqtt: info
+    netty: info
+    external: info
+    camera: info
+    tube: info
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index a2f5e97..fadf7d2 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,61 +1,4 @@
 spring:
-  servlet:
-    multipart:
-      enabled: true
-      max-file-size: 30MB
-      max-request-size: 30MB
-  datasource:
-      #  使用druid数据库连接池
-    druid:
-        #开启druid监控web
-      stat-view-servlet:
-        enabled: true
-      driver-class-name: org.postgresql.Driver
-          #    url: jdbc:postgresql://111.40.46.199:15432/ry-vue?stringtype=unspecified
-          #    username: postgres
-          #    password: Yykj.2021
-      url: jdbc:postgresql://192.168.1.15:5432/ry-vue?stringtype=unspecified
-      username: postgres
-      password: postgres
-      #最大连接数
-      maxActive: 30
-      #最小连接数
-      minIdle: 5
-      #获取连接的最大等待时间
-      maxWait: 10000
-      #解决mysql8小时的问题
-      validation-query: SELECT 'X'
-      #空闲连接的检查时间间隔
-      timeBetweenEvictionRunsMillis: 60000
-      #空闲连接最小空闲时间
-      minEvictableIdleTimeMillis: 300000
-  netty:
-    udp:
-      port: 40000
-      enabled: true
-    tcp:
-      enabled: true
-  mqtt:
-    host: tcp://192.168.1.15:1883
-    clientId: cc3
-    username: admin
-    password: xzx12345
-    topic: tube
-    timeout: 100
-    keepalive: 60
-    enabled: true
-  stealelec:
-    url: http://iot.zhdk.net:8090/Warning/GetWarning?userName=cy4oil
-mybatis:
-  typeAliasesPackage: com.ard.alarm.**.domain
-  mapperLocations: classpath:/mapper/*.xml
-# minio配置
-minio:
-  endpoint: http://192.168.1.15:9001
-  accessKey: admin
-  secretKey: xzx12345
-server:
-  port: 8088
-logging:
-  level:
-    com.ard.utils.hiksdk.service.impl.FMSGCallBack: debug
+  profiles:
+    active: prod
+

--
Gitblit v1.9.3