xucaiqin 1 lună în urmă
părinte
comite
a90548b9e8

+ 11 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/config/AuthInterceptorConfig.java

@@ -1,9 +1,12 @@
 package com.sckw.core.config;
 
 import com.sckw.core.interceptor.AuthenticationInterceptor;
+import com.sckw.core.web.constant.CommonConstants;
+import jakarta.annotation.Resource;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 /**
@@ -12,9 +15,17 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 @ConditionalOnClass(WebMvcConfigurer.class)
 @Configuration
 public class AuthInterceptorConfig implements WebMvcConfigurer {
+    @Resource
+    private ProjectConfig projectConfig;
     @Override
     public void addInterceptors(InterceptorRegistry registry) {
         // 注册自定义拦截器实例,并指定拦截的路径模式
         registry.addInterceptor(new AuthenticationInterceptor()).addPathPatterns("/**"); // 可以排除某些路径不被拦截
     }
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler(CommonConstants.RESOURCE_PREFIX + "/**")
+                .addResourceLocations("file:" + projectConfig.getProfile() + "/");
+    }
 }

+ 16 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/config/ProjectConfig.java

@@ -0,0 +1,16 @@
+package com.sckw.core.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "common")
+public class ProjectConfig {
+
+    private String profile;
+    private String domain;
+
+}

+ 65 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/exception/InvalidExtensionException.java

@@ -0,0 +1,65 @@
+package com.sckw.core.exception;
+
+import org.apache.tomcat.util.http.fileupload.FileUploadException;
+
+import java.util.Arrays;
+
+
+public class InvalidExtensionException extends FileUploadException {
+    private static final long serialVersionUID = 1L;
+
+    private String[] allowedExtension;
+    private String extension;
+    private String filename;
+
+    public InvalidExtensionException(String[] allowedExtension, String extension, String filename) {
+        super("文件[" + filename + "]后缀[" + extension + "]不正确,请上传" + Arrays.toString(allowedExtension) + "格式");
+        this.allowedExtension = allowedExtension;
+        this.extension = extension;
+        this.filename = filename;
+    }
+
+    public String[] getAllowedExtension() {
+        return allowedExtension;
+    }
+
+    public String getExtension() {
+        return extension;
+    }
+
+    public String getFilename() {
+        return filename;
+    }
+
+    public static class InvalidImageExtensionException extends InvalidExtensionException {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidFlashExtensionException extends InvalidExtensionException {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidMediaExtensionException extends InvalidExtensionException {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidVideoExtensionException extends InvalidExtensionException {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename) {
+            super(allowedExtension, extension, filename);
+        }
+    }
+}

+ 36 - 6
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/DateUtils.java

@@ -6,6 +6,7 @@ import com.sckw.core.exception.BusinessException;
 import com.sckw.core.exception.BusinessPlatfromException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateFormatUtils;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -62,6 +63,32 @@ public class DateUtils extends DateUtil {
 
     public static int THIRTEEN = 13;
 
+    public static String datePath() {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyy/MM/dd");
+    }
+    public static String dateTimeNow() {
+        return dateTimeNow("yyyyMMddHHmmss");
+    }
+    /**
+     * 获取当前日期和时间的指定格式的字符串表示
+     *
+     * @param format 日期时间格式,例如"YYYY-MM-DD HH:MM:SS"
+     * @return 当前日期和时间的字符串表示
+     */
+    public static String dateTimeNow(final String format) {
+        return parseDateToStr(format, new Date());
+    }
+    /**
+     * 将指定日期按照指定格式进行格式化
+     *
+     * @param format 要使用的日期时间格式,例如"YYYY-MM-DD HH:MM:SS"
+     * @param date   要格式化的日期对象
+     * @return 格式化后的日期时间字符串
+     */
+    public static String parseDateToStr(final String format, final Date date) {
+        return new SimpleDateFormat(format).format(date);
+    }
     /**
      * 获取时间
      *
@@ -523,7 +550,6 @@ public class DateUtils extends DateUtil {
     }
 
 
-
     /**
      * ltf 获取
      * 获取指定日期所在周的周一
@@ -789,7 +815,6 @@ public class DateUtils extends DateUtil {
     }
 
 
-
     /**
      * @desc: localDate转换为date 结束时间
      * @author: yzc
@@ -807,6 +832,7 @@ public class DateUtils extends DateUtil {
 
     /**
      * 获取前n天的开始时间
+     *
      * @return
      */
     public static LocalDateTime getStartDay(int n) {
@@ -850,6 +876,7 @@ public class DateUtils extends DateUtil {
 
     /**
      * 计算两个时间之前的天数
+     *
      * @param startTime
      * @param endTime
      * @return
@@ -870,8 +897,9 @@ public class DateUtils extends DateUtil {
 
     /**
      * 计算两个时间的秒差值
+     *
      * @param startTime 开始时间
-     * @param endTime 结束时间
+     * @param endTime   结束时间
      * @return
      */
     public static Long calculateTimeDiffMinutes(Date startTime, Date endTime) {
@@ -887,7 +915,7 @@ public class DateUtils extends DateUtil {
             throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR,
                     "时间顺序异常,结束时间早于开始时间,startTime=[" + startTime + "], endTime=[" + endTime + "], 差值:[" + diffMillis + "]毫秒");
         }
-        return diffMillis/1000;
+        return diffMillis / 1000;
     }
 
 
@@ -907,6 +935,7 @@ public class DateUtils extends DateUtil {
         }
         return startDate;
     }
