diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..7944320
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,161 @@
+
+
+ 4.0.0
+
+
+
+
+ 1.0-SNAPSHOT
+ ../pom.xml
+
+
+
+ common-module
+ 0.0.1-SNAPSHOT
+ common-module
+ Demo project for Spring Boot
+
+
+ 8
+ 4.4.0
+ 1.2.78
+ 5.7.16
+ 33.2.1-jre
+ 4.1.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ com.github.xiaoymin
+ knife4j-openapi3-spring-boot-starter
+ ${knife4j.version}
+
+
+ commons-lang3
+ org.apache.commons
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.apache.commons
+ commons-lang3
+ 3.12.0
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ io.lettuce
+ lettuce-core
+
+
+
+
+ redis.clients
+ jedis
+
+
+
+ cn.hutool
+ hutool-all
+ ${hutool.version}
+
+
+
+ com.auth0
+ java-jwt
+ ${jwt.version}
+
+
+ org.apache.httpcomponents
+ httpclient
+
+
+
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+ commons-io
+ commons-io
+ 2.16.1
+ compile
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.5.1
+
+
+ com.aostarit
+ smcrypto
+ 1.0
+ system
+ ${project.basedir}/src/main/resources/libs/aostarit.smcrypto-1.0.0.jar
+
+
+
+ com.alibaba
+ easyexcel
+ 2.2.8
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ 2.17.1
+
+
+
+ com.github.ulisesbocchio
+ jasypt-spring-boot-starter
+
+
+
+ commons-codec
+ commons-codec
+ 1.16.1
+
+
+ org.bouncycastle
+ bcprov-jdk15to18
+ 1.68
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+
+
diff --git a/utils/AESPKCS7PaddingUtils.java b/utils/AESPKCS7PaddingUtils.java
new file mode 100644
index 0000000..0aee4a0
--- /dev/null
+++ b/utils/AESPKCS7PaddingUtils.java
@@ -0,0 +1,127 @@
+package com.sgcc.utils;
+
+import ch.qos.logback.core.boolex.EvaluationException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Base64;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.Security;
+
+/**
+ * AES加密/解密工具类
+ *
+ * @author zhaoyuanyuan
+ * @version 1.0.0
+ * @date 2024/11/22 14:03
+ */
+@Slf4j
+public class AESPKCS7PaddingUtils {
+
+ /**
+ * 密钥算法
+ */
+ private static final String KEY_ALGORITHM = "AES";
+
+ /**
+ * 加密/解密算法 / 工作模式 / 填充方式
+ * Java 6支持PKCS5Padding填充方式
+ * Bouncy Castle支持PKCS7Padding填充方式
+ */
+ private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
+
+ /**
+ * 偏移量,只有CBC模式才需要
+ */
+ private final static String ivParameter = "0000000000000000";
+
+ /**
+ * AES要求密钥长度为128位或192位或256位,java默认限制AES密钥长度最多128位
+ */
+ public static String secretKey = "";
+
+ /**
+ * 编码格式
+ */
+ public static final String ENCODING = "utf-8";
+
+ static {
+ //如果是PKCS7Padding填充方式,则必须加上下面这行
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
+ /**
+ * AES加密
+ *
+ * @param source 源字符串
+ * @return {@code String }
+ * @author zhaoyuanyuan
+ * @date 2024/11/22 14:05
+ */
+ public static String encrypt(String source) {
+ try {
+ byte[] sourceBytes = source.getBytes(ENCODING);
+ byte[] keyBytes = secretKey.getBytes(ENCODING);
+ Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
+ IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(ENCODING));
+ cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, KEY_ALGORITHM),iv);
+ byte[] decrypted = cipher.doFinal(sourceBytes);
+ return Base64.encodeBase64String(decrypted);
+ } catch (Exception e) {
+ log.error(e.toString());
+ }
+ return null;
+ }
+
+ /**
+ * AES解密
+ *
+ * @param encryptStr 加密后的密文
+ * @return {@code String }
+ * @author zhaoyuanyuan
+ * @date 2024/11/22 14:05
+ */
+ public static String decrypt(String encryptStr) {
+ try {
+ byte[] sourceBytes = Base64.decodeBase64(encryptStr);
+ byte[] keyBytes = secretKey.getBytes(ENCODING);
+ Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
+ IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(ENCODING));
+ cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, KEY_ALGORITHM),iv);
+ byte[] decoded = cipher.doFinal(sourceBytes);
+ return new String(decoded, ENCODING);
+ } catch (Exception e) {
+ log.error(e.toString());
+ }
+ return null;
+ }
+
+ /**
+ * 校验密码
+ *
+ * @param inputPassword 输入密码
+ * @param password 数据库存储密码
+ * @return boolean
+ * @author zhaoyuanyuan
+ * @date 2024/11/23 09:40
+ */
+ public static boolean validatePassword(String inputPassword, String password) {
+ if (decrypt(inputPassword).equals(decrypt(password))) {
+ return true;
+ }
+ return false;
+ }
+
+ public static void main(String[] args) throws Exception {
+ //加密
+ String enString = AESPKCS7PaddingUtils.encrypt("12345678");
+ System.out.println("加密后的字串是:" + enString);
+ // 解密
+ String DeString = AESPKCS7PaddingUtils.decrypt("wUpDBpZlm//omEBf20WCag==");
+ System.out.println("解密后的字串是:" + DeString);
+ }
+
+}
+
diff --git a/utils/BeanUtils.java b/utils/BeanUtils.java
new file mode 100644
index 0000000..e5504b5
--- /dev/null
+++ b/utils/BeanUtils.java
@@ -0,0 +1,514 @@
+package com.sgcc.utils;
+
+import com.google.common.collect.Maps;
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.util.Assert;
+import org.springframework.util.ReflectionUtils;
+
+/**
+ * 实体转化工具类
+ *
+ * @author zhaoyuanyuan
+ * @version 1.0.0
+ * @date 2024/06/24 17:35
+ */
+@Slf4j
+public class BeanUtils {
+
+ private static final String CLASS = "class";
+
+ private BeanUtils() {
+ throw new IllegalStateException("Utility class");
+ }
+
+ /**
+ * 判断对象是否为数字
+ *
+ * @param o
+ * @return
+ */
+ public static boolean isNumber(Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (o instanceof Number) {
+ return true;
+ }
+ if (o instanceof String) {
+ try {
+ Double.parseDouble((String) o);
+ return true;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 将bean转化为map
+ *
+ * @param clazz bean
+ * @param 泛型
+ * @return Map 返回对象
+ */
+ public static Map toMap(final T clazz) {
+ Map paramsMap = Maps.newHashMap();
+ try {
+ BeanInfo bi = Introspector.getBeanInfo(clazz.getClass());
+ PropertyDescriptor[] pd = bi.getPropertyDescriptors();
+ for (int i = 0; i < pd.length; i++) {
+ String name = pd[i].getName();
+ Method method = pd[i].getReadMethod();
+ Object value = method.invoke(clazz);
+ if (!CLASS.equals(name)) {
+ paramsMap.put(name, value);
+ }
+ }
+ } catch (IntrospectionException ie) {
+ log.error("IntrospectionException.className=" + clazz.getClass() + "BeanInfo error : ", ie);
+ } catch (Exception e) {
+ log.error("Exception.className=" + clazz.getClass() + "Method error :", e);
+ }
+ return paramsMap;
+ }
+
+ /**
+ * 获取到对象中属性为指定值的属性名
+ *
+ * @param source 要拷贝的对象
+ * @param values 指定的值数组
+ * @return
+ */
+ public static String[] getPropertyNamesWithValues(Object source, String... values) {
+ List valueList = (values != null ? Arrays.asList(values) : null);
+ final BeanWrapper src = new BeanWrapperImpl(source);
+ PropertyDescriptor[] pds = src.getPropertyDescriptors();
+ Set propertyNames = new HashSet<>();
+ for (PropertyDescriptor pd : pds) {
+ Object srcValue = src.getPropertyValue(pd.getName());
+ if (valueList == null && srcValue == null) {
+ propertyNames.add(pd.getName());
+ } else if (valueList != null && valueList.contains(srcValue)) {
+ propertyNames.add(pd.getName());
+ } else {
+ // DO NOTHING
+ }
+ }
+ String[] result = new String[propertyNames.size()];
+ return propertyNames.toArray(result);
+ }
+
+ /**
+ * 列表实体类属性拷贝,忽略null值
+ *
+ * @param fromList 待转换实体列数组
+ * @param tClass 目标类
+ * @param
+ * @param
+ * @return
+ */
+ public static List copyPropertiesIgnoreNull(List fromList, Class tClass) {
+ return copyPropertiesIgnoreValues(fromList, tClass, (String[]) null);
+ }
+
+ /**
+ * 实体类属性拷贝,忽略null值、空字符串""和"null"
+ *
+ * @param fromList 待转换实体列数组
+ * @param tClass 目标类
+ * @param
+ * @param
+ * @return
+ */
+ public static List copyPropertiesIgnoreEmpty(List fromList, Class tClass) {
+ return copyPropertiesIgnoreValues(fromList, tClass, null, "", "null");
+ }
+
+ /**
+ * 实体类列表属性拷贝,忽略指定值
+ * 将entityList转换成modelList
+ *
+ * @param fromList 待转换实体列数组
+ * @param tClass 目标类
+ * @param values 指定的值数组
+ * @param
+ * @param
+ * @return
+ */
+ public static List copyPropertiesIgnoreValues(List fromList, Class tClass, String... values) {
+ Assert.notNull(tClass, "tClass must not be null.");
+ List tList = new ArrayList<>();
+ if (fromList != null && !fromList.isEmpty()) {
+ for (F f : fromList) {
+ T t = copyPropertiesIgnoreValues(f, tClass, values);
+ tList.add(t);
+ }
+ }
+ return tList;
+ }
+
+ /**
+ * 实体类列表属性拷贝
+ * 将entityList转换成modelList
+ *
+ * @param fromList 待转换实体列数组
+ * @param tClass 目标类
+ * @param
+ * @param
+ * @return
+ */
+ public static List copyProperties(List fromList, Class tClass) {
+ Assert.notNull(tClass, "tClass must not be null.");
+ List tList = new ArrayList<>();
+ if (fromList != null && !fromList.isEmpty()) {
+ for (F f : fromList) {
+ T t = copyProperties(f, tClass);
+ tList.add(t);
+ }
+ }
+ return tList;
+ }
+
+ /**
+ * 实体类属性拷贝,忽略null值
+ *
+ * @param entity 实体类
+ * @param modelClass 目标类
+ * @param
+ * @param
+ * @return
+ */
+ public static T copyPropertiesIgnoreNull(F entity, Class modelClass) {
+ return copyPropertiesIgnoreValues(entity, modelClass, (String[]) null);
+ }
+
+ /**
+ * 实体类属性拷贝,忽略null值、空字符串""和"null"
+ *
+ * @param entity 实体类
+ * @param modelClass 目标类
+ * @param
+ * @param
+ * @return
+ */
+ public static T copyPropertiesIgnoreEmpty(F entity, Class modelClass) {
+ return copyPropertiesIgnoreValues(entity, modelClass, null, "", "null");
+ }
+
+ /**
+ * 实体类属性拷贝,忽略指定值
+ *
+ * @param entity 实体类
+ * @param modelClass 目标类
+ * @param values 指定的值数组
+ * @param
+ * @param
+ * @return
+ */
+ public static T copyPropertiesIgnoreValues(F entity, Class modelClass, String... values) {
+ return copyProperties(entity, modelClass, getPropertyNamesWithValues(entity, values));
+ }
+
+ /**
+ * 实体类属性拷贝
+ *
+ * @param entity 实体类
+ * @param modelClass 目标类
+ * @param
+ * @param
+ * @return
+ */
+ public static T copyProperties(F entity, Class modelClass) {
+ return copyProperties(entity, modelClass, (String[]) null);
+ }
+
+ /**
+ * 实体类属性拷贝
+ *
+ * @param entity 实体类
+ * @param modelClass 目标类
+ * @param ignoreProperties 忽略属性列表
+ * @param
+ * @param
+ * @return
+ */
+ public static T copyProperties(F entity, Class modelClass, String... ignoreProperties) {
+ Assert.notNull(modelClass, "modelClass must not be null.");
+ Object model = null;
+
+ try {
+ model = modelClass.newInstance();
+ } catch (InstantiationException e) {
+ log.error("copyProperties: InstantiationException", e);
+ } catch (IllegalAccessException e) {
+ log.error("copyProperties: IllegalAccessException", e);
+ }
+
+ if (entity != null) {
+ org.springframework.beans.BeanUtils.copyProperties(entity, model, ignoreProperties);
+ } else {
+ // DO NOTHING
+ }
+ return (T) model;
+ }
+
+ /**
+ * 将下划线大写方式命名的字符串转换为驼峰式。
+ * 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。
+ * 例如:hello_world->helloWorld
+ *
+ * @param name 转换前的下划线大写方式命名的字符串
+ * @return 转换后的驼峰式命名的字符串
+ */
+ public static String camelName(String name) {
+ StringBuilder result = new StringBuilder();
+ // 快速检查
+ if (name == null || name.isEmpty()) {
+ // 没必要转换
+ return "";
+ } else if (!name.contains("_")) {
+ // 不含下划线,仅将首字母小写
+ return name.substring(0, 1).toLowerCase() + name.substring(1).toLowerCase();
+ }
+ // 用下划线将原始字符串分割
+ String[] camels = name.split("_");
+ for (String camel : camels) {
+ // 跳过原始字符串中开头、结尾的下换线或双重下划线
+ if (camel.isEmpty()) {
+ continue;
+ }
+ // 处理真正的驼峰片段
+ if (result.length() == 0) {
+ // 第一个驼峰片段,全部字母都小写
+ result.append(camel.toLowerCase());
+ } else {
+ // 其他的驼峰片段,首字母大写
+ result.append(camel.substring(0, 1).toUpperCase());
+ result.append(camel.substring(1).toLowerCase());
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * 将下划线大写方式命名的字符串转换为驼峰式。
+ * 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。
+ * 例如:hello_world,test_id->helloWorld,testId
+ *
+ * @param names 转换前的下划线大写方式命名的字符串
+ * @return 转换后的驼峰式命名的字符串
+ */
+ public static String camelNames(String names) {
+ if (names == null || names.equals("")) {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder();
+ String[] fs = names.split(",");
+ for (String field : fs) {
+ field = camelName(field);
+ sb.append(field + ",");
+ }
+ String result = sb.toString();
+ return result.substring(0, result.length() - 1);
+ }
+
+ /**
+ * 将下划线大写方式命名的字符串转换为驼峰式。
+ * (首字母写) 如果转换前的下划线大写方式命名的字符串为空,
+ * 则返回空字符串。
+ * 例如:hello_world->HelloWorld
+ *
+ * @param name 转换前的下划线大写方式命名的字符串
+ * @return 转换后的驼峰式命名的字符串
+ */
+ public static String camelNameCapFirst(String name) {
+ // 转换为首字母小写的驼峰片段
+ String camel = camelName(name);
+ if (camel == null || camel.length() < 1) {
+ return name;
+ }
+ // 首字母大写
+ char[] charArray = camel.toCharArray();
+ charArray[0] -= 32;
+ return String.valueOf(charArray);
+ }
+
+ /**
+ * 将驼峰命名转化成下划线
+ *
+ * @param param
+ * @return
+ */
+ public static String camelToUnderline(String param) {
+ if (param == null) {
+ return null;
+ }
+ int paramLen = param.length();
+ if (paramLen < 3) {
+ return param.toLowerCase();
+ }
+ int wordCount = 0;
+ StringBuilder sb = new StringBuilder(param);
+ // 从第三个字符开始 避免命名不规范
+ for (int i = 2; i < paramLen; i++) {
+ if (Character.isUpperCase(param.charAt(i))) {
+ sb.insert(i + wordCount, "_");
+ wordCount += 1;
+ }
+ }
+ return sb.toString().toLowerCase();
+ }
+
+ /**
+ * 根据指定的类名判定指定的类是否存在。
+ *
+ * @param className
+ * @return
+ */
+ public static boolean validClass(String className) {
+ try {
+ Class.forName(className);
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+ /**
+ * 判定类是否继承自父类
+ *
+ * @param cls 子类
+ * @param parentClass 父类
+ * @return
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public static boolean isInherit(Class cls, Class parentClass) {
+ return parentClass.isAssignableFrom(cls);
+ }
+
+ /**
+ * 输入基类包名,扫描其下的类,返回类的全路径
+ *
+ * @param basePackages 如:com.hotent
+ * @return
+ * @throws IllegalArgumentException
+ */
+ @SuppressWarnings("all")
+ public static List scanPackages(String basePackages)
+ throws IllegalArgumentException {
+ ResourcePatternResolver rl = new PathMatchingResourcePatternResolver();
+ MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(
+ rl);
+ List result = new ArrayList();
+ String[] arrayPackages = basePackages.split(",");
+ try {
+ for (int j = 0; j < arrayPackages.length; j++) {
+ String packageToScan = arrayPackages[j];
+ String packagePart = packageToScan.replace('.', '/');
+ String classPattern = "classpath*:/" + packagePart
+ + "/**/*.class";
+ Resource[] resources = rl.getResources(classPattern);
+ for (int i = 0; i < resources.length; i++) {
+ Resource resource = resources[i];
+ MetadataReader metadataReader = metadataReaderFactory
+ .getMetadataReader(resource);
+ String className = metadataReader.getClassMetadata()
+ .getClassName();
+ result.add(className);
+ }
+ }
+ } catch (Exception e) {
+ new IllegalArgumentException("scan pakcage class error,pakcages:"
+ + basePackages);
+ }
+
+ return result;
+ }
+
+ /**
+ * 将字符串数据按照指定的类型进行转换。
+ *
+ * @param typeName 实际的数据类型
+ * @param value 字符串值。
+ * @return Object
+ */
+ public static Object convertByActType(String typeName, String value) {
+ Object o = null;
+ if (typeName.equals("int")) {
+ o = Integer.parseInt(value);
+ } else if (typeName.equals("short")) {
+ o = Short.parseShort(value);
+ } else if (typeName.equals("long")) {
+ o = Long.parseLong(value);
+ } else if (typeName.equals("float")) {
+ o = Float.parseFloat(value);
+ } else if (typeName.equals("double")) {
+ o = Double.parseDouble(value);
+ } else if (typeName.equals("boolean")) {
+ o = Boolean.parseBoolean(value);
+ } else if (typeName.equals("java.lang.String")) {
+ o = value;
+ } else {
+ o = value;
+ }
+ return o;
+ }
+
+ /**
+ * 根据类和成员变量名称获取成员变量。
+ *
+ * @param thisClass
+ * @param fieldName
+ * @return
+ * @throws NoSuchFieldException Field
+ */
+ public static Field getField(Class> thisClass, String fieldName)
+ throws NoSuchFieldException {
+
+ if (fieldName == null) {
+ throw new NoSuchFieldException("Error field !");
+ }
+
+ Field field = thisClass.getDeclaredField(fieldName);
+ return field;
+ }
+
+ /**
+ * 数据列表去重
+ *
+ * @param list
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public static void removeDuplicate(List list) {
+ HashSet h = new HashSet(list);
+ list.clear();
+ list.addAll(h);
+ }
+
+ private static void handleReflectionException(Exception e) {
+ ReflectionUtils.handleReflectionException(e);
+ }
+
+}
\ No newline at end of file
diff --git a/utils/ClassUtils.java b/utils/ClassUtils.java
new file mode 100644
index 0000000..06f1bd1
--- /dev/null
+++ b/utils/ClassUtils.java
@@ -0,0 +1,58 @@
+package com.sgcc.utils;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Class反射工具类
+ *
+ * @author zhaoyuanyuan
+ * @version 1.0.0
+ * @date 2024/06/24 17:26
+ */
+public class ClassUtils {
+
+ /**
+ * 对象转化为Map
+ *
+ * @param obj
+ * @return {@code Map }
+ * @author zhaoyuanyuan
+ * @date 2024/06/24 17:26
+ */
+ public static Map objectToMap(Object obj) throws IllegalAccessException {
+ Map map = new HashMap<>();
+ if (obj == null){
+ return map;
+ }
+ Field[] fields = obj.getClass().getDeclaredFields();
+ for(Field field:fields){
+ field.setAccessible(true);
+ map.put(field.getName(), field.get(obj));
+ }
+ return map;
+ }
+
+ /**
+ * 类型转化,实体对象列表转Map列表
+ *
+ * @param objectList
+ * @return {@code List