From 6fdc5024eb18f538c35aa35fab70c6c402b06f8c Mon Sep 17 00:00:00 2001 From: bynt Date: Mon, 5 Jun 2023 13:38:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=80=A7=E5=88=AB=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eladmin-common/pom.xml | 6 + .../common/convert/JpaConverterListJson.java | 23 + .../me/zhengjie/constant/MailConstant.java | 17 + .../main/java/me/zhengjie/utils/CacheKey.java | 6 + .../java/me/zhengjie/utils/CompressUtil.java | 85 ++++ .../java/me/zhengjie/utils/EncryptUtil.java | 411 ++++++++++++++++++ .../main/java/me/zhengjie/utils/FileUtil.java | 58 +++ .../java/me/zhengjie/utils/RedisUtils.java | 27 +- .../service/mapstruct/LogErrorMapperImpl.java | 2 +- .../service/mapstruct/LogSmallMapperImpl.java | 2 +- eladmin-system/pom.xml | 6 + .../src/main/java/me/zhengjie/AppRun.java | 2 + .../modules/constant/FileConstant.java | 20 + .../config/properties/DeliveryProperties.java | 43 ++ .../modules/gender/domain/DeliveryGender.java | 95 ++++ .../repository/DeliveryGenderRepository.java | 75 ++++ .../gender/rest/DeliveryGenderController.java | 91 ++++ .../gender/service/DeliveryGenderService.java | 110 +++++ .../gender/service/dto/DeliveryGenderDto.java | 54 +++ .../dto/DeliveryGenderQueryCriteria.java | 35 ++ .../impl/DeliveryGenderServiceImpl.java | 207 +++++++++ .../mapstruct/DeliveryGenderMapper.java | 32 ++ .../gender/task/GenderConversionTask.java | 135 ++++++ .../service/impl/LoanUserServiceImpl.java | 1 - .../mnt/service/dto/DeployQueryCriteria.java | 19 +- .../system/domain/sms/util/SmsUtil.java | 3 + .../uploadnew/task/SaveToFileNewTask.java | 9 +- .../modules/uploadnew/util/AESUtils.java | 239 ++++++++++ .../modules/uploadnew/util/ZipUtils.java | 34 ++ .../resources/config/application-prod.yml | 9 + eladmin-tools/pom.xml | 8 +- .../main/java/me/zhengjie/utils/MailUtil.java | 87 +++- 32 files changed, 1925 insertions(+), 26 deletions(-) create mode 100644 eladmin-common/src/main/java/me/zhengjie/common/convert/JpaConverterListJson.java create mode 100644 eladmin-common/src/main/java/me/zhengjie/constant/MailConstant.java create mode 100644 eladmin-common/src/main/java/me/zhengjie/utils/CompressUtil.java create mode 100644 eladmin-common/src/main/java/me/zhengjie/utils/EncryptUtil.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/gender/config/properties/DeliveryProperties.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/gender/domain/DeliveryGender.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/gender/repository/DeliveryGenderRepository.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/gender/rest/DeliveryGenderController.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/gender/service/DeliveryGenderService.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/gender/service/dto/DeliveryGenderDto.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/gender/service/dto/DeliveryGenderQueryCriteria.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/gender/service/impl/DeliveryGenderServiceImpl.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/gender/service/mapstruct/DeliveryGenderMapper.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/gender/task/GenderConversionTask.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/util/AESUtils.java diff --git a/eladmin-common/pom.xml b/eladmin-common/pom.xml index 93e9855..0534df4 100644 --- a/eladmin-common/pom.xml +++ b/eladmin-common/pom.xml @@ -22,5 +22,11 @@ hutool-all ${hutool.version} + + net.lingala.zip4j + zip4j + 1.3.2 + compile + diff --git a/eladmin-common/src/main/java/me/zhengjie/common/convert/JpaConverterListJson.java b/eladmin-common/src/main/java/me/zhengjie/common/convert/JpaConverterListJson.java new file mode 100644 index 0000000..ab8bd6f --- /dev/null +++ b/eladmin-common/src/main/java/me/zhengjie/common/convert/JpaConverterListJson.java @@ -0,0 +1,23 @@ +package me.zhengjie.common.convert; + +import cn.hutool.json.JSONUtil; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; + +/** + * @author Enzo + * @date : 2021/12/28 + */ +@Converter +public class JpaConverterListJson implements AttributeConverter { + @Override + public String convertToDatabaseColumn(Object obj) { + return JSONUtil.toJsonStr(obj); + } + + @Override + public Object convertToEntityAttribute(String s) { + return JSONUtil.parseArray(s); + } +} diff --git a/eladmin-common/src/main/java/me/zhengjie/constant/MailConstant.java b/eladmin-common/src/main/java/me/zhengjie/constant/MailConstant.java new file mode 100644 index 0000000..9d20f43 --- /dev/null +++ b/eladmin-common/src/main/java/me/zhengjie/constant/MailConstant.java @@ -0,0 +1,17 @@ +package me.zhengjie.constant; + +/** + * @author Enzo + * @date : 2022/3/3 + */ +public class MailConstant { + private MailConstant() { + } + + /** + * 请求类型 + */ + public static final String MAIL_TYPE = "GS"; + + +} diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/CacheKey.java b/eladmin-common/src/main/java/me/zhengjie/utils/CacheKey.java index 24ad0c5..1b8b286 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/CacheKey.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/CacheKey.java @@ -53,4 +53,10 @@ public interface CacheKey { * 角色信息 */ String ROLE_ID = "role::id:"; + + + /** + * dmp请求类型 + */ + String GR_REQUEST_TYPE = "gender::request::type"; } diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/CompressUtil.java b/eladmin-common/src/main/java/me/zhengjie/utils/CompressUtil.java new file mode 100644 index 0000000..7eefaaa --- /dev/null +++ b/eladmin-common/src/main/java/me/zhengjie/utils/CompressUtil.java @@ -0,0 +1,85 @@ +package me.zhengjie.utils; + +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import net.lingala.zip4j.core.ZipFile; +import net.lingala.zip4j.exception.ZipException; +import net.lingala.zip4j.model.ZipParameters; +import net.lingala.zip4j.util.Zip4jConstants; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.util.ArrayList; + +/** + * @author Enzo + * @date : 2022/10/24 + */ +public class CompressUtil { + private CompressUtil() { + } + + /** + * @param zipPath 压缩文件路径 + * @param filepath 文件路径 + * @param password 压缩密码 + */ + public static void decryptionCompression(String zipPath, String filepath, String password) { + try { + //创建压缩文件 + ZipFile zipFile = new ZipFile(zipPath); + ArrayList files = new ArrayList<>(); + files.add(new File(filepath)); + + //设置压缩文件参数 + ZipParameters parameters = new ZipParameters(); + //设置压缩方法 + parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); + + //设置压缩级别 + //DEFLATE_LEVEL_FASTEST - Lowest compression level but higher speed of compression + //DEFLATE_LEVEL_FAST - Low compression level but higher speed of compression + //DEFLATE_LEVEL_NORMAL - Optimal balance between compression level/speed + //DEFLATE_LEVEL_MAXIMUM - High compression level with a compromise of speed + //DEFLATE_LEVEL_ULTRA - Highest compression level but low speed + parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); + + + //设置加密方法 + parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES); + + //设置aes加密强度 + parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256); + + if (StringUtils.isNotBlank(password)) { + //设置压缩文件加密 + parameters.setEncryptFiles(Boolean.TRUE); + //设置密码 + parameters.setPassword(password); + } + + //添加文件到压缩文件 + zipFile.addFiles(files, parameters); + } catch (ZipException e) { + e.printStackTrace(); + } + } + + public static String unzipFiles(String fileUrl, String zipPath, String password) throws ZipException { + File file = new File(zipPath); + ZipFile zipFile = new ZipFile(file); + //设置文件编码,根据实际场景 + zipFile.setFileNameCharset(CharsetUtil.GBK); + if (zipFile.isEncrypted()) { + zipFile.setPassword(password); + } + String uuid = IdUtil.randomUUID(); + String filePath + = fileUrl.concat(StrUtil.SLASH).concat(uuid); + zipFile.extractAll(filePath); + return filePath; + } + + +} diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/EncryptUtil.java b/eladmin-common/src/main/java/me/zhengjie/utils/EncryptUtil.java new file mode 100644 index 0000000..a0e3fab --- /dev/null +++ b/eladmin-common/src/main/java/me/zhengjie/utils/EncryptUtil.java @@ -0,0 +1,411 @@ +package me.zhengjie.utils; + +import cn.hutool.core.util.CharsetUtil; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import sun.misc.BASE64Decoder; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.Base64; +import java.util.Objects; + +/** + * @author Enzo + * @date : 2022/11/1 + */ +@Slf4j +public class EncryptUtil { + + + public static final String MD5 = "MD5"; + public static final String SHA1 = "SHA1"; + public static final String HmacMD5 = "HmacMD5"; + public static final String HmacSHA1 = "HmacSHA1"; + public static final String DES = "DES"; + public static final String AES = "AES"; + + + /** + * 签名算法 + */ + public static final String SIGN_ALGORITHMS = "SHA1PRNG"; + + + private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding"; + + /** + * 编码格式;默认使用uft-8 + */ + public static String charset = CharsetUtil.UTF_8; + /** + * DES + */ + public int keysizeDES = 0; + /** + * AES + */ + public static int keysizeAES = 128; + + public static EncryptUtil me; + + private EncryptUtil() { + //单例 + } + + //双重锁 + public static EncryptUtil getInstance() { + if (me == null) { + synchronized (EncryptUtil.class) { + if (me == null) { + me = new EncryptUtil(); + } + } + } + return me; + } + + /** + * 使用MessageDigest进行单向加密(无密码) + * + * @param res 被加密的文本 + * @param algorithm 加密算法名称 + * @return + */ + private String messageDigest(String res, String algorithm) { + try { + MessageDigest md = MessageDigest.getInstance(algorithm); + byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset); + return base64(md.digest(resBytes)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 使用KeyGenerator进行单向/双向加密(可设密码) + * + * @param res 被加密的原文 + * @param algorithm 加密使用的算法名称 + * @param key 加密使用的秘钥 + * @return + */ + private String keyGeneratorMac(String res, String algorithm, String key) { + try { + SecretKey sk = null; + if (key == null) { + KeyGenerator kg = KeyGenerator.getInstance(algorithm); + sk = kg.generateKey(); + } else { + byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset); + sk = new SecretKeySpec(keyBytes, algorithm); + } + Mac mac = Mac.getInstance(algorithm); + mac.init(sk); + byte[] result = mac.doFinal(res.getBytes()); + return base64(result); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 使用KeyGenerator双向加密,DES/AES,注意这里转化为字符串的时候是将2进制转为16进制格式的字符串,不是直接转,因为会出错 + * + * @param res 加密的原文 + * @param algorithm 加密使用的算法名称 + * @param key 加密的秘钥 + * @param keysize + * @param isEncode + * @return + */ + private static String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) { + try { + KeyGenerator kg = KeyGenerator.getInstance(algorithm); + SecureRandom random = SecureRandom.getInstance(SIGN_ALGORITHMS); + if (keysize == 0) { + byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset); + random.setSeed(keyBytes); + kg.init(random); + } else if (key == null) { + kg.init(keysize); + } else { + byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset); + random.setSeed(keyBytes); + kg.init(keysize, random); + } + SecretKey sk = kg.generateKey(); + SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm); + Cipher cipher = Cipher.getInstance(algorithm); + if (isEncode) { + cipher.init(Cipher.ENCRYPT_MODE, sks); + byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset); + return parseByte2HexStr(cipher.doFinal(resBytes)); + } else { + cipher.init(Cipher.DECRYPT_MODE, sks); + return new String(cipher.doFinal(Objects.requireNonNull(parseHexStr2Byte(res)))); + } + } catch (Exception e) { + log.error("++++++++++++++++++ the keyGeneratorES error res as {} key as {} +++++++++++++++", res, key); + } + return null; + } + + private String base64(byte[] res) { + return Base64.getEncoder().encodeToString(res); + } + + /** + * 将二进制转换成16进制 + */ + public static String parseByte2HexStr(byte[] buf) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < buf.length; i++) { + String hex = Integer.toHexString(buf[i] & 0xFF); + if (hex.length() == 1) { + hex = '0' + hex; + } + sb.append(hex.toUpperCase()); + } + return sb.toString(); + } + + /** + * 将16进制转换为二进制 + */ + public static byte[] parseHexStr2Byte(String hexStr) { + if (hexStr.length() < 1) { + return null; + } + byte[] result = new byte[hexStr.length() / 2]; + for (int i = 0; i < hexStr.length() / 2; i++) { + int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16); + int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16); + result[i] = (byte) (high * 16 + low); + } + return result; + } + + /** + * md5加密算法进行加密(不可逆) + * + * @param res 需要加密的原文 + * @return + */ + public String MD5(String res) { + return messageDigest(res, MD5); + } + + /** + * md5加密算法进行加密(不可逆) + * + * @param res 需要加密的原文 + * @param key 秘钥 + * @return + */ + public String MD5(String res, String key) { + return keyGeneratorMac(res, HmacMD5, key); + } + + /** + * 使用SHA1加密算法进行加密(不可逆) + * + * @param res 需要加密的原文 + * @return + */ + public String SHA1(String res) { + return messageDigest(res, SHA1); + } + + /** + * 使用SHA1加密算法进行加密(不可逆) + * + * @param res 需要加密的原文 + * @param key 秘钥 + * @return + */ + public String SHA1(String res, String key) { + return keyGeneratorMac(res, HmacSHA1, key); + } + + /** + * 使用DES加密算法进行加密(可逆) + * + * @param res 需要加密的原文 + * @param key 秘钥 + * @return + */ + public String DESencode(String res, String key) { + return keyGeneratorES(res, DES, key, keysizeDES, true); + } + + /** + * 对使用DES加密算法的密文进行解密(可逆) + * + * @param res 需要解密的密文 + * @param key 秘钥 + * @return + */ + public String DESdecode(String res, String key) { + return keyGeneratorES(res, DES, key, keysizeDES, false); + } + + /** + * 使用AES加密算法经行加密(可逆) + * + * @param res 需要加密的密文 + * @param key 秘钥 + * @return + */ + public static String AESEncode(String res, String key) { + return keyGeneratorES(res, AES, key, keysizeAES, true); + } + + /** + * 对使用AES加密算法的密文进行解密 + * + * @param res 需要解密的密文 + * @param key 秘钥 + * @return + */ + public static String AESDecode(String res, String key) { + return keyGeneratorES(res, AES, key, keysizeAES, false); + } + + /** + * 使用异或进行加密 + * + * @param res 需要加密的密文 + * @param key 秘钥 + * @return + */ + public String XORencode(String res, String key) { + byte[] bs = res.getBytes(); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) ((bs[i]) ^ key.hashCode()); + } + return parseByte2HexStr(bs); + } + + /** + * 使用异或进行解密 + * + * @param res 需要解密的密文 + * @param key 秘钥 + * @return + */ + public String XORdecode(String res, String key) { + byte[] bs = parseHexStr2Byte(res); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) ((bs[i]) ^ key.hashCode()); + } + return new String(bs); + } + + /** + * 直接使用异或(第一调用加密,第二次调用解密) + * + * @param res 密文 + * @param key 秘钥 + * @return + */ + public int XOR(int res, String key) { + return res ^ key.hashCode(); + } + + + /** + * base 64 encode + * + * @param bytes 待编码的byte[] + * @return 编码后的base 64 code + */ + public static String base64Encode(byte[] bytes) { + return Base64.getEncoder().encodeToString(bytes); + } + + /** + * base 64 decode + * + * @param base64Code 待解码的base 64 code + * @return 解码后的byte[] + * @throws Exception + */ + public static byte[] base64Decode(String base64Code) throws Exception { + return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code); + } + + + /** + * AES加密 + * + * @param content 待加密的内容 + * @param encryptKey 加密密钥 + * @return 加密后的byte[] + * @throws Exception + */ + @SneakyThrows + public static byte[] aesEncryptToBytes(String content, String encryptKey) { + KeyGenerator kgen = KeyGenerator.getInstance(AES); + kgen.init(128); + Cipher cipher = Cipher.getInstance(ALGORITHMSTR); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), AES)); + return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)); + + } + + + /** + * AES加密为base 64 code + * + * @param content 待加密的内容 + * @param encryptKey 加密密钥 + * @return 加密后的base 64 code + * @throws Exception + */ + public static String aesEncrypt(String content, String encryptKey) { + return base64Encode(aesEncryptToBytes(content, encryptKey)); + } + + /** + * AES解密 + * + * @param encryptBytes 待解密的byte[] + * @param decryptKey 解密密钥 + * @return 解密后的String + * @throws Exception + */ + public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception { + KeyGenerator kgen = KeyGenerator.getInstance(AES); + kgen.init(128); + + Cipher cipher = Cipher.getInstance(ALGORITHMSTR); + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), AES)); + byte[] decryptBytes = cipher.doFinal(encryptBytes); + return new String(decryptBytes); + } + + + /** + * 将base 64 code AES解密 + * + * @param encryptStr 待解密的base 64 code + * @param decryptKey 解密密钥 + * @return 解密后的string + * @throws Exception + */ + public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception { + return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey); + } + + +} diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java b/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java index 5edd704..9242a4e 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java @@ -17,9 +17,11 @@ package me.zhengjie.utils; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.poi.excel.BigExcelWriter; import cn.hutool.poi.excel.ExcelUtil; import me.zhengjie.exception.BadRequestException; +import org.apache.commons.lang3.StringUtils; import org.apache.poi.util.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -333,8 +335,64 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { } } + + /** + * MultipartFile转file + * @param multipartFile + * @return + */ + public static File multiToFile(MultipartFile multipartFile) { + //选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 。 + File file = null; + try { + String originalFilename = multipartFile.getOriginalFilename(); + String[] filename = originalFilename.split("\\."); + file = File.createTempFile(filename[0], StrUtil.DOT.concat(filename[1])); + multipartFile.transferTo(file); + file.deleteOnExit(); + } catch (IOException e) { + log.error(e.getMessage()); + } + return file; + } + + + public static String getMd5(File file) { return getMd5(getByte(file)); } + + + /** + * CSV文件生成方法 字符流追加:FileWriter writer = new FileWriter(file,true) + * + * @param dataList 数据列表 + * @param filePath 文件路径 + * @param addFlag 是否追加 + */ + public static void writeToCsv(List dataList, String filePath, boolean addFlag) { + //根据指定路径构建文件对象 + File csvFile = new File(filePath); + try ( + //文件输出流对象,第二个参数时boolean类型,为true表示文件追加(在已有的文件中追加内容) + FileWriter writer = new FileWriter(csvFile, addFlag); + //构建缓存字符输出流(不推荐使用OutputStreamWriter) + BufferedWriter buffWriter = new BufferedWriter(writer, 1024)) { + + //遍历list + for (String rowStr : dataList) { + //如果数据不为空,则写入文件内容,并且换行 + if (StringUtils.isNotBlank(rowStr)) { + buffWriter.write(rowStr); + buffWriter.newLine();//文件写完最后一个换行不用处理 + } + } + //刷新流,也就是把缓存中剩余的内容输出到文件 + buffWriter.flush(); + } catch (Exception e) { + throw new BadRequestException("failed to write to csv"); + } + + } } diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/RedisUtils.java b/eladmin-common/src/main/java/me/zhengjie/utils/RedisUtils.java index 2973cc5..bd3dd7e 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/RedisUtils.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/RedisUtils.java @@ -15,8 +15,14 @@ */ package me.zhengjie.utils; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import me.zhengjie.constant.MailConstant; +import me.zhengjie.constant.SystemConstant; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -214,7 +220,7 @@ public class RedisUtils { public List multiGet(List keys) { List list = redisTemplate.opsForValue().multiGet(Sets.newHashSet(keys)); List resultList = Lists.newArrayList(); - Optional.ofNullable(list).ifPresent(e-> list.forEach(ele-> Optional.ofNullable(ele).ifPresent(resultList::add))); + Optional.ofNullable(list).ifPresent(e -> list.forEach(ele -> Optional.ofNullable(ele).ifPresent(resultList::add))); return resultList; } @@ -706,4 +712,23 @@ public class RedisUtils { log.debug("缓存删除数量:" + count + "个"); log.debug("--------------------------------------------"); } + + + /** + * 批次获取 + * + * @param prefix + * @param ids + */ + public String acquisitionBatch(String cacheType) { + String format = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_PATTERN); + Integer num = (Integer) get(cacheType.concat(format)); + Integer batch = ObjectUtil.isNull(num) ? + 1 : num + 1; + // 保存批次号 + set(cacheType.concat(format), batch, 1, TimeUnit.DAYS); + return MailConstant.MAIL_TYPE.concat(StrUtil.DASHED). + concat(format).concat(StrUtil.DASHED).concat(String.valueOf(batch)); + + } } diff --git a/eladmin-logging/target/generated-sources/annotations/me/zhengjie/service/mapstruct/LogErrorMapperImpl.java b/eladmin-logging/target/generated-sources/annotations/me/zhengjie/service/mapstruct/LogErrorMapperImpl.java index 1c66da5..e9a9b78 100644 --- a/eladmin-logging/target/generated-sources/annotations/me/zhengjie/service/mapstruct/LogErrorMapperImpl.java +++ b/eladmin-logging/target/generated-sources/annotations/me/zhengjie/service/mapstruct/LogErrorMapperImpl.java @@ -9,7 +9,7 @@ import org.springframework.stereotype.Component; @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2023-05-29T16:32:36+0800", + date = "2023-06-05T10:51:01+0800", comments = "version: 1.3.1.Final, compiler: javac, environment: Java 1.8.0_251 (Oracle Corporation)" ) @Component diff --git a/eladmin-logging/target/generated-sources/annotations/me/zhengjie/service/mapstruct/LogSmallMapperImpl.java b/eladmin-logging/target/generated-sources/annotations/me/zhengjie/service/mapstruct/LogSmallMapperImpl.java index 7f874e8..6fcd3a7 100644 --- a/eladmin-logging/target/generated-sources/annotations/me/zhengjie/service/mapstruct/LogSmallMapperImpl.java +++ b/eladmin-logging/target/generated-sources/annotations/me/zhengjie/service/mapstruct/LogSmallMapperImpl.java @@ -9,7 +9,7 @@ import org.springframework.stereotype.Component; @Generated( value = "org.mapstruct.ap.MappingProcessor", - date = "2023-05-29T16:32:36+0800", + date = "2023-06-05T10:51:01+0800", comments = "version: 1.3.1.Final, compiler: javac, environment: Java 1.8.0_251 (Oracle Corporation)" ) @Component diff --git a/eladmin-system/pom.xml b/eladmin-system/pom.xml index fc66362..0bbb6be 100644 --- a/eladmin-system/pom.xml +++ b/eladmin-system/pom.xml @@ -121,6 +121,12 @@ aliyun-sdk-oss 3.10.0 + + + net.lingala.zip4j + zip4j + 1.3.2 + diff --git a/eladmin-system/src/main/java/me/zhengjie/AppRun.java b/eladmin-system/src/main/java/me/zhengjie/AppRun.java index ed24406..e7775b3 100644 --- a/eladmin-system/src/main/java/me/zhengjie/AppRun.java +++ b/eladmin-system/src/main/java/me/zhengjie/AppRun.java @@ -25,6 +25,7 @@ import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.bind.annotation.RestController; @@ -36,6 +37,7 @@ import org.springframework.web.bind.annotation.RestController; */ @EnableAsync @RestController +@EnableScheduling @Api(hidden = true) @SpringBootApplication @EnableTransactionManagement diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/constant/FileConstant.java b/eladmin-system/src/main/java/me/zhengjie/modules/constant/FileConstant.java index acb2742..74dd301 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/constant/FileConstant.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/constant/FileConstant.java @@ -7,6 +7,20 @@ package me.zhengjie.modules.constant; */ public class FileConstant { + + /** + * zip 密码 + */ + public static final String ZIP_PASSWORD = "DB2022hjk213v1..."; + + public static final String PLAT_DECRYPTION = "CXpRNIJC4xlZd6vk"; + + + /** + * 加密密码 + */ + public static final String AES_PASSWORD = "park_%33229*711&"; + /** * 文件分隔符 . */ @@ -42,4 +56,10 @@ public class FileConstant { * 以 rar 结尾的文件 */ public static final String RAR_FILE_SUB_NAME = "rar"; + + + + + + } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/gender/config/properties/DeliveryProperties.java b/eladmin-system/src/main/java/me/zhengjie/modules/gender/config/properties/DeliveryProperties.java new file mode 100644 index 0000000..f2d1787 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/gender/config/properties/DeliveryProperties.java @@ -0,0 +1,43 @@ +package me.zhengjie.modules.gender.config.properties; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author Enzo + * @date : 2022/10/18 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "gender") +public class DeliveryProperties { + + @ApiModelProperty("文件地址") + private String fileUrl; + + @ApiModelProperty("压缩密码") + private String zipPassword; + + @ApiModelProperty("下载地址") + private String downPath; + + @ApiModelProperty("emailAddress") + private String emailAddress; + + @ApiModelProperty("genderEmailAddress") + private String genderEmailAddress; + + + @ApiModelProperty("emailPassword") + private String emailPassword; + + + + @ApiModelProperty("toGenderEmailAddress") + private String toGenderEmailAddress; + + + +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/gender/domain/DeliveryGender.java b/eladmin-system/src/main/java/me/zhengjie/modules/gender/domain/DeliveryGender.java new file mode 100644 index 0000000..9ba22f6 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/gender/domain/DeliveryGender.java @@ -0,0 +1,95 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package me.zhengjie.modules.gender.domain; + +import lombok.Data; +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.ApiModelProperty; +import cn.hutool.core.bean.copier.CopyOptions; +import me.zhengjie.common.convert.JpaConverterListJson; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import javax.persistence.*; +import javax.validation.constraints.*; +import java.sql.Timestamp; +import java.io.Serializable; +import java.util.List; + +/** +* @website https://el-admin.vip +* @description / +* @author Enzo +* @date 2023-06-01 +**/ +@Entity +@Data +@Table(name="tb_delivery_gender") +public class DeliveryGender implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + @ApiModelProperty(value = "id") + private Long id; + + @Column(name = "task_name") + @ApiModelProperty(value = "名称") + private String taskName; + + @Column(name = "num") + @ApiModelProperty(value = "数量") + private Integer num; + + @Column(name = "status") + @ApiModelProperty(value = "状态") + private Integer status; + + @Column(name = "down_url") + @ApiModelProperty(value = "下载地址") + private String downUrl; + + @Column(name = "down_path") + @ApiModelProperty(value = "文件地址") + private String downPath; + + @Column(name = "mail_name") + @ApiModelProperty(value = "文件地址") + private String mailName; + + @Column(name = "type") + @ApiModelProperty(value = "类型") + private Integer type; + + @CreationTimestamp + @Column(name = "create_time") + @ApiModelProperty(value = "创建时间") + private Timestamp createTime; + + @UpdateTimestamp + @Column(name = "update_time") + @ApiModelProperty(value = "更新时间") + private Timestamp updateTime; + + @Column(name = "task_num_str") + @ApiModelProperty(value = "标识") + @Convert(converter = JpaConverterListJson.class) + private List taskNumStr; + + public void copy(DeliveryGender source){ + BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/gender/repository/DeliveryGenderRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/gender/repository/DeliveryGenderRepository.java new file mode 100644 index 0000000..0add4b5 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/gender/repository/DeliveryGenderRepository.java @@ -0,0 +1,75 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package me.zhengjie.modules.gender.repository; + +import me.zhengjie.modules.gender.domain.DeliveryGender; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + +/** + * @author Enzo + * @website https://el-admin.vip + * @date 2023-06-01 + **/ +public interface DeliveryGenderRepository extends JpaRepository, JpaSpecificationExecutor { + + /** + * 任务查找记录 + * + * @param taskName + * @return + */ + @Query(value = "from DeliveryGender where taskName = ?1 order by id desc ") + List findByTaskName(String taskName); + + + + /** + * 发送邮件查找记录 + * + * @param taskName + * @return + */ + @Query(value = "from DeliveryGender where mailName = ?1 order by id desc ") + List findByMailName(String taskName); + + /** + * 修改状态 + * + * @param num + * @param taskName + * @return + */ + @Modifying + @Query("UPDATE DeliveryGender d set d.status = ?1 where d.taskName = ?2") + int updateStatusAndDecryptNum(Integer num, String taskName); + + /** + * 修改状态 + * @param downUrl + * @param zipPath + * @param number + * @param taskName + * @return + */ + @Modifying + @Query("UPDATE DeliveryGender d set d.status = ?3,d.downUrl = ?1,d.downPath = ?2 where d.taskName = ?4") + int updateStatusAndDownUrlByTaskName(String downUrl, String zipPath, Integer number, String taskName); +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/gender/rest/DeliveryGenderController.java b/eladmin-system/src/main/java/me/zhengjie/modules/gender/rest/DeliveryGenderController.java new file mode 100644 index 0000000..1df069c --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/gender/rest/DeliveryGenderController.java @@ -0,0 +1,91 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package me.zhengjie.modules.gender.rest; + +import me.zhengjie.annotation.Log; +import me.zhengjie.modules.gender.domain.DeliveryGender; +import me.zhengjie.modules.gender.service.DeliveryGenderService; +import me.zhengjie.modules.gender.service.dto.DeliveryGenderQueryCriteria; +import org.springframework.data.domain.Pageable; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import io.swagger.annotations.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; + +/** +* @website https://el-admin.vip +* @author Enzo +* @date 2023-06-01 +**/ +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/deliveryGender") +public class DeliveryGenderController { + + private final DeliveryGenderService deliveryGenderService; + + @Log("导出数据") + @ApiOperation("导出数据") + @GetMapping(value = "/download") + @PreAuthorize("@el.check('deliveryGender:list')") + public void download(HttpServletResponse response, DeliveryGenderQueryCriteria criteria) throws IOException { + deliveryGenderService.download(deliveryGenderService.queryAll(criteria), response); + } + + @GetMapping + @ApiOperation("查询") + @PreAuthorize("@el.check('deliveryGender:list')") + public ResponseEntity query(DeliveryGenderQueryCriteria criteria, Pageable pageable){ + return new ResponseEntity<>(deliveryGenderService.queryAll(criteria,pageable),HttpStatus.OK); + } + + @PostMapping + @ApiOperation("新增") + @PreAuthorize("@el.check('deliveryGender:add')") + public ResponseEntity create(@Validated @RequestBody DeliveryGender resources){ + return new ResponseEntity<>(deliveryGenderService.create(resources),HttpStatus.CREATED); + } + + @PutMapping + @ApiOperation("修改") + @PreAuthorize("@el.check('deliveryGender:edit')") + public ResponseEntity update(@Validated @RequestBody DeliveryGender resources){ + deliveryGenderService.update(resources); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @ApiOperation("删除") + @PreAuthorize("@el.check('deliveryGender:del')") + @DeleteMapping + public ResponseEntity delete(@RequestBody Long[] ids) { + deliveryGenderService.deleteAll(ids); + return new ResponseEntity<>(HttpStatus.OK); + } + + + @ApiOperation("上传文件发送邮件") + @PostMapping("/upload/files") + public ResponseEntity uploadFile(@RequestParam("file") MultipartFile[] files, @RequestParam(value = "taskName") String taskName) { + return new ResponseEntity<>(deliveryGenderService.uploadFile(files, taskName), HttpStatus.OK); + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/DeliveryGenderService.java b/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/DeliveryGenderService.java new file mode 100644 index 0000000..1a3491d --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/DeliveryGenderService.java @@ -0,0 +1,110 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package me.zhengjie.modules.gender.service; + +import me.zhengjie.modules.gender.domain.DeliveryGender; +import me.zhengjie.modules.gender.service.dto.DeliveryGenderDto; +import me.zhengjie.modules.gender.service.dto.DeliveryGenderQueryCriteria; +import org.springframework.data.domain.Pageable; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Map; +import java.util.List; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; + +/** +* @website https://el-admin.vip +* @description 服务接口 +* @author Enzo +* @date 2023-06-01 +**/ +public interface DeliveryGenderService { + + /** + * 查询数据分页 + * @param criteria 条件 + * @param pageable 分页参数 + * @return Map + */ + Map queryAll(DeliveryGenderQueryCriteria criteria, Pageable pageable); + + /** + * 查询所有数据不分页 + * @param criteria 条件参数 + * @return List + */ + List queryAll(DeliveryGenderQueryCriteria criteria); + + /** + * 根据ID查询 + * @param id ID + * @return DeliveryGenderDto + */ + DeliveryGenderDto findById(Long id); + + /** + * 创建 + * @param resources / + * @return DeliveryGenderDto + */ + DeliveryGenderDto create(DeliveryGender resources); + + /** + * 编辑 + * @param resources / + */ + void update(DeliveryGender resources); + + /** + * 多选删除 + * @param ids / + */ + void deleteAll(Long[] ids); + + /** + * 导出数据 + * @param all 待导出的数据 + * @param response / + * @throws IOException / + */ + void download(List all, HttpServletResponse response) throws IOException; + /** + * 上传文件发送邮件 + * + * @param files + * @param taskName + * @return + */ + Boolean uploadFile(MultipartFile[] files, String taskName); + + /** + * 名称查找 + * @param substring + * @return + */ + DeliveryGender findByMailName(String substring); + + /** + * 修改下载地址 + * + * @param downUrl + * @param zipPath + * @param number + * @param taskName + */ + Boolean updateStatusByTaskName(String downUrl, String zipPath, Integer number, String taskName); +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/dto/DeliveryGenderDto.java b/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/dto/DeliveryGenderDto.java new file mode 100644 index 0000000..3735d8a --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/dto/DeliveryGenderDto.java @@ -0,0 +1,54 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package me.zhengjie.modules.gender.service.dto; + +import lombok.Data; +import java.sql.Timestamp; +import java.io.Serializable; +import java.util.List; + +/** +* @website https://el-admin.vip +* @description / +* @author Enzo +* @date 2023-06-01 +**/ +@Data +public class DeliveryGenderDto implements Serializable { + + private Long id; + + /** 名称 */ + private String taskName; + + /** 数量 */ + private Integer num; + + /** 状态 */ + private Integer status; + + /** 类型 */ + private Integer type; + + /** 创建时间 */ + private Timestamp createTime; + + /** 更新时间 */ + private Timestamp updateTime; + + /** 标识 */ + private List taskNumStr; +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/dto/DeliveryGenderQueryCriteria.java b/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/dto/DeliveryGenderQueryCriteria.java new file mode 100644 index 0000000..6cb9493 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/dto/DeliveryGenderQueryCriteria.java @@ -0,0 +1,35 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package me.zhengjie.modules.gender.service.dto; + +import lombok.Data; +import me.zhengjie.annotation.Query; + +/** + * @author Enzo + * @website https://el-admin.vip + * @date 2023-06-01 + **/ +@Data +public class DeliveryGenderQueryCriteria { + + /** + * 模糊 + */ + @Query(type = Query.Type.INNER_LIKE) + private String taskName; + +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/impl/DeliveryGenderServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/impl/DeliveryGenderServiceImpl.java new file mode 100644 index 0000000..9435c78 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/impl/DeliveryGenderServiceImpl.java @@ -0,0 +1,207 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package me.zhengjie.modules.gender.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import me.zhengjie.exception.BadRequestException; +import me.zhengjie.modules.constant.FileConstant; +import me.zhengjie.modules.gender.config.properties.DeliveryProperties; +import me.zhengjie.modules.gender.domain.DeliveryGender; +import me.zhengjie.modules.gender.repository.DeliveryGenderRepository; +import me.zhengjie.modules.gender.service.DeliveryGenderService; +import me.zhengjie.modules.gender.service.dto.DeliveryGenderDto; +import me.zhengjie.modules.gender.service.dto.DeliveryGenderQueryCriteria; +import me.zhengjie.modules.gender.service.mapstruct.DeliveryGenderMapper; +import me.zhengjie.modules.uploadnew.util.AESUtils; +import me.zhengjie.modules.uploadnew.util.ToolExcelUtils; +import me.zhengjie.modules.uploadnew.util.TxtUtils; +import me.zhengjie.modules.uploadnew.util.ZipUtils; +import me.zhengjie.utils.*; +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author Enzo + * @website https://el-admin.vip + * @description 服务实现 + * @date 2023-06-01 + **/ +@Slf4j +@Service +@RequiredArgsConstructor +public class DeliveryGenderServiceImpl implements DeliveryGenderService { + + private final DeliveryGenderRepository deliveryGenderRepository; + + private final DeliveryGenderMapper deliveryGenderMapper; + + private final DeliveryProperties deliveryProperties; + + private final RedisUtils redisUtils; + + + @Override + public Map queryAll(DeliveryGenderQueryCriteria criteria, Pageable pageable) { + Page page = deliveryGenderRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable); + return PageUtil.toPage(page.map(deliveryGenderMapper::toDto)); + } + + @Override + public List queryAll(DeliveryGenderQueryCriteria criteria) { + return deliveryGenderMapper.toDto(deliveryGenderRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder))); + } + + @Override + @Transactional + public DeliveryGenderDto findById(Long id) { + DeliveryGender deliveryGender = deliveryGenderRepository.findById(id).orElseGet(DeliveryGender::new); + ValidationUtil.isNull(deliveryGender.getId(), "DeliveryGender", "id", id); + return deliveryGenderMapper.toDto(deliveryGender); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public DeliveryGenderDto create(DeliveryGender resources) { + return deliveryGenderMapper.toDto(deliveryGenderRepository.save(resources)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(DeliveryGender resources) { + DeliveryGender deliveryGender = deliveryGenderRepository.findById(resources.getId()).orElseGet(DeliveryGender::new); + ValidationUtil.isNull(deliveryGender.getId(), "DeliveryGender", "id", resources.getId()); + deliveryGender.copy(resources); + deliveryGenderRepository.save(deliveryGender); + } + + @Override + public void deleteAll(Long[] ids) { + for (Long id : ids) { + DeliveryGender deliveryGender = deliveryGenderRepository.findById(id).orElseGet(DeliveryGender::new); + if (ObjectUtil.isNotNull(deliveryGender)){ + FileUtil.del(deliveryGender.getDownPath()); + } + deliveryGenderRepository.deleteById(id); + } + } + + @Override + public void download(List all, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (DeliveryGenderDto genderDto : all) { + Map map = new LinkedHashMap<>(); + map.put("名称", genderDto.getTaskName()); + map.put("数量", genderDto.getNum()); + map.put("状态", genderDto.getStatus()); + map.put("类型", genderDto.getType()); + map.put("创建时间", genderDto.getCreateTime()); + map.put("更新时间", genderDto.getUpdateTime()); + map.put("标识", genderDto.getTaskNumStr()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } + + + @Override + @SneakyThrows + public Boolean uploadFile(MultipartFile[] files, String taskName) { + if (files.length > 0) { + List arrayList = Lists.newArrayList(); + for (MultipartFile file : files) { + String originalFilename = file.getOriginalFilename(); + File filePath = FileUtil.multiToFile(file); + if (StringUtils.isNotBlank(originalFilename)) { + arrayList = originalFilename.contains(FileConstant.TXT_FILE_SUB_NAME) + ? TxtUtils.txtParseListVyUrl(filePath.getPath()) : + originalFilename.contains(FileConstant.CSV_FILE_SUB_NAME) + ? ToolExcelUtils.csvParseListByUrl(filePath.getPath()) + : ToolExcelUtils.excelParseListByUrl(filePath.getPath()); + } + } + if (CollUtil.isNotEmpty(arrayList)) { + // 去除重复数据 + List dtoArrayList = Lists.newArrayList(Sets.newHashSet(arrayList)); + // 加密 + List stringList = dtoArrayList.stream().filter + (StringUtils::isNotBlank).map + (source -> AESUtils.dbEncrypt(FileConstant.AES_PASSWORD, source)) + .collect(Collectors.toList()); + if (stringList.size() < 100) { + throw new BadRequestException("上传条数不能小于100条"); + } + // 每次500000 数据 + List> partition = Lists.partition(stringList, 500000); + for (List list : partition) { + String uuid = IdUtil.fastSimpleUUID(); + String sendMailName = redisUtils.acquisitionBatch(CacheKey.GR_REQUEST_TYPE); + String file = FileUtil.SYS_TEM_DIR.concat(StrUtil.SLASH).concat(uuid); + // 保存文件下载地址 + ZipUtils.zipFileAndSendGenderMail(list, file, sendMailName, deliveryProperties); + this.saveDeliveryRecord(taskName, sendMailName, list.size(), 1); + } + return Boolean.TRUE; + } + } + return Boolean.FALSE; + } + + public Boolean saveDeliveryRecord(String taskImeiName, String sendMailName, Integer num, Integer type) { + DeliveryGender deliveryRecord = new DeliveryGender(); + deliveryRecord.setNum(num); + deliveryRecord.setStatus(0); + deliveryRecord.setType(type); + deliveryRecord.setMailName(sendMailName); + deliveryRecord.setTaskName(taskImeiName); + return deliveryGenderRepository.save(deliveryRecord).getId() != null; + } + + @Override + public DeliveryGender findByMailName(String taskName) { + // 防止重复提交数据 + List byTaskName = + deliveryGenderRepository.findByMailName(taskName); + return CollUtil.isNotEmpty(byTaskName) ? byTaskName.get(0) : null; + } + + @Override + public Boolean updateStatusByTaskName(String downUrl, String zipPath, Integer number, String taskName) { + return deliveryGenderRepository.updateStatusAndDownUrlByTaskName(downUrl, zipPath, number, taskName) > 0; + } + +} + diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/mapstruct/DeliveryGenderMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/mapstruct/DeliveryGenderMapper.java new file mode 100644 index 0000000..53d28f9 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/gender/service/mapstruct/DeliveryGenderMapper.java @@ -0,0 +1,32 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package me.zhengjie.modules.gender.service.mapstruct; + +import me.zhengjie.base.BaseMapper; +import me.zhengjie.modules.gender.domain.DeliveryGender; +import me.zhengjie.modules.gender.service.dto.DeliveryGenderDto; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** +* @website https://el-admin.vip +* @author Enzo +* @date 2023-06-01 +**/ +@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface DeliveryGenderMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/gender/task/GenderConversionTask.java b/eladmin-system/src/main/java/me/zhengjie/modules/gender/task/GenderConversionTask.java new file mode 100644 index 0000000..140635d --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/gender/task/GenderConversionTask.java @@ -0,0 +1,135 @@ +package me.zhengjie.modules.gender.task; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.text.csv.CsvData; +import cn.hutool.core.text.csv.CsvReader; +import cn.hutool.core.text.csv.CsvUtil; +import cn.hutool.core.text.csv.CsvWriter; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import me.zhengjie.constant.MailConstant; +import me.zhengjie.modules.constant.FileConstant; +import me.zhengjie.modules.gender.config.properties.DeliveryProperties; +import me.zhengjie.modules.gender.domain.DeliveryGender; +import me.zhengjie.modules.gender.service.DeliveryGenderService; +import me.zhengjie.modules.uploadnew.util.AESUtils; +import me.zhengjie.utils.*; +import org.apache.commons.lang3.StringUtils; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import javax.mail.Message; +import javax.mail.internet.MimeMessage; +import java.io.File; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author Enzo + * @date : 2023/5/15 + */ + +@Slf4j +@Component +@RequiredArgsConstructor +public class GenderConversionTask { + + + private final RedisUtils redisUtils; + + private final DeliveryProperties deliveryProperties; + + private final DeliveryGenderService deliveryGenderService; + + + @SneakyThrows + @Scheduled(cron = "0 0/10 * * * ? ") + @Transactional(rollbackFor = Exception.class) + public void receiveMail() { + // 获取邮件内容 + List list = MailUtil.readMailByIMAP + (deliveryProperties.getGenderEmailAddress(), deliveryProperties.getEmailPassword()); + if (CollUtil.isNotEmpty(list)) { + for (Message message : list) { + // 获取未读的邮件内容 且与之对应 + if (deliveryProperties.getToGenderEmailAddress().equalsIgnoreCase + (MailUtil.getFrom((MimeMessage) message))) { + String taskName = message.getSubject(); + Object objCache = redisUtils.get(taskName); + if (ObjectUtil.isNotNull(objCache)) { + continue; + } + // 设置十分钟缓存 + redisUtils.set(taskName, taskName, 10, TimeUnit.MINUTES); + if (taskName.startsWith(MailConstant.MAIL_TYPE)) { + String substring = taskName.substring(0, taskName.lastIndexOf(StrUtil.DASHED)); + DeliveryGender byTaskName = deliveryGenderService.findByMailName(substring); + if (ObjectUtil.isNotNull(byTaskName) + && !byTaskName.getTaskNumStr().contains(taskName)) { + List taskNumStr = byTaskName.getTaskNumStr(); + taskNumStr.add(taskName); + log.info("================ the gender mail taskName as {} ==============", taskName); + List joinList = Lists.newArrayList(); + CsvReader reader = CsvUtil.getReader(); + // 解析附件内容并保存文件 + String path = MailUtil.saveAttachMent + (message, deliveryProperties.getFileUrl()); + // 解压文件 + String unzipPath = + CompressUtil.unzipFiles(deliveryProperties.getFileUrl(), + path, deliveryProperties.getZipPassword()); + File file = new File(unzipPath); + File parseFile = Objects.requireNonNull + (file.listFiles())[0]; + // 解析文件 + CsvData data = reader.read(parseFile); + // csv通配 + data.getRows().forEach(clue -> { + String decrypt = AESUtils.dbDecrypt + (FileConstant.AES_PASSWORD, clue.get(0)); + String aesEncrypt = EncryptUtil.aesEncrypt(decrypt, FileConstant.PLAT_DECRYPTION); + List collect = Stream.of(aesEncrypt, clue.get(1)).collect(Collectors.toList()); + String join = Joiner.on(StrUtil.COMMA).skipNulls().join(collect); + joinList.add(join); + }); + + if (StringUtils.isNotBlank(byTaskName.getDownPath())) { + FileUtil.writeToCsv(joinList, parseFile.getPath(), Boolean.TRUE); + deliveryGenderService.update(byTaskName); + return; + } + String down = deliveryProperties.getFileUrl().concat(StrUtil.SLASH).concat(IdUtil.fastSimpleUUID()); + // 首次加载 + String csvPath = down.concat(StrUtil.DOT).concat(FileConstant.CSV_FILE_SUB_NAME); + String zipPath = down.concat(StrUtil.DOT).concat(FileConstant.ZIP_FILE_SUB_NAME); + CsvWriter writer = CsvUtil.getWriter(csvPath, CharsetUtil.CHARSET_UTF_8); + writer.write(joinList); + writer.close(); + // 设置压缩文件 + CompressUtil.decryptionCompression(zipPath, csvPath, null); + String filePath = zipPath.substring + (zipPath.lastIndexOf(StrUtil.SLASH) + 1); + String downUrl = deliveryProperties.getDownPath().concat(filePath); + byTaskName.setStatus(1); + byTaskName.setDownUrl(downUrl); + byTaskName.setDownPath(zipPath); + deliveryGenderService.update(byTaskName); + log.info("================ change down url {} zip url {} ================", zipPath, filePath); + } + } + } + } + } + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/loan/service/impl/LoanUserServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/loan/service/impl/LoanUserServiceImpl.java index b713f4a..59ebd2c 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/loan/service/impl/LoanUserServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/loan/service/impl/LoanUserServiceImpl.java @@ -3,7 +3,6 @@ package me.zhengjie.modules.loan.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; -import me.zhengjie.domain.Log; import me.zhengjie.exception.BadRequestException; import me.zhengjie.modules.loan.domain.LoanUser; import me.zhengjie.modules.loan.dto.LoanUserDTO; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployQueryCriteria.java b/eladmin-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployQueryCriteria.java index c404620..8e7c099 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployQueryCriteria.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployQueryCriteria.java @@ -17,23 +17,24 @@ package me.zhengjie.modules.mnt.service.dto; import lombok.Data; import me.zhengjie.annotation.Query; + import java.sql.Timestamp; import java.util.List; /** -* @author zhanghouying -* @date 2019-08-24 -*/ + * @author zhanghouying + * @date 2019-08-24 + */ @Data -public class DeployQueryCriteria{ +public class DeployQueryCriteria { - /** - * 模糊 - */ + /** + * 模糊 + */ @Query(type = Query.Type.INNER_LIKE, propName = "name", joinName = "app") private String appName; - @Query(type = Query.Type.BETWEEN) - private List createTime; + @Query(type = Query.Type.BETWEEN) + private List createTime; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/sms/util/SmsUtil.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/sms/util/SmsUtil.java index 45b9de6..9729d8f 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/sms/util/SmsUtil.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/sms/util/SmsUtil.java @@ -1,7 +1,9 @@ package me.zhengjie.modules.system.domain.sms.util; +import cn.hutool.core.codec.Base64; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest; @@ -137,6 +139,7 @@ public class SmsUtil { } public static void main(String[] args) { + System.out.println(Base64.decodeStr("MTc3MjQyNDU0MDY=")); String str = new String(" [\"13586541001\",\"13586541002\",\"13586541003\"]"); String[] split = str.split(","); ArrayList strings = Lists.newArrayList(Arrays.asList(split)); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/task/SaveToFileNewTask.java b/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/task/SaveToFileNewTask.java index d3f4a4c..5ec2d52 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/task/SaveToFileNewTask.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/task/SaveToFileNewTask.java @@ -5,7 +5,6 @@ import cn.hutool.core.codec.Base64; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.RandomUtil; -import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.extra.ssh.JschUtil; import cn.hutool.extra.ssh.Sftp; @@ -20,11 +19,9 @@ import com.google.common.collect.Sets; import com.jcraft.jsch.Session; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import me.zhengjie.constant.SmsConstant; import me.zhengjie.exception.BadRequestException; import me.zhengjie.modules.constant.DefaultConstant; import me.zhengjie.modules.constant.FileConstant; -import me.zhengjie.modules.system.domain.sms.dto.ShortLinkUrlDto; import me.zhengjie.modules.upload.task.model.ResponseEncryptJsonContent; import me.zhengjie.modules.upload.task.model.SendEncryptJsonContent; import me.zhengjie.modules.upload.task.model.SendRemoteUpdateJsonContent; @@ -33,7 +30,6 @@ import me.zhengjie.modules.uploadnew.consts.DecryptionJsonContent; import me.zhengjie.modules.uploadnew.domain.TbUploadFileNew; import me.zhengjie.modules.uploadnew.service.TbUploadFileNewService; import me.zhengjie.modules.uploadnew.service.dto.TbUploadFileNewDto; -import me.zhengjie.modules.uploadnew.util.ExcelUtils; import me.zhengjie.modules.uploadnew.util.ToolExcelUtils; import me.zhengjie.modules.uploadnew.util.TxtUtils; import me.zhengjie.utils.ConvertUtil; @@ -48,13 +44,14 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.time.LocalDateTime; import java.time.ZoneOffset; -import java.util.*; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import static me.zhengjie.modules.upload.consts.SysConst.*; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/util/AESUtils.java b/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/util/AESUtils.java new file mode 100644 index 0000000..b2ab052 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/util/AESUtils.java @@ -0,0 +1,239 @@ +package me.zhengjie.modules.uploadnew.util; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.symmetric.SymmetricAlgorithm; +import cn.hutool.crypto.symmetric.SymmetricCrypto; +import lombok.extern.slf4j.Slf4j; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; +import java.util.Base64; + +/** + * AES加解密 + */ +@Slf4j +public class AESUtils { + + /** + * 密钥长度: 128, 192 or 256 + */ + private static final int KEY_SIZE = 128; + + /** + * 加密/解密算法名称 + */ + private static final String ALGORITHM = "AES"; + + /** + * Key + */ + private static final String HEX = "0123456789ABCDEF"; + + /** + * 随机数生成器(RNG)算法名称 + */ + private static final String RNG_ALGORITHM = "SHA1PRNG"; + + /** + * 生成密钥对象 + */ + private static SecretKey generateKey(byte[] key) throws Exception { + // 创建安全随机数生成器 + SecureRandom random = SecureRandom.getInstance(RNG_ALGORITHM); + // 设置 密钥key的字节数组 作为安全随机数生成器的种子 + random.setSeed(key); + + // 创建 AES算法生成器 + KeyGenerator gen = KeyGenerator.getInstance(ALGORITHM); + // 初始化算法生成器 + gen.init(KEY_SIZE, random); + + // 生成 AES密钥对象, 也可以直接创建密钥对象: return new SecretKeySpec(key, ALGORITHM); + return gen.generateKey(); + } + + /** + * 数据加密: 明文 -> 密文 + */ + public static String encrypt(String plainBytes, String key) { + try { + // 生成密钥对象 + SecretKey secKey = generateKey(key.getBytes(StandardCharsets.UTF_8)); + + // 获取 AES 密码器 + Cipher cipher = Cipher.getInstance(ALGORITHM); + // 初始化密码器(加密模型) + cipher.init(Cipher.ENCRYPT_MODE, secKey); + + //数据反转加密 + String s = new StringBuilder(plainBytes).reverse().toString(); + // 加密数据, 返回密文 + byte[] cipherBytes = cipher.doFinal(s.getBytes(StandardCharsets.UTF_8)); + + //base64加密 + String str = Base64.getEncoder().encodeToString(cipherBytes); + return str; + } catch (Exception e) { + log.error("加密失败" + e.fillInStackTrace()); + return null; + } + + } + + /** + * 数据解密: 密文 -> 明文 + */ + public static String decrypt(String cipherBytes, String key) { + try { + // 生成密钥对象 + SecretKey secKey = generateKey(key.getBytes(StandardCharsets.UTF_8)); + + // 获取 AES 密码器 + Cipher cipher = Cipher.getInstance(ALGORITHM); + // 初始化密码器(解密模型) + cipher.init(Cipher.DECRYPT_MODE, secKey); + + //base64解密 + byte[] bytes = Base64.getDecoder().decode(cipherBytes); + + // 解密数据, 返回明文 + byte[] plainBytes = cipher.doFinal(bytes); + + //反转解密的结果返回 + return new StringBuilder(new String(plainBytes, StandardCharsets.UTF_8)).reverse().toString(); + } catch (Exception e) { + log.error("解密失败" + e.fillInStackTrace()); + return null; + } + } + + + /** + * 加密 + * + * @param str 加密之前的字符串 + * @return + */ + public static String encryptHex(String str, String key) { + + SymmetricCrypto aes = new SymmetricCrypto + (SymmetricAlgorithm.AES, + key.getBytes(StandardCharsets.UTF_8)); + return aes.encryptHex(str); + } + + /** + * 解密 + * + * @param str 加密后的字符串 + * @return + */ + public static String decryptStr(String str, String key) { + SymmetricCrypto aes = new SymmetricCrypto + (SymmetricAlgorithm.AES, + key.getBytes(StandardCharsets.UTF_8)); + return aes.decryptStr(str); + } + + + /** + * AES加密 + */ + public static String dbEncrypt(String seed, String cleartext) { + byte[] rawKey = getRawKey(seed.getBytes()); + byte[] result = encrypt(rawKey, cleartext.getBytes()); + return toHex(result); + } + + /** + * AES解密 + */ + public static String dbDecrypt(String seed, String encrypted) { + try { + byte[] rawKey = getRawKey(seed.getBytes()); + byte[] enc = toByte(encrypted); + byte[] result = decrypt(rawKey, enc); + return new String(result); + } catch (Exception e) { + return StrUtil.EMPTY; + } + } + + private static byte[] getRawKey(byte[] seed) { + try { + KeyGenerator kgen = KeyGenerator.getInstance(ALGORITHM); + SecureRandom sr = SecureRandom.getInstance(RNG_ALGORITHM); + sr.setSeed(seed); + // 192 and 256 bits may not be available + kgen.init(256, sr); + SecretKey skey = kgen.generateKey(); + return skey.getEncoded(); + } catch (Exception e) { + return new byte[0]; + } + } + + + private static byte[] encrypt(byte[] raw, byte[] clear) { + try { + SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITHM); + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, skeySpec); + return cipher.doFinal(clear); + } catch (Exception e) { + return new byte[0]; + } + } + + private static byte[] decrypt(byte[] raw, byte[] encrypted) { + SecretKeySpec skeSpec = new SecretKeySpec(raw, ALGORITHM); + try { + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, skeSpec); + return cipher.doFinal(encrypted); + } catch (Exception e) { + return new byte[0]; + } + } + + public static String toHex(String txt) { + return toHex(txt.getBytes()); + } + + public static String fromHex(String hex) { + return new String(toByte(hex)); + } + + public static byte[] toByte(String hexString) { + int len = hexString.length() >> 1; + + byte[] result = new byte[len]; + for (int i = 0; i < len; i++) { + result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); + } + return result; + } + + public static String toHex(byte[] buf) { + if (buf.length == 0) { + return StrUtil.EMPTY; + } + StringBuilder result = new StringBuilder(buf.length >> 1); + for (byte b : buf) { + appendHex(result, b); + } + return result.toString(); + } + + + private static void appendHex(StringBuilder sb, byte b) { + sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); + } + +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/util/ZipUtils.java b/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/util/ZipUtils.java index 38ff0ca..696cc78 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/util/ZipUtils.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/uploadnew/util/ZipUtils.java @@ -1,13 +1,23 @@ package me.zhengjie.modules.uploadnew.util; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.text.csv.CsvUtil; +import cn.hutool.core.text.csv.CsvWriter; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; +import me.zhengjie.modules.constant.FileConstant; +import me.zhengjie.modules.gender.config.properties.DeliveryProperties; import me.zhengjie.modules.uploadnew.service.dto.WavDTO; +import me.zhengjie.utils.CompressUtil; +import me.zhengjie.utils.MailUtil; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; +import java.io.File; import java.io.InputStream; import java.nio.charset.Charset; import java.util.ArrayList; @@ -53,4 +63,28 @@ public class ZipUtils { } return wavs; } + + + public static String zipFileAndSendGenderMail(List list, String file, String taskImeiName, DeliveryProperties deliveryProperties) { + // 保存文件 + String csvPath = file.concat(StrUtil.DOT).concat(FileConstant.CSV_FILE_SUB_NAME); + String zipPath = file.concat(StrUtil.DOT).concat(FileConstant.ZIP_FILE_SUB_NAME); + //构造文件 + File csvFile = new File(csvPath); + //设置导出字符类型, CHARSET_UTF_8 + CsvWriter csvWriter = new CsvWriter(csvFile, CharsetUtil.CHARSET_UTF_8); + csvWriter.write(list); + csvWriter.close(); + // 设置压缩文件 + CompressUtil.decryptionCompression + (zipPath, csvPath, deliveryProperties.getZipPassword()); + MailUtil.sendMail(deliveryProperties.getGenderEmailAddress(), + deliveryProperties.getEmailPassword(), deliveryProperties.getToGenderEmailAddress(), zipPath, taskImeiName); + boolean zipResult = FileUtil.del(zipPath); + boolean csvResult = FileUtil.del(csvPath); + log.info("=========================== the csv path as {}, " + + "zip path as {} csvResult as {} zipResult as {} ========================", + csvPath, zipPath, csvResult, zipResult); + return zipPath; + } } diff --git a/eladmin-system/src/main/resources/config/application-prod.yml b/eladmin-system/src/main/resources/config/application-prod.yml index 643660a..930ddc1 100644 --- a/eladmin-system/src/main/resources/config/application-prod.yml +++ b/eladmin-system/src/main/resources/config/application-prod.yml @@ -153,3 +153,12 @@ rdsFileRecord: link: downloadUrl: http://116.62.197.152:8000/api/tempFileRecord/downloadFile reqUrl: http://116.62.197.152:8000/api/temp/file/link/nofile?filePath= + +gender: + emailPassword: baiye2022 + fileUrl: /home/eladmin/mail + zipPassword: DB2022hjk213v1... + emailAddress: ensoze@outlook.com + downPath: https://xx.tuoz.net/mail/down/ + genderEmailAddress: ensoze2023@outlook.com + toGenderEmailAddress: ggggod_2022@outlook.com diff --git a/eladmin-tools/pom.xml b/eladmin-tools/pom.xml index 61b1f6d..4282d42 100644 --- a/eladmin-tools/pom.xml +++ b/eladmin-tools/pom.xml @@ -13,7 +13,7 @@ 工具模块 - 1.5.0-b01 + 1.6.2 [7.2.0, 7.2.99] 4.9.153.ALL @@ -28,8 +28,8 @@ - javax.mail - mail + com.sun.mail + javax.mail ${mail.version} @@ -47,4 +47,4 @@ ${alipay.version} - \ No newline at end of file + diff --git a/eladmin-tools/src/main/java/me/zhengjie/utils/MailUtil.java b/eladmin-tools/src/main/java/me/zhengjie/utils/MailUtil.java index 975b121..81b90dc 100644 --- a/eladmin-tools/src/main/java/me/zhengjie/utils/MailUtil.java +++ b/eladmin-tools/src/main/java/me/zhengjie/utils/MailUtil.java @@ -41,6 +41,7 @@ public class MailUtil { Properties props = System.getProperties(); //设置电子邮件协议 props.setProperty("mail.store.protocol", "imaps"); + props.setProperty("mail.smtp.ssl.protocols", "TLSv1.2"); try { Session session = Session.getDefaultInstance(props, null); Store store = session.getStore("imaps"); @@ -54,11 +55,13 @@ public class MailUtil { throw new BadRequestException("没有找到该服务"); } catch (MessagingException e) { log.error("======================= open mail error time {} message as {} ==================", DateUtil.date(), e.getMessage()); - throw new BadRequestException("发送邮件失败"); + throw new BadRequestException("接收邮件失败"); } return list; } + + /** * 创建一封复杂邮件(文本+图片+附件) */ @@ -182,7 +185,7 @@ public class MailUtil { } - public static boolean sendEmail(String sender, String password, String host, String port, String receiver,String subject,String content) { + public static boolean sendEmail(String sender, String password, String host, String port, String receiver, String subject, String content) { try { @@ -223,7 +226,6 @@ public class MailUtil { multipart.addBodyPart(textPart); - msg.setContent(multipart); Transport transport = session.getTransport(); @@ -241,6 +243,85 @@ public class MailUtil { } } + /** + * 获得邮件发件人 + * + * @param msg 邮件内容 + * @return + * @throws MessagingException + * @throws UnsupportedEncodingException + */ + public static String getFrom(MimeMessage msg) throws MessagingException { + Address[] froms = msg.getFrom(); + if (froms.length < 1) + throw new MessagingException("没有发件人!"); + InternetAddress address = (InternetAddress) froms[0]; + return address.getAddress(); + } + + public static String saveAttachMent(Part part, String path) throws Exception { + String fileName; + if (part.isMimeType("multipart/*")) { + Multipart mp = (Multipart) part.getContent(); + for (int i = 0; i < mp.getCount(); i++) { + BodyPart mpart = mp.getBodyPart(i); + String disposition = mpart.getDisposition(); + if ((disposition != null) && + ((disposition.equals(Part.ATTACHMENT)) || (disposition.equals(Part.INLINE)))) { + fileName = mpart.getFileName(); + if (fileName.toLowerCase().contains("gb2312")) { + fileName = MimeUtility.decodeText(fileName); + } + return saveFile(fileName, mpart.getInputStream(), path); + } else if (mpart.isMimeType("multipart/*")) { + saveAttachMent(mpart, path); + } else { + fileName = mpart.getFileName(); + if ((fileName != null) && (fileName.toLowerCase().contains("GB2312"))) { + fileName = MimeUtility.decodeText(fileName); + return saveFile(fileName, mpart.getInputStream(), path); + } + } + } + } else if (part.isMimeType("message/rfc822")) { + saveAttachMent((Part) part.getContent(), path); + } + return StrUtil.EMPTY; + } + + + /** + * 【真正的保存附件到指定目录里】 + */ + private static String saveFile(String fileName, InputStream in, String path) { + + String osName = System.getProperty("os.name"); + File file = new File(path); + if (!file.exists()) { + file.mkdirs(); + } + String separator; + if (osName == null) { + osName = ""; + } + if (osName.toLowerCase().contains("win")) { + separator = "\\"; + } else { + separator = "/"; + } + File storeFile = new File(path + separator + fileName); + try (BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(storeFile.toPath())); + BufferedInputStream bis = new BufferedInputStream(in)) { + int c; + while ((c = bis.read()) != -1) { + bos.write(c); + bos.flush(); + } + } catch (Exception exception) { + throw new BadRequestException("文件保存失败!"); + } + return storeFile.getPath(); + } }