+
     public static Date getEndDate(String date) {
         Date endDate;
         if (StringUtils.isBlank(date)) {
@@ -926,8 +955,9 @@ public class DateUtils extends DateUtil {
 
     /**
      * 计算两个时间之间的小时数((保留两位小数,四舍五入))
+     *
      * @param startTime 开始时间
-     * @param endTime 结束时间
+     * @param endTime   结束时间
      * @return 小时数(例如:1.5 表示 1小时30分钟)
      */
     public static double hoursBetween(Date startTime, Date endTime) {
@@ -953,7 +983,7 @@ public class DateUtils extends DateUtil {
 
 
     public static void main(String[] args) {
-        getPreviousMonthsExclusive(5).forEach(x->{
+        getPreviousMonthsExclusive(5).forEach(x -> {
             System.out.println(x.toString());
         });
 

+ 155 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/FileUploadUtils.java

@@ -0,0 +1,155 @@
+package com.sckw.core.utils;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.file.FileNameUtil;
+import cn.hutool.core.util.StrUtil;
+import com.sckw.core.exception.BusinessException;
+import com.sckw.core.exception.InvalidExtensionException;
+import com.sckw.core.web.constant.CommonConstants;
+import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.Objects;
+
+/**
+ * 文件上传工具类
+ *
+ */
+public class FileUploadUtils {
+    /**
+     * 默认大小 50M
+     */
+    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
+
+    /**
+     * 默认的文件名最大长度 100
+     */
+    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
+
+    /**
+     * 根据文件路径上传
+     *
+     * @param baseDir 相对应用的基目录
+     * @param file    上传的文件
+     * @return 文件名称
+     * @throws IOException
+     */
+    public static String upload(String baseDir, MultipartFile file) throws IOException {
+        try {
+            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+        } catch (Exception e) {
+            throw new IOException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 判断MIME类型是否是允许的MIME类型
+     *
+     * @param extension
+     * @param allowedExtension
+     * @return
+     */
+    public static boolean isAllowedExtension(String extension, String[] allowedExtension) {
+        for (String str : allowedExtension) {
+            if (str.equalsIgnoreCase(extension)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 文件大小校验
+     *
+     * @param file 上传的文件
+     * @return
+     * @throws FileSizeLimitExceededException 如果超出最大大小
+     */
+    public static void assertAllowed(MultipartFile file, String[] allowedExtension) throws FileSizeLimitExceededException, InvalidExtensionException {
+        long size = file.getSize();
+        if (size > DEFAULT_MAX_SIZE) {
+            throw new BusinessException("文件上超限制" + DEFAULT_MAX_SIZE / 1024 / 1024);
+        }
+
+        String fileName = file.getOriginalFilename();
+        String extension = getExtension(file);
+        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
+            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
+                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, fileName);
+            } else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) {
+                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, fileName);
+            } else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) {
+                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, fileName);
+            } else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) {
+                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, fileName);
+            } else {
+                throw new InvalidExtensionException(allowedExtension, extension, fileName);
+            }
+        }
+    }
+
+    /**
+     * 文件上传
+     *
+     * @param baseDir          相对应用的基目录
+     * @param file             上传的文件
+     * @param allowedExtension 上传文件类型
+     * @return 返回上传成功的文件名
+     * @throws FileSizeLimitExceededException       如果超出最大大小
+     * @throws IOException                          比如读写文件出错时
+     */
+    public static String upload(String baseDir, MultipartFile file, String[] allowedExtension) throws FileSizeLimitExceededException, IOException, InvalidExtensionException {
+        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
+        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
+            throw new BusinessException("文件名超长"+FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+        }
+        assertAllowed(file, allowedExtension);
+
+
+        String fileName = extractFilename(file);
+
+        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
+        file.transferTo(Paths.get(absPath));
+        return getPathFileName(fileName);
+    }
+
+    /**
+     * 编码文件名
+     */
+    public static String extractFilename(MultipartFile file) {
+        return StrUtil.format("{}/{}_{}.{}", DateUtils.datePath(), FileNameUtil.getPrefix(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
+    }
+
+    public static File getAbsoluteFile(String uploadDir, String fileName) throws IOException {
+        File desc = new File(uploadDir + File.separator + fileName);
+
+        if (!desc.exists()) {
+            if (!desc.getParentFile().exists()) {
+                desc.getParentFile().mkdirs();
+            }
+        }
+        return desc;
+    }
+
+    public static String getPathFileName( String fileName) throws IOException {
+        return CommonConstants.RESOURCE_PREFIX + "/" +  fileName;
+    }
+
+
+    /**
+     * 获取文件名的后缀
+     *
+     * @param file 表单文件
+     * @return 后缀名
+     */
+    public static String getExtension(MultipartFile file) {
+        String extension =  FileUtil.getSuffix(file.getOriginalFilename());
+        if (StringUtils.isEmpty(extension)) {
+            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
+        }
+        return extension;
+    }
+}

+ 48 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/MimeTypeUtils.java

@@ -0,0 +1,48 @@
+package com.sckw.core.utils;
+
+/**
+ * 媒体类型工具类
+ *
+ */
+public class MimeTypeUtils {
+    public static final String IMAGE_PNG = "image/png";
+
+    public static final String IMAGE_JPG = "image/jpg";
+
+    public static final String IMAGE_JPEG = "image/jpeg";
+
+    public static final String IMAGE_BMP = "image/bmp";
+
+    public static final String IMAGE_GIF = "image/gif";
+
+    public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
+
+    public static final String[] FLASH_EXTENSION = {"swf", "flv"};
+
+    public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
+        "asf", "rm", "rmvb"};
+
+    public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
+
+    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
+        // 图片
+        "bmp", "gif", "jpg", "jpeg", "png",
+        // word excel powerpoint
+        "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
+        // 压缩文件
+        "rar", "zip", "gz", "bz2",
+        // 视频格式
+        "mp4", "avi", "rmvb",
+        // pdf
+        "pdf"};
+    public static String getExtension(String prefix) {
+        return switch (prefix) {
+            case IMAGE_PNG -> "png";
+            case IMAGE_JPG -> "jpg";
+            case IMAGE_JPEG -> "jpeg";
+            case IMAGE_BMP -> "bmp";
+            case IMAGE_GIF -> "gif";
+            default -> "";
+        };
+    }
+}

+ 115 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/Seq.java

@@ -0,0 +1,115 @@
+package com.sckw.core.utils;
+
+
+import com.aliyun.oss.ServiceException;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+
+public class Seq {
+    // 通用序列类型
+    public static final String commSeqType = "COMMON";
+
+    // 上传序列类型
+    public static final String uploadSeqType = "UPLOAD";
+
+    // 通用接口序列数
+    private static AtomicInteger commSeq = new AtomicInteger(1);
+
+    // 上传接口序列数
+    private static AtomicInteger uploadSeq = new AtomicInteger(1);
+    private static final AtomicInteger orderSeq = new AtomicInteger(1);
+    private static final AtomicInteger refundSeq = new AtomicInteger(1);
+    private static final AtomicInteger splitSeq = new AtomicInteger(1);
+
+    // 机器标识
+    private static final String machineCode = "A";
+
+    /**
+     * 获取通用序列号
+     *
+     * @return 序列值
+     */
+    public static String getId() {
+        return getId(commSeqType);
+    }
+
+    /**
+     * 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串
+     *
+     * @return 序列值
+     */
+    public static String getId(String type) {
+        AtomicInteger atomicInt = commSeq;
+        if (uploadSeqType.equals(type)) {
+            atomicInt = uploadSeq;
+        }
+        return getId(atomicInt, 3);
+    }
+
+    /**
+     * 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串
+     *
+     * @param atomicInt 序列数
+     * @param length    数值长度
+     * @return 序列值
+     */
+    public static String getId(AtomicInteger atomicInt, int length) {
+        String result = DateUtils.dateTimeNow();
+        result += machineCode;
+        result += getSeq(atomicInt, length);
+        return result;
+    }
+
+    public enum OrderType {
+        DRAW,
+        ORDER,
+        REFUND,
+        SPLIT
+    }
+
+    public static String getOrderId(OrderType type) {
+        if (OrderType.ORDER.equals(type)) {
+            return getId(orderSeq, "O", 3);
+        } else if (OrderType.REFUND.equals(type)) {
+            return getId(refundSeq, "R", 3);
+        } else if (OrderType.SPLIT.equals(type)) {
+            return getId(splitSeq, "S", 3);
+        } else if (OrderType.DRAW.equals(type)) {
+            return getId(splitSeq, "D", 3);
+        }
+        throw new ServiceException("类型异常");
+    }
+
+    /**
+     *
+     * @param atomicInt
+     * @param code      自定义机器码
+     * @param length
+     * @return
+     */
+    public static String getId(AtomicInteger atomicInt, String code, int length) {
+        String result = DateUtils.dateTimeNow();
+        result += code;
+        result += getSeq(atomicInt, length);
+        return result;
+    }
+
+    /**
+     * 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数
+     *
+     * @return 序列值
+     */
+    private synchronized static String getSeq(AtomicInteger atomicInt, int length) {
+        // 先取值再+1
+        int value = atomicInt.getAndIncrement();
+
+        // 如果更新后值>=10 的 (length)幂次方则重置为1
+        int maxSeq = (int) Math.pow(10, length);
+        if (atomicInt.get() >= maxSeq) {
+            atomicInt.set(1);
+        }
+        // 转字符串,用0左补齐
+        return StringUtils.padl(value, length);
+    }
+}

+ 34 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/StringUtils.java

@@ -1,5 +1,6 @@
 package com.sckw.core.utils;
 
+import cn.hutool.core.convert.Convert;
 import com.sckw.core.exception.BusinessException;
 import com.sckw.core.model.constant.Global;
 import com.sckw.core.model.constant.NumberConstant;
@@ -39,7 +40,40 @@ public class StringUtils {
      * ${xxx}
      **/
     public static final Pattern pattern = Pattern.compile("(\\$\\{)([\\w]+)(\\})");
+    /**
+     * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
+     *
+     * @param num  数字对象
+     * @param size 字符串指定长度
+     * @return 返回数字的字符串格式,该字符串为指定长度。
+     */
+    public static 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 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) {
+                sb.append(cn.hutool.core.convert.Convert.toStr(c).repeat(size - len));
+                sb.append(s);
+            } else {
+                return s.substring(len - size, len);
+            }
+        } else {
+            sb.append(Convert.toStr(c).repeat(Math.max(0, size)));
+        }
+        return sb.toString();
+    }
     /**
      * 判断字符串是否为空
      *

+ 1 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/web/constant/CommonConstants.java

@@ -12,4 +12,5 @@ public class CommonConstants {
     public static final String DATE_TIME = "1000-01-01 00:00:00";
     public static final String TRUCK_LOCATION = "cache:truck:location:";
     public static final String UNDERSCORE = "_";
+    public static final String RESOURCE_PREFIX = "/profile";
 }

+ 1 - 0
sckw-common/sckw-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -1,3 +1,4 @@
+com.sckw.core.config.ProjectConfig
 com.sckw.core.aspect.DaoAspect
 com.sckw.core.aspect.NoRepeatSubmitAspect
 com.sckw.core.exception.GlobalSystemExceptionHandler