作者 钟来

初始提交

正在显示 37 个修改的文件 包含 4292 行增加0 行删除

要显示太多修改。

为保证性能只显示 37 of 37+ 个文件。

  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <modelVersion>4.0.0</modelVersion>
  6 + <parent>
  7 + <groupId>com.zhonglai.luhui</groupId>
  8 + <artifactId>lh-common</artifactId>
  9 + <version>1.0.0</version>
  10 + </parent>
  11 +
  12 + <artifactId>lh-common-util</artifactId>
  13 + <description>核心工具</description>
  14 +
  15 + <properties>
  16 + <maven.compiler.source>8</maven.compiler.source>
  17 + <maven.compiler.target>8</maven.compiler.target>
  18 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  19 + </properties>
  20 +
  21 + <dependencies>
  22 + <dependency>
  23 + <groupId>jakarta.validation</groupId>
  24 + <artifactId>jakarta.validation-api</artifactId>
  25 + </dependency>
  26 + <!-- 文件上传工具类 -->
  27 + <dependency>
  28 + <groupId>commons-fileupload</groupId>
  29 + <artifactId>commons-fileupload</artifactId>
  30 + </dependency>
  31 + <!--常用工具类 -->
  32 + <dependency>
  33 + <groupId>org.apache.commons</groupId>
  34 + <artifactId>commons-lang3</artifactId>
  35 + </dependency>
  36 +
  37 + <dependency>
  38 + <groupId>com.google.code.gson</groupId>
  39 + <artifactId>gson</artifactId>
  40 + </dependency>
  41 +
  42 + <dependency>
  43 + <groupId>cn.hutool</groupId>
  44 + <artifactId>hutool-all</artifactId>
  45 + </dependency>
  46 +
  47 + <!-- 阿里JSON解析器 -->
  48 + <dependency>
  49 + <groupId>com.alibaba</groupId>
  50 + <artifactId>fastjson</artifactId>
  51 + </dependency>
  52 + </dependencies>
  53 +</project>
  1 +package com.zhonglai.luhui.util;
  2 +
  3 +import java.math.BigDecimal;
  4 +import java.math.RoundingMode;
  5 +
  6 +/**
  7 + * 精确的浮点数运算
  8 + *
  9 + * @author ruoyi
  10 + */
  11 +public class Arith
  12 +{
  13 +
  14 + /** 默认除法运算精度 */
  15 + private static final int DEF_DIV_SCALE = 10;
  16 +
  17 + /** 这个类不能实例化 */
  18 + private Arith()
  19 + {
  20 + }
  21 +
  22 + /**
  23 + * 提供精确的加法运算。
  24 + * @param v1 被加数
  25 + * @param v2 加数
  26 + * @return 两个参数的和
  27 + */
  28 + public static double add(double v1, double v2)
  29 + {
  30 + BigDecimal b1 = new BigDecimal(Double.toString(v1));
  31 + BigDecimal b2 = new BigDecimal(Double.toString(v2));
  32 + return b1.add(b2).doubleValue();
  33 + }
  34 +
  35 + /**
  36 + * 提供精确的减法运算。
  37 + * @param v1 被减数
  38 + * @param v2 减数
  39 + * @return 两个参数的差
  40 + */
  41 + public static double sub(double v1, double v2)
  42 + {
  43 + BigDecimal b1 = new BigDecimal(Double.toString(v1));
  44 + BigDecimal b2 = new BigDecimal(Double.toString(v2));
  45 + return b1.subtract(b2).doubleValue();
  46 + }
  47 +
  48 + /**
  49 + * 提供精确的乘法运算。
  50 + * @param v1 被乘数
  51 + * @param v2 乘数
  52 + * @return 两个参数的积
  53 + */
  54 + public static double mul(double v1, double v2)
  55 + {
  56 + BigDecimal b1 = new BigDecimal(Double.toString(v1));
  57 + BigDecimal b2 = new BigDecimal(Double.toString(v2));
  58 + return b1.multiply(b2).doubleValue();
  59 + }
  60 +
  61 + /**
  62 + * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
  63 + * 小数点以后10位,以后的数字四舍五入。
  64 + * @param v1 被除数
  65 + * @param v2 除数
  66 + * @return 两个参数的商
  67 + */
  68 + public static double div(double v1, double v2)
  69 + {
  70 + return div(v1, v2, DEF_DIV_SCALE);
  71 + }
  72 +
  73 + /**
  74 + * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
  75 + * 定精度,以后的数字四舍五入。
  76 + * @param v1 被除数
  77 + * @param v2 除数
  78 + * @param scale 表示表示需要精确到小数点以后几位。
  79 + * @return 两个参数的商
  80 + */
  81 + public static double div(double v1, double v2, int scale)
  82 + {
  83 + if (scale < 0)
  84 + {
  85 + throw new IllegalArgumentException(
  86 + "The scale must be a positive integer or zero");
  87 + }
  88 + BigDecimal b1 = new BigDecimal(Double.toString(v1));
  89 + BigDecimal b2 = new BigDecimal(Double.toString(v2));
  90 + if (b1.compareTo(BigDecimal.ZERO) == 0)
  91 + {
  92 + return BigDecimal.ZERO.doubleValue();
  93 + }
  94 + return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
  95 + }
  96 +
  97 + /**
  98 + * 提供精确的小数位四舍五入处理。
  99 + * @param v 需要四舍五入的数字
  100 + * @param scale 小数点后保留几位
  101 + * @return 四舍五入后的结果
  102 + */
  103 + public static double round(double v, int scale)
  104 + {
  105 + if (scale < 0)
  106 + {
  107 + throw new IllegalArgumentException(
  108 + "The scale must be a positive integer or zero");
  109 + }
  110 + BigDecimal b = new BigDecimal(Double.toString(v));
  111 + BigDecimal one = BigDecimal.ONE;
  112 + return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
  113 + }
  114 +}
  1 +package com.zhonglai.luhui.util;
  2 +
  3 +import java.util.Arrays;
  4 +
  5 +public class ByteUtil {
  6 + /**
  7 + * byte数组中取int数值,本方法适用于(低位在前,高位在后)的顺序,和和intToBytes()配套使用
  8 + *
  9 + * @param src
  10 + * byte数组
  11 + * @param offset
  12 + * 从数组的第offset位开始
  13 + * @return int数值
  14 + */
  15 + public static long bytesToLongASC(byte[] src, int offset,int lenth) {
  16 + int value = 0;
  17 + for(int i=0;i<lenth;i++)
  18 + {
  19 + value = value | ((src[offset+i] & 0xFF)<<(8*i));
  20 + }
  21 + return value;
  22 + }
  23 +
  24 + /**
  25 + * 把16进制字符串转换成字节数组
  26 + *
  27 + * @param hex
  28 + * @return
  29 + */
  30 + public static byte[] hexStringToByte(String hex) {
  31 + int len = (hex.length() / 2);
  32 + byte[] result = new byte[len];
  33 + char[] achar = hex.toCharArray();
  34 + for (int i = 0; i < len; i++) {
  35 + int pos = i * 2;
  36 + result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
  37 + }
  38 + return result;
  39 + }
  40 + private static byte toByte(char c) {
  41 + byte b = (byte) "0123456789ABCDEF".indexOf(c);
  42 + return b;
  43 + }
  44 +
  45 + /**
  46 + * 把16进制字符串转换成字节数组
  47 + *
  48 + * @param hex
  49 + * @return
  50 + */
  51 + public static String hexStringToSpace(String hex) {
  52 + if (null == hex) {
  53 + return null;
  54 + } else {
  55 + StringBuilder sb = new StringBuilder(hex.length() << 1);
  56 +
  57 + for(int i = 0; i < hex.length(); i+=2) {
  58 + sb.append(hex.substring(i,i+2)).append(" ");
  59 + }
  60 + return sb.toString();
  61 + }
  62 + }
  63 +
  64 + /**
  65 + * 把原数组加点目标数组后面
  66 + * @param dest 目标数组
  67 + * @param src 原数组
  68 + * @return
  69 + */
  70 + public static byte[] addBytes(byte[] dest,byte[] src )
  71 + {
  72 + int dl = dest.length;
  73 + int sl = src.length;
  74 + dest = Arrays.copyOf(dest, dl+sl);//数组扩容
  75 + System.arraycopy(src,0,dest,dl,src.length);
  76 + return dest;
  77 + }
  78 +
  79 + /**
  80 + * 将int数值转换为占四个字节的byte数组,本方法适用于(高位在前,低位在后)的顺序。 和bytesToInt2()配套使用
  81 + */
  82 + public static byte[] intToBytesDESC(long value,int lenth)
  83 + {
  84 + byte[] src = new byte[lenth];
  85 + for(int i=0;i<lenth;i++)
  86 + {
  87 + src[i] = (byte) ((value>>(8*(lenth-i-1))) & 0xFF);
  88 + }
  89 + return src;
  90 + }
  91 +
  92 + /**
  93 + * 将int数值转换为占四个字节的byte数组,本方法适用于(低位在前,高位在后)的顺序。 和bytesToInt()配套使用
  94 + * @param value
  95 + * 要转换的int值
  96 + * @return byte数组
  97 + */
  98 + public static byte[] intToBytesASC( long value,int lenth)
  99 + {
  100 + byte[] src = new byte[lenth];
  101 + for(int i=lenth;i>0;i--)
  102 + {
  103 + src[i-1] = (byte) ((value>>(8*(i-1))) & 0xFF);
  104 + }
  105 + return src;
  106 + }
  107 +
  108 + public static void main(String[] args) {
  109 + System.out.println(ByteUtil.toHexString( ByteUtil.intToBytesASC(2011239256,4)));
  110 + }
  111 +
  112 + /**
  113 + * ip转化位4byte
  114 + * @param ip
  115 + * @return
  116 + */
  117 + public static byte[] ipTo4Byte(String ip)
  118 + {
  119 + String[] ips = ip.split(".");
  120 + return new byte[]{(byte) Integer.parseInt(ips[0]),(byte) Integer.parseInt(ips[1]),(byte) Integer.parseInt(ips[2]),(byte) Integer.parseInt(ips[3])};
  121 + }
  122 +
  123 + /**
  124 + * byte数组中取int数值,本方法适用于(低位在后,高位在前)的顺序。和intToBytes2()配套使用
  125 + */
  126 + public static long bytesToLongDESC(byte[] src, int offset,int lenth) {
  127 + long value = 0;
  128 + for(int i=lenth;i>0;i--)
  129 + {
  130 + value = value | ((src[offset+(lenth-i)] & 0xFF)<<(8*(i-1)));
  131 + }
  132 + return value;
  133 + }
  134 +
  135 + private static final char[] hex = "0123456789abcdef".toCharArray();
  136 + public static String toHexString(byte[] bytes) {
  137 + if (null == bytes) {
  138 + return null;
  139 + } else {
  140 + StringBuilder sb = new StringBuilder(bytes.length << 1);
  141 +
  142 + for(int i = 0; i < bytes.length; ++i) {
  143 + sb.append(hex[(bytes[i] & 240) >> 4]).append(hex[bytes[i] & 15]);
  144 + }
  145 +
  146 + return sb.toString();
  147 + }
  148 + }
  149 +
  150 + /**
  151 + * 计算CRC16/Modbus校验码 低位在前,高位在后
  152 + *
  153 + * @param str 十六进制字符串
  154 + * @return
  155 + */
  156 + public static String getCRC16(String str) {
  157 + byte[] bytes = hexStringToByte(str);
  158 + return getCRC16(bytes);
  159 + }
  160 +
  161 + /**
  162 + * 计算CRC16/Modbus校验码 低位在前,高位在后
  163 + *
  164 + * @return
  165 + */
  166 + public static String getCRC16( byte[] bytes) {
  167 + int CRC = 0x0000ffff;
  168 + int POLYNOMIAL = 0x0000a001;
  169 +
  170 + int i, j;
  171 + for (i = 0; i < bytes.length; i++) {
  172 + CRC ^= ((int) bytes[i] & 0x000000ff);
  173 + for (j = 0; j < 8; j++) {
  174 + if ((CRC & 0x00000001) != 0) {
  175 + CRC >>= 1;
  176 + CRC ^= POLYNOMIAL;
  177 + } else {
  178 + CRC >>= 1;
  179 + }
  180 + }
  181 + }
  182 + String crc = Integer.toHexString(CRC);
  183 + if (crc.length() == 2) {
  184 + crc = "00" + crc;
  185 + } else if (crc.length() == 3) {
  186 + crc = "0" + crc;
  187 + }
  188 + crc = crc.substring(2, 4) + crc.substring(0, 2);
  189 + return crc.toUpperCase();
  190 + }
  191 +
  192 + /**
  193 + * 用于从一个 long 值中指定的起始位置和结束位置读取位数据。该方法使用位掩码操作来获取指定位范围内的数据。
  194 + * @param value
  195 + * @param startPosition
  196 + * @param endPosition
  197 + * @return
  198 + */
  199 + public static long readBits(long value, int startPosition, int endPosition) {
  200 + long mask = (1L << (endPosition - startPosition + 1)) - 1;
  201 + return (value >> startPosition) & mask;
  202 + }
  203 +
  204 + /**
  205 + * 用于简化给变量的不同位赋值的操作。该方法接收四个参数:value 是要被赋值的变量,bitValue 是要赋给指定位的值,startPosition 和 endPosition 是指定位的起始位置和结束位置。
  206 + * @param value
  207 + * @param bitValue
  208 + * @param startPosition
  209 + * @param endPosition
  210 + * @return
  211 + */
  212 + public static int assignBits(int value, int bitValue, int startPosition, int endPosition) {
  213 + int mask = ((1 << (endPosition - startPosition + 1)) - 1) << startPosition;
  214 + value &= ~mask;
  215 + value |= (bitValue << startPosition);
  216 + return value;
  217 + }
  218 +
  219 +}
  1 +package com.zhonglai.luhui.util;
  2 +
  3 +import org.apache.commons.lang3.StringUtils;
  4 +
  5 +import javax.crypto.Cipher;
  6 +import javax.crypto.SecretKey;
  7 +import javax.crypto.SecretKeyFactory;
  8 +import javax.crypto.spec.DESKeySpec;
  9 +import java.security.SecureRandom;
  10 +import java.util.Random;
  11 +
  12 +/**
  13 + * 采用MD5加密解密
  14 + * @author tfq
  15 + * @datetime 2011-10-13
  16 + */
  17 +public class DESUtil {
  18 +
  19 + private static final String KEY = "kimwaynet";// 密钥
  20 + private final static String DES = "DES";// DES算法名称
  21 +
  22 + //加密
  23 + private static byte[] encrypt(byte[] src, byte[] key) throws Exception {
  24 + SecureRandom sr = new SecureRandom();
  25 + DESKeySpec dks = new DESKeySpec(key);
  26 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
  27 + SecretKey securekey = keyFactory.generateSecret(dks);
  28 + Cipher cipher = Cipher.getInstance(DES);
  29 + cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
  30 + return cipher.doFinal(src);
  31 + }
  32 +
  33 + //解密
  34 + private static byte[] decrypt(byte[] src, byte[] key) throws Exception {
  35 + SecureRandom sr = new SecureRandom();
  36 + DESKeySpec dks = new DESKeySpec(key);
  37 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
  38 + SecretKey securekey = keyFactory.generateSecret(dks);
  39 + Cipher cipher = Cipher.getInstance(DES);
  40 + cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
  41 + return cipher.doFinal(src);
  42 + }
  43 +
  44 + private static String byte2hex(byte[] b) {
  45 + String hs = "";
  46 + String stmp = "";
  47 + for (int n = 0; n < b.length; n++) {
  48 + stmp = (Integer.toHexString(b[n] & 0XFF));
  49 + if (stmp.length() == 1)
  50 + hs = hs + "0" + stmp;
  51 + else
  52 + hs = hs + stmp;
  53 + }
  54 + return hs.toUpperCase();
  55 +
  56 + }
  57 + private static byte[] hex2byte(byte[] b) {
  58 + if ((b.length % 2) != 0)
  59 + throw new IllegalArgumentException("length not even");
  60 + byte[] b2 = new byte[b.length / 2];
  61 + for (int n = 0; n < b.length; n += 2) {
  62 + String item = new String(b, n, 2);
  63 + b2[n / 2] = (byte) Integer.parseInt(item, 16);
  64 + }
  65 + return b2;
  66 + }
  67 +
  68 + //解密
  69 + public static String decode(String src,String key) {
  70 + if(StringUtils.isEmpty(key))
  71 + {
  72 + key = KEY;
  73 + }
  74 + String decryptStr = "";
  75 + try {
  76 + decryptStr = new String(decrypt(hex2byte(src.getBytes()),key.getBytes()));
  77 + } catch (Exception ex) {
  78 + ex.printStackTrace();
  79 + }
  80 + return decryptStr;
  81 + }
  82 +
  83 + //加密
  84 + public static String encode(String src,String key){
  85 + if(StringUtils.isEmpty(key))
  86 + {
  87 + key = KEY;
  88 + }
  89 + byte[] bytes = null;
  90 + String encryptStr = "";
  91 + try {
  92 + bytes = encrypt(src.getBytes(), key.getBytes());
  93 + } catch (Exception ex) {
  94 + ex.printStackTrace();
  95 + }
  96 + if (bytes != null)
  97 + encryptStr = byte2hex(bytes);
  98 + return encryptStr;
  99 + }
  100 +
  101 + public static String getDecodeMAC(String decryptStr){
  102 + String mac = "";
  103 + String[] strs = decryptStr.split(":");
  104 + if (strs.length == 5) {
  105 + mac = strs[0];
  106 + }
  107 + return mac;
  108 + }
  109 +
  110 + /**
  111 + * 生成指定长度的随机字符串
  112 + * @param args
  113 + */
  114 + /**
  115 + * 产生随机字符串
  116 + * */
  117 + private static Random randGen = null;
  118 + private static char[] numbersAndLetters = null;
  119 +
  120 + public static final String randomString(int length) {
  121 + if (length < 1) {
  122 + return null;
  123 + }
  124 + if (randGen == null) {
  125 + randGen = new Random();
  126 + numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" +
  127 + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
  128 + //numbersAndLetters = ("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
  129 + }
  130 + char [] randBuffer = new char[length];
  131 + for (int i=0; i<randBuffer.length; i++) {
  132 + randBuffer[i] = numbersAndLetters[randGen.nextInt(71)];
  133 + //randBuffer[i] = numbersAndLetters[randGen.nextInt(35)];
  134 + }
  135 + return new String(randBuffer);
  136 + }
  137 +
  138 + // 测试主函数
  139 + public static void main(String args[]) {
  140 +// String s = new String("F:/yu2le-service-log");
  141 +// System.out.println("原始:" + s);
  142 +// s = encode(s,"LINUXYU2LE");
  143 +// System.out.println("加密的:" + s);
  144 + System.out.println("解密的:" + decode("498CFDA0AA8A2E9A","kimwaynet"));
  145 +
  146 +// System.out.println(encode("13912927204","LS6GzB"));
  147 + }
  148 +}
  1 +package com.zhonglai.luhui.util;
  2 +
  3 +import org.apache.commons.lang3.time.DateFormatUtils;
  4 +
  5 +import java.lang.management.ManagementFactory;
  6 +import java.text.ParseException;
  7 +import java.text.SimpleDateFormat;
  8 +import java.time.*;
  9 +import java.util.Date;
  10 +
  11 +/**
  12 + * 时间工具类
  13 + *
  14 + * @author ruoyi
  15 + */
  16 +public class DateUtils extends org.apache.commons.lang3.time.DateUtils
  17 +{
  18 + public static String YYYY = "yyyy";
  19 +
  20 + public static String YYYY_MM = "yyyy-MM";
  21 +
  22 + public static String YYYY_MM_DD = "yyyy-MM-dd";
  23 +
  24 + public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
  25 +
  26 + public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
  27 +
  28 + private static String[] parsePatterns = {
  29 + "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
  30 + "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
  31 + "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
  32 +
  33 + /**
  34 + * 获取当前Date型日期
  35 + *
  36 + * @return Date() 当前日期
  37 + */
  38 + public static Date getNowDate()
  39 + {
  40 + return new Date();
  41 + }
  42 +
  43 + /**
  44 + * 获取当前日期, 默认格式为yyyy-MM-dd
  45 + *
  46 + * @return String
  47 + */
  48 + public static String getDate()
  49 + {
  50 + return dateTimeNow(YYYY_MM_DD);
  51 + }
  52 +
  53 + public static final String getTime()
  54 + {
  55 + return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
  56 + }
  57 +
  58 + public static final String dateTimeNow()
  59 + {
  60 + return dateTimeNow(YYYYMMDDHHMMSS);
  61 + }
  62 +
  63 + public static final String dateTimeNow(final String format)
  64 + {
  65 + return parseDateToStr(format, new Date());
  66 + }
  67 +
  68 + public static final String dateTime(final Date date)
  69 + {
  70 + return parseDateToStr(YYYY_MM_DD, date);
  71 + }
  72 +
  73 + public static final String parseDateToStr(final String format, final Date date)
  74 + {
  75 + return new SimpleDateFormat(format).format(date);
  76 + }
  77 +
  78 + public static final Date dateTime(final String format, final String ts)
  79 + {
  80 + try
  81 + {
  82 + return new SimpleDateFormat(format).parse(ts);
  83 + }
  84 + catch (ParseException e)
  85 + {
  86 + throw new RuntimeException(e);
  87 + }
  88 + }
  89 +
  90 + /**
  91 + * 日期路径 即年/月/日 如2018/08/08
  92 + */
  93 + public static final String datePath()
  94 + {
  95 + Date now = new Date();
  96 + return DateFormatUtils.format(now, "yyyy/MM/dd");
  97 + }
  98 +
  99 + /**
  100 + * 日期路径 即年/月/日 如20180808
  101 + */
  102 + public static final String dateTime()
  103 + {
  104 + Date now = new Date();
  105 + return DateFormatUtils.format(now, "yyyyMMdd");
  106 + }
  107 +
  108 + /**
  109 + * 日期型字符串转化为日期 格式
  110 + */
  111 + public static Date parseDate(Object str)
  112 + {
  113 + if (str == null)
  114 + {
  115 + return null;
  116 + }
  117 + try
  118 + {
  119 + return parseDate(str.toString(), parsePatterns);
  120 + }
  121 + catch (ParseException e)
  122 + {
  123 + return null;
  124 + }
  125 + }
  126 +
  127 + /**
  128 + * 获取服务器启动时间
  129 + */
  130 + public static Date getServerStartDate()
  131 + {
  132 + long time = ManagementFactory.getRuntimeMXBean().getStartTime();
  133 + return new Date(time);
  134 + }
  135 +
  136 + /**
  137 + * 计算相差天数
  138 + */
  139 + public static int differentDaysByMillisecond(Date date1, Date date2)
  140 + {
  141 + return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
  142 + }
  143 +
  144 + /**
  145 + * 计算两个时间差
  146 + */
  147 + public static String getDatePoor(Date endDate, Date nowDate)
  148 + {
  149 + long nd = 1000 * 24 * 60 * 60;
  150 + long nh = 1000 * 60 * 60;
  151 + long nm = 1000 * 60;
  152 + // long ns = 1000;
  153 + // 获得两个时间的毫秒时间差异
  154 + long diff = endDate.getTime() - nowDate.getTime();
  155 + // 计算差多少天
  156 + long day = diff / nd;
  157 + // 计算差多少小时
  158 + long hour = diff % nd / nh;
  159 + // 计算差多少分钟
  160 + long min = diff % nd % nh / nm;
  161 + // 计算差多少秒//输出结果
  162 + // long sec = diff % nd % nh % nm / ns;
  163 + return day + "天" + hour + "小时" + min + "分钟";
  164 + }
  165 +
  166 + /**
  167 + * 增加 LocalDateTime ==> Date
  168 + */
  169 + public static Date toDate(LocalDateTime temporalAccessor)
  170 + {
  171 + ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
  172 + return Date.from(zdt.toInstant());
  173 + }
  174 +
  175 + /**
  176 + * 增加 LocalDate ==> Date
  177 + */
  178 + public static Date toDate(LocalDate temporalAccessor)
  179 + {
  180 + LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
  181 + ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
  182 + return Date.from(zdt.toInstant());
  183 + }
  184 +
  185 + public static Integer getNowTimeMilly() {
  186 + String time = System.currentTimeMillis() / 1000L + "";
  187 + return Integer.parseInt(time);
  188 + }
  189 +}
  1 +package com.zhonglai.luhui.util;
  2 +
  3 +import org.apache.commons.lang3.StringUtils;
  4 +import org.apache.commons.lang3.exception.ExceptionUtils;
  5 +
  6 +import java.io.PrintWriter;
  7 +import java.io.StringWriter;
  8 +
  9 +/**
  10 + * 错误信息处理类。
  11 + *
  12 + * @author ruoyi
  13 + */
  14 +public class ExceptionUtil
  15 +{
  16 + /**
  17 + * 获取exception的详细错误信息。
  18 + */
  19 + public static String getExceptionMessage(Throwable e)
  20 + {
  21 + StringWriter sw = new StringWriter();
  22 + e.printStackTrace(new PrintWriter(sw, true));
  23 + return sw.toString();
  24 + }
  25 +
  26 + public static String getRootErrorMessage(Exception e)
  27 + {
  28 + Throwable root = ExceptionUtils.getRootCause(e);
  29 + root = (root == null ? e : root);
  30 + if (root == null)
  31 + {
  32 + return "";
  33 + }
  34 + String msg = root.getMessage();
  35 + if (msg == null)
  36 + {
  37 + return "null";
  38 + }
  39 + return StringUtils.defaultString(msg);
  40 + }
  41 +}
  1 +package com.zhonglai.luhui.util;
  2 +
  3 +import com.google.gson.FieldNamingPolicy;
  4 +import com.google.gson.Gson;
  5 +import com.google.gson.GsonBuilder;
  6 +
  7 +public class GsonConstructor {
  8 + private static final Gson gson;
  9 +
  10 + public GsonConstructor() {
  11 + }
  12 +
  13 + public static final Gson get() {
  14 + return gson;
  15 + }
  16 +
  17 + static {
  18 + gson = (new GsonBuilder()).setVersion(1.0D).disableInnerClassSerialization().setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).setDateFormat("yyyy-MM-dd").create();
  19 + }
  20 +}
  1 +package com.zhonglai.luhui.util;
  2 +
  3 +/**
  4 + * 处理并记录日志文件
  5 + *
  6 + * @author ruoyi
  7 + */
  8 +public class LogUtils
  9 +{
  10 + public static String getBlock(Object msg)
  11 + {
  12 + if (msg == null)
  13 + {
  14 + msg = "";
  15 + }
  16 + return "[" + msg.toString() + "]";
  17 + }
  18 +}
  1 +package com.zhonglai.luhui.util;
  2 +
  3 +import cn.hutool.core.text.StrFormatter;
  4 +
  5 +import java.util.*;
  6 +
  7 +/**
  8 + * 字符串工具类
  9 + *
  10 + * @author ruoyi
  11 + */
  12 +public class StringUtils extends org.apache.commons.lang3.StringUtils
  13 +{
  14 + /** 空字符串 */
  15 + private static final String NULLSTR = "";
  16 +
  17 + /** 下划线 */
  18 + private static final char SEPARATOR = '_';
  19 +
  20 + /**
  21 + * 获取参数不为空值
  22 + *
  23 + * @param value defaultValue 要判断的value
  24 + * @return value 返回值
  25 + */
  26 + public static <T> T nvl(T value, T defaultValue)
  27 + {
  28 + return value != null ? value : defaultValue;
  29 + }
  30 +
  31 + /**
  32 + * * 判断一个Collection是否为空, 包含List,Set,Queue
  33 + *
  34 + * @param coll 要判断的Collection
  35 + * @return true:为空 false:非空
  36 + */
  37 + public static boolean isEmpty(Collection<?> coll)
  38 + {
  39 + return isNull(coll) || coll.isEmpty();
  40 + }
  41 +
  42 + /**
  43 + * * 判断一个Collection是否非空,包含List,Set,Queue
  44 + *
  45 + * @param coll 要判断的Collection
  46 + * @return true:非空 false:空
  47 + */
  48 + public static boolean isNotEmpty(Collection<?> coll)
  49 + {
  50 + return !isEmpty(coll);
  51 + }
  52 +
  53 + /**
  54 + * * 判断一个对象数组是否为空
  55 + *
  56 + * @param objects 要判断的对象数组
  57 + ** @return true:为空 false:非空
  58 + */
  59 + public static boolean isEmpty(Object[] objects)
  60 + {
  61 + return isNull(objects) || (objects.length == 0);
  62 + }
  63 +
  64 + /**
  65 + * * 判断一个对象数组是否非空
  66 + *
  67 + * @param objects 要判断的对象数组
  68 + * @return true:非空 false:空
  69 + */
  70 + public static boolean isNotEmpty(Object[] objects)
  71 + {
  72 + return !isEmpty(objects);
  73 + }
  74 +
  75 + /**
  76 + * * 判断一个Map是否为空
  77 + *
  78 + * @param map 要判断的Map
  79 + * @return true:为空 false:非空
  80 + */
  81 + public static boolean isEmpty(Map<?, ?> map)
  82 + {
  83 + return isNull(map) || map.isEmpty();
  84 + }
  85 +
  86 + /**
  87 + * * 判断一个Map是否为空
  88 + *
  89 + * @param map 要判断的Map
  90 + * @return true:非空 false:空
  91 + */
  92 + public static boolean isNotEmpty(Map<?, ?> map)
  93 + {
  94 + return !isEmpty(map);
  95 + }
  96 +
  97 + /**
  98 + * * 判断一个字符串是否为空串
  99 + *
  100 + * @param str String
  101 + * @return true:为空 false:非空
  102 + */
  103 + public static boolean isEmpty(String str)
  104 + {
  105 + return isNull(str) || NULLSTR.equals(str.trim());
  106 + }
  107 +
  108 + /**
  109 + * * 判断一个字符串是否为非空串
  110 + *
  111 + * @param str String
  112 + * @return true:非空串 false:空串
  113 + */
  114 + public static boolean isNotEmpty(String str)
  115 + {
  116 + return !isEmpty(str);
  117 + }
  118 +
  119 + /**
  120 + * * 判断一个对象是否为空
  121 + *
  122 + * @param object Object
  123 + * @return true:为空 false:非空
  124 + */
  125 + public static boolean isNull(Object object)
  126 + {
  127 + return object == null;
  128 + }
  129 +
  130 + /**
  131 + * * 判断一个对象是否非空
  132 + *
  133 + * @param object Object
  134 + * @return true:非空 false:空
  135 + */
  136 + public static boolean isNotNull(Object object)
  137 + {
  138 + return !isNull(object);
  139 + }
  140 +
  141 + /**
  142 + * * 判断一个对象是否是数组类型(Java基本型别的数组)
  143 + *
  144 + * @param object 对象
  145 + * @return true:是数组 false:不是数组
  146 + */
  147 + public static boolean isArray(Object object)
  148 + {
  149 + return isNotNull(object) && object.getClass().isArray();
  150 + }
  151 +
  152 + /**
  153 + * 去空格
  154 + */
  155 + public static String trim(String str)
  156 + {
  157 + return (str == null ? "" : str.trim());
  158 + }
  159 +
  160 + /**
  161 + * 截取字符串
  162 + *
  163 + * @param str 字符串
  164 + * @param start 开始
  165 + * @return 结果
  166 + */
  167 + public static String substring(final String str, int start)
  168 + {
  169 + if (str == null)
  170 + {
  171 + return NULLSTR;
  172 + }
  173 +
  174 + if (start < 0)
  175 + {
  176 + start = str.length() + start;
  177 + }
  178 +
  179 + if (start < 0)
  180 + {
  181 + start = 0;
  182 + }
  183 + if (start > str.length())
  184 + {
  185 + return NULLSTR;
  186 + }
  187 +
  188 + return str.substring(start);
  189 + }
  190 +
  191 + /**
  192 + * 截取字符串
  193 + *
  194 + * @param str 字符串
  195 + * @param start 开始
  196 + * @param end 结束
  197 + * @return 结果
  198 + */
  199 + public static String substring(final String str, int start, int end)
  200 + {
  201 + if (str == null)
  202 + {
  203 + return NULLSTR;
  204 + }
  205 +
  206 + if (end < 0)
  207 + {
  208 + end = str.length() + end;
  209 + }
  210 + if (start < 0)
  211 + {
  212 + start = str.length() + start;
  213 + }
  214 +
  215 + if (end > str.length())
  216 + {
  217 + end = str.length();
  218 + }
  219 +
  220 + if (start > end)
  221 + {
  222 + return NULLSTR;
  223 + }
  224 +
  225 + if (start < 0)
  226 + {
  227 + start = 0;
  228 + }
  229 + if (end < 0)
  230 + {
  231 + end = 0;
  232 + }
  233 +
  234 + return str.substring(start, end);
  235 + }
  236 +
  237 + /**
  238 + * 格式化文本, {} 表示占位符<br>
  239 + * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
  240 + * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
  241 + * 例:<br>
  242 + * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
  243 + * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
  244 + * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
  245 + *
  246 + * @param template 文本模板,被替换的部分用 {} 表示
  247 + * @param params 参数值
  248 + * @return 格式化后的文本
  249 + */
  250 + public static String format(String template, Object... params)
  251 + {
  252 + if (isEmpty(params) || isEmpty(template))
  253 + {
  254 + return template;
  255 + }
  256 + return StrFormatter.format(template, params);
  257 + }
  258 +
  259 +
  260 +
  261 + /**
  262 + * 字符串转set
  263 + *
  264 + * @param str 字符串
  265 + * @param sep 分隔符
  266 + * @return set集合
  267 + */
  268 + public static final Set<String> str2Set(String str, String sep)
  269 + {
  270 + return new HashSet<String>(str2List(str, sep, true, false));
  271 + }
  272 +
  273 + /**
  274 + * 字符串转list
  275 + *
  276 + * @param str 字符串
  277 + * @param sep 分隔符
  278 + * @param filterBlank 过滤纯空白
  279 + * @param trim 去掉首尾空白
  280 + * @return list集合
  281 + */
  282 + public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
  283 + {
  284 + List<String> list = new ArrayList<String>();
  285 + if (StringUtils.isEmpty(str))
  286 + {
  287 + return list;
  288 + }
  289 +
  290 + // 过滤空白字符串
  291 + if (filterBlank && StringUtils.isBlank(str))
  292 + {
  293 + return list;
  294 + }
  295 + String[] split = str.split(sep);
  296 + for (String string : split)
  297 + {
  298 + if (filterBlank && StringUtils.isBlank(string))
  299 + {
  300 + continue;
  301 + }
  302 + if (trim)
  303 + {
  304 + string = string.trim();
  305 + }
  306 + list.add(string);
  307 + }
  308 +
  309 + return list;
  310 + }
  311 +
  312 + /**
  313 + * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
  314 + *
  315 + * @param cs 指定字符串
  316 + * @param searchCharSequences 需要检查的字符串数组
  317 + * @return 是否包含任意一个字符串
  318 + */
  319 + public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
  320 + {
  321 + if (isEmpty(cs) || isEmpty(searchCharSequences))
  322 + {
  323 + return false;
  324 + }
  325 + for (CharSequence testStr : searchCharSequences)
  326 + {
  327 + if (containsIgnoreCase(cs, testStr))
  328 + {
  329 + return true;
  330 + }
  331 + }
  332 + return false;
  333 + }
  334 +
  335 + /**
  336 + * 驼峰转下划线命名
  337 + */
  338 + public static String toUnderScoreCase(String str)
  339 + {
  340 + if (str == null)
  341 + {
  342 + return null;
  343 + }
  344 + StringBuilder sb = new StringBuilder();
  345 + // 前置字符是否大写
  346 + boolean preCharIsUpperCase = true;
  347 + // 当前字符是否大写
  348 + boolean curreCharIsUpperCase = true;
  349 + // 下一字符是否大写
  350 + boolean nexteCharIsUpperCase = true;
  351 + for (int i = 0; i < str.length(); i++)
  352 + {
  353 + char c = str.charAt(i);
  354 + if (i > 0)
  355 + {
  356 + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
  357 + }
  358 + else
  359 + {
  360 + preCharIsUpperCase = false;
  361 + }
  362 +
  363 + curreCharIsUpperCase = Character.isUpperCase(c);
  364 +
  365 + if (i < (str.length() - 1))
  366 + {
  367 + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
  368 + }
  369 +
  370 + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
  371 + {
  372 + sb.append(SEPARATOR);
  373 + }
  374 + else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
  375 + {
  376 + sb.append(SEPARATOR);
  377 + }
  378 + sb.append(Character.toLowerCase(c));
  379 + }
  380 +
  381 + return sb.toString();
  382 + }
  383 +
  384 + /**
  385 + * 是否包含字符串
  386 + *
  387 + * @param str 验证字符串
  388 + * @param strs 字符串组
  389 + * @return 包含返回true
  390 + */
  391 + public static boolean inStringIgnoreCase(String str, String... strs)
  392 + {
  393 + if (str != null && strs != null)
  394 + {
  395 + for (String s : strs)
  396 + {
  397 + if (str.equalsIgnoreCase(trim(s)))
  398 + {
  399 + return true;
  400 + }
  401 + }
  402 + }
  403 + return false;
  404 + }
  405 +
  406 + /**
  407 + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
  408 + *
  409 + * @param name 转换前的下划线大写方式命名的字符串
  410 + * @return 转换后的驼峰式命名的字符串
  411 + */
  412 + public static String convertToCamelCase(String name)
  413 + {
  414 + StringBuilder result = new StringBuilder();
  415 + // 快速检查
  416 + if (name == null || name.isEmpty())
  417 + {
  418 + // 没必要转换
  419 + return "";
  420 + }
  421 + else if (!name.contains("_"))
  422 + {
  423 + // 不含下划线,仅将首字母大写
  424 + return name.substring(0, 1).toUpperCase() + name.substring(1);
  425 + }
  426 + // 用下划线将原始字符串分割
  427 + String[] camels = name.split("_");
  428 + for (String camel : camels)
  429 + {
  430 + // 跳过原始字符串中开头、结尾的下换线或双重下划线
  431 + if (camel.isEmpty())
  432 + {
  433 + continue;
  434 + }
  435 + // 首字母大写
  436 + result.append(camel.substring(0, 1).toUpperCase());
  437 + result.append(camel.substring(1).toLowerCase());
  438 + }
  439 + return result.toString();
  440 + }
  441 +
  442 + /**
  443 + * 驼峰式命名法 例如:user_name->userName
  444 + */
  445 + public static String toCamelCase(String s)
  446 + {
  447 + if (s == null)
  448 + {
  449 + return null;
  450 + }
  451 + s = s.toLowerCase();
  452 + StringBuilder sb = new StringBuilder(s.length());
  453 + boolean upperCase = false;
  454 + for (int i = 0; i < s.length(); i++)
  455 + {
  456 + char c = s.charAt(i);
  457 +
  458 + if (c == SEPARATOR)
  459 + {
  460 + upperCase = true;
  461 + }
  462 + else if (upperCase)
  463 + {
  464 + sb.append(Character.toUpperCase(c));
  465 + upperCase = false;
  466 + }
  467 + else
  468 + {
  469 + sb.append(c);
  470 + }
  471 + }
  472 + return sb.toString();
  473 + }
  474 +
  475 +
  476 +
  477 + @SuppressWarnings("unchecked")
  478 + public static <T> T cast(Object obj)
  479 + {
  480 + return (T) obj;
  481 + }
  482 +
  483 + /**
  484 + * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
  485 + *
  486 + * @param num 数字对象
  487 + * @param size 字符串指定长度
  488 + * @return 返回数字的字符串格式,该字符串为指定长度。
  489 + */
  490 + public static final String padl(final Number num, final int size)
  491 + {
  492 + return padl(num.toString(), size, '0');
  493 + }
  494 +
  495 + /**
  496 + * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
  497 + *
  498 + * @param s 原始字符串
  499 + * @param size 字符串指定长度
  500 + * @param c 用于补齐的字符
  501 + * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
  502 + */
  503 + public static final String padl(final String s, final int size, final char c)
  504 + {
  505 + final StringBuilder sb = new StringBuilder(size);
  506 + if (s != null)
  507 + {
  508 + final int len = s.length();
  509 + if (s.length() <= size)
  510 + {
  511 + for (int i = size - len; i > 0; i--)
  512 + {
  513 + sb.append(c);
  514 + }
  515 + sb.append(s);
  516 + }
  517 + else
  518 + {
  519 + return s.substring(len - size, len);
  520 + }
  521 + }
  522 + else
  523 + {
  524 + for (int i = size; i > 0; i--)
  525 + {
  526 + sb.append(c);
  527 + }
  528 + }
  529 + return sb.toString();
  530 + }
  531 +
  532 + /**
  533 + * [简要描述]:首字母大写
  534 + *
  535 + * @author com.zhonglai
  536 + * @param str
  537 + * @return
  538 + */
  539 + public static String getName(String str) {
  540 + char ch = str.toCharArray()[0];
  541 + ch = (char) ((ch - 97) + 'A');
  542 + str = ch + str.substring(1);
  543 + return str;
  544 + }
  545 +
  546 + public static void main(String[] args) {
  547 + System.out.println(StringUtils.toUnderScoreCase("deviceInfoId"));
  548 + }
  549 +}
  1 +package com.zhonglai.luhui.util;
  2 +
  3 +
  4 +import java.util.concurrent.*;
  5 +import java.util.logging.Level;
  6 +import java.util.logging.Logger;
  7 +
  8 +/**
  9 + * 线程相关工具类.
  10 + *
  11 + * @author ruoyi
  12 + */
  13 +public class Threads
  14 +{
  15 + private static final Logger logger = Logger.getLogger(Threads.class.getName());
  16 +
  17 + /**
  18 + * sleep等待,单位为毫秒
  19 + */
  20 + public static void sleep(long milliseconds)
  21 + {
  22 + try
  23 + {
  24 + Thread.sleep(milliseconds);
  25 + }
  26 + catch (InterruptedException e)
  27 + {
  28 + return;
  29 + }
  30 + }
  31 +
  32 + /**
  33 + * 停止线程池
  34 + * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
  35 + * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
  36 + * 如果仍然超時,則強制退出.
  37 + * 另对在shutdown时线程本身被调用中断做了处理.
  38 + */
  39 + public static void shutdownAndAwaitTermination(ExecutorService pool)
  40 + {
  41 + if (pool != null && !pool.isShutdown())
  42 + {
  43 + pool.shutdown();
  44 + try
  45 + {
  46 + if (!pool.awaitTermination(120, TimeUnit.SECONDS))
  47 + {
  48 + pool.shutdownNow();
  49 + if (!pool.awaitTermination(120, TimeUnit.SECONDS))
  50 + {
  51 + logger.info("Pool did not terminate");
  52 + }
  53 + }
  54 + }
  55 + catch (InterruptedException ie)
  56 + {
  57 + pool.shutdownNow();
  58 + Thread.currentThread().interrupt();
  59 + }
  60 + }
  61 + }
  62 +
  63 + /**
  64 + * 打印线程异常信息
  65 + */
  66 + public static void printException(Runnable r, Throwable t)
  67 + {
  68 + if (t == null && r instanceof Future<?>)
  69 + {
  70 + try
  71 + {
  72 + Future<?> future = (Future<?>) r;
  73 + if (future.isDone())
  74 + {
  75 + future.get();
  76 + }
  77 + }
  78 + catch (CancellationException ce)
  79 + {
  80 + t = ce;
  81 + }
  82 + catch (ExecutionException ee)
  83 + {
  84 + t = ee.getCause();
  85 + }
  86 + catch (InterruptedException ie)
  87 + {
  88 + Thread.currentThread().interrupt();
  89 + }
  90 + }
  91 + if (t != null)
  92 + {
  93 + logger.log(Level.SEVERE,t.getMessage(), t);
  94 + }
  95 + }
  96 +}
  1 +package com.zhonglai.luhui.util.bean;
  2 +
  3 +import javax.validation.ConstraintViolation;
  4 +import javax.validation.ConstraintViolationException;
  5 +import javax.validation.Validator;
  6 +import java.util.Set;
  7 +
  8 +/**
  9 + * bean对象属性验证
  10 + *
  11 + * @author ruoyi
  12 + */
  13 +public class BeanValidators
  14 +{
  15 + public static void validateWithException(Validator validator, Object object, Class<?>... groups)
  16 + throws ConstraintViolationException
  17 + {
  18 + Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
  19 + if (!constraintViolations.isEmpty())
  20 + {
  21 + throw new ConstraintViolationException(constraintViolations);
  22 + }
  23 + }
  24 +}
  1 +package com.zhonglai.luhui.util.bean;
  2 +
  3 +import java.lang.reflect.Field;
  4 +import java.lang.reflect.Modifier;
  5 +import java.util.Map;
  6 +
  7 +/**
  8 + * map操作
  9 + */
  10 +public class MapToObjectConverter {
  11 +
  12 + /**
  13 + * map转指定对象
  14 + * @param map
  15 + * @param clazz
  16 + * @return
  17 + * @param <T>
  18 + * @throws IllegalAccessException
  19 + * @throws InstantiationException
  20 + */
  21 + public static <T> T convert(Map<String, Object> map, Class<T> clazz) throws IllegalAccessException, InstantiationException {
  22 + T obj = clazz.newInstance();
  23 + for (Field field : clazz.getDeclaredFields()) {
  24 + int mod = field.getModifiers();
  25 + if (Modifier.isStatic(mod) || Modifier.isFinal(mod) || Modifier.isTransient(mod)) {
  26 + continue;
  27 + }
  28 + field.setAccessible(true);
  29 + if (map.containsKey(field.getName())) {
  30 + field.set(obj, map.get(field.getName()));
  31 + }
  32 + }
  33 + return obj;
  34 + }
  35 +}
  1 +package com.zhonglai.luhui.util.file;
  2 +
  3 +import org.apache.commons.lang3.StringUtils;
  4 +
  5 +import java.io.File;
  6 +
  7 +/**
  8 + * 文件类型工具类
  9 + *
  10 + * @author ruoyi
  11 + */
  12 +public class FileTypeUtils
  13 +{
  14 + /**
  15 + * 获取文件类型
  16 + * <p>
  17 + * 例如: ruoyi.txt, 返回: txt
  18 + *
  19 + * @param file 文件名
  20 + * @return 后缀(不含".")
  21 + */
  22 + public static String getFileType(File file)
  23 + {
  24 + if (null == file)
  25 + {
  26 + return StringUtils.EMPTY;
  27 + }
  28 + return getFileType(file.getName());
  29 + }
  30 +
  31 + /**
  32 + * 获取文件类型
  33 + * <p>
  34 + * 例如: ruoyi.txt, 返回: txt
  35 + *
  36 + * @param fileName 文件名
  37 + * @return 后缀(不含".")
  38 + */
  39 + public static String getFileType(String fileName)
  40 + {
  41 + int separatorIndex = fileName.lastIndexOf(".");
  42 + if (separatorIndex < 0)
  43 + {
  44 + return "";
  45 + }
  46 + return fileName.substring(separatorIndex + 1).toLowerCase();
  47 + }
  48 +
  49 + /**
  50 + * 获取文件类型
  51 + *
  52 + * @param photoByte 文件字节码
  53 + * @return 后缀(不含".")
  54 + */
  55 + public static String getFileExtendName(byte[] photoByte)
  56 + {
  57 + String strFileExtendName = "JPG";
  58 + if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
  59 + && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
  60 + {
  61 + strFileExtendName = "GIF";
  62 + }
  63 + else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
  64 + {
  65 + strFileExtendName = "JPG";
  66 + }
  67 + else if ((photoByte[0] == 66) && (photoByte[1] == 77))
  68 + {
  69 + strFileExtendName = "BMP";
  70 + }
  71 + else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
  72 + {
  73 + strFileExtendName = "PNG";
  74 + }
  75 + return strFileExtendName;
  76 + }
  77 +}
  1 +package com.zhonglai.luhui.util.file;
  2 +
  3 +/**
  4 + * 媒体类型工具类
  5 + *
  6 + * @author ruoyi
  7 + */
  8 +public class MimeTypeUtils
  9 +{
  10 + public static final String IMAGE_PNG = "image/png";
  11 +
  12 + public static final String IMAGE_JPG = "image/jpg";
  13 +
  14 + public static final String IMAGE_JPEG = "image/jpeg";
  15 +
  16 + public static final String IMAGE_BMP = "image/bmp";
  17 +
  18 + public static final String IMAGE_GIF = "image/gif";
  19 +
  20 + public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
  21 +
  22 + public static final String[] FLASH_EXTENSION = { "swf", "flv" };
  23 +
  24 + public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
  25 + "asf", "rm", "rmvb" };
  26 +
  27 + public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
  28 +
  29 + public static final String[] DEFAULT_ALLOWED_EXTENSION = {
  30 + // 图片
  31 + "bmp", "gif", "jpg", "jpeg", "png",
  32 + // word excel powerpoint
  33 + "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
  34 + // 压缩文件
  35 + "rar", "zip", "gz", "bz2",
  36 + // 视频格式
  37 + "mp4", "avi", "rmvb",
  38 + // pdf
  39 + "pdf" };
  40 +
  41 + public static String getExtension(String prefix)
  42 + {
  43 + switch (prefix)
  44 + {
  45 + case IMAGE_PNG:
  46 + return "png";
  47 + case IMAGE_JPG:
  48 + return "jpg";
  49 + case IMAGE_JPEG:
  50 + return "jpeg";
  51 + case IMAGE_BMP:
  52 + return "bmp";
  53 + case IMAGE_GIF:
  54 + return "gif";
  55 + default:
  56 + return "";
  57 + }
  58 + }
  59 +}
  1 +package com.zhonglai.luhui.util.html;
  2 +
  3 +
  4 +import org.apache.commons.lang3.StringUtils;
  5 +
  6 +/**
  7 + * 转义和反转义工具类
  8 + *
  9 + * @author ruoyi
  10 + */
  11 +public class EscapeUtil
  12 +{
  13 + public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
  14 +
  15 + private static final char[][] TEXT = new char[64][];
  16 +
  17 + static
  18 + {
  19 + for (int i = 0; i < 64; i++)
  20 + {
  21 + TEXT[i] = new char[] { (char) i };
  22 + }
  23 +
  24 + // special HTML characters
  25 + TEXT['\''] = "&#039;".toCharArray(); // 单引号
  26 + TEXT['"'] = "&#34;".toCharArray(); // 双引号
  27 + TEXT['&'] = "&#38;".toCharArray(); // &符
  28 + TEXT['<'] = "&#60;".toCharArray(); // 小于号
  29 + TEXT['>'] = "&#62;".toCharArray(); // 大于号
  30 + }
  31 +
  32 + /**
  33 + * 转义文本中的HTML字符为安全的字符
  34 + *
  35 + * @param text 被转义的文本
  36 + * @return 转义后的文本
  37 + */
  38 + public static String escape(String text)
  39 + {
  40 + return encode(text);
  41 + }
  42 +
  43 + /**
  44 + * 还原被转义的HTML特殊字符
  45 + *
  46 + * @param content 包含转义符的HTML内容
  47 + * @return 转换后的字符串
  48 + */
  49 + public static String unescape(String content)
  50 + {
  51 + return decode(content);
  52 + }
  53 +
  54 + /**
  55 + * 清除所有HTML标签,但是不删除标签内的内容
  56 + *
  57 + * @param content 文本
  58 + * @return 清除标签后的文本
  59 + */
  60 + public static String clean(String content)
  61 + {
  62 + return new HTMLFilter().filter(content);
  63 + }
  64 +
  65 + /**
  66 + * Escape编码
  67 + *
  68 + * @param text 被编码的文本
  69 + * @return 编码后的字符
  70 + */
  71 + private static String encode(String text)
  72 + {
  73 + if (StringUtils.isEmpty(text))
  74 + {
  75 + return StringUtils.EMPTY;
  76 + }
  77 +
  78 + final StringBuilder tmp = new StringBuilder(text.length() * 6);
  79 + char c;
  80 + for (int i = 0; i < text.length(); i++)
  81 + {
  82 + c = text.charAt(i);
  83 + if (c < 256)
  84 + {
  85 + tmp.append("%");
  86 + if (c < 16)
  87 + {
  88 + tmp.append("0");
  89 + }
  90 + tmp.append(Integer.toString(c, 16));
  91 + }
  92 + else
  93 + {
  94 + tmp.append("%u");
  95 + if (c <= 0xfff)
  96 + {
  97 + // issue#I49JU8@Gitee
  98 + tmp.append("0");
  99 + }
  100 + tmp.append(Integer.toString(c, 16));
  101 + }
  102 + }
  103 + return tmp.toString();
  104 + }
  105 +
  106 + /**
  107 + * Escape解码
  108 + *
  109 + * @param content 被转义的内容
  110 + * @return 解码后的字符串
  111 + */
  112 + public static String decode(String content)
  113 + {
  114 + if (StringUtils.isEmpty(content))
  115 + {
  116 + return content;
  117 + }
  118 +
  119 + StringBuilder tmp = new StringBuilder(content.length());
  120 + int lastPos = 0, pos = 0;
  121 + char ch;
  122 + while (lastPos < content.length())
  123 + {
  124 + pos = content.indexOf("%", lastPos);
  125 + if (pos == lastPos)
  126 + {
  127 + if (content.charAt(pos + 1) == 'u')
  128 + {
  129 + ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
  130 + tmp.append(ch);
  131 + lastPos = pos + 6;
  132 + }
  133 + else
  134 + {
  135 + ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
  136 + tmp.append(ch);
  137 + lastPos = pos + 3;
  138 + }
  139 + }
  140 + else
  141 + {
  142 + if (pos == -1)
  143 + {
  144 + tmp.append(content.substring(lastPos));
  145 + lastPos = content.length();
  146 + }
  147 + else
  148 + {
  149 + tmp.append(content.substring(lastPos, pos));
  150 + lastPos = pos;
  151 + }
  152 + }
  153 + }
  154 + return tmp.toString();
  155 + }
  156 +
  157 + public static void main(String[] args)
  158 + {
  159 + String html = "<script>alert(1);</script>";
  160 + String escape = EscapeUtil.escape(html);
  161 + // String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
  162 + // String html = "<123";
  163 + // String html = "123>";
  164 + System.out.println("clean: " + EscapeUtil.clean(html));
  165 + System.out.println("escape: " + escape);
  166 + System.out.println("unescape: " + EscapeUtil.unescape(escape));
  167 + }
  168 +}
  1 +package com.zhonglai.luhui.util.html;
  2 +
  3 +import java.util.*;
  4 +import java.util.concurrent.ConcurrentHashMap;
  5 +import java.util.concurrent.ConcurrentMap;
  6 +import java.util.regex.Matcher;
  7 +import java.util.regex.Pattern;
  8 +
  9 +/**
  10 + * HTML过滤器,用于去除XSS漏洞隐患。
  11 + *
  12 + * @author ruoyi
  13 + */
  14 +public final class HTMLFilter
  15 +{
  16 + /**
  17 + * regex flag union representing /si modifiers in php
  18 + **/
  19 + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
  20 + private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
  21 + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
  22 + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
  23 + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
  24 + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
  25 + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
  26 + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
  27 + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
  28 + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
  29 + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
  30 + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
  31 + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
  32 + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
  33 + private static final Pattern P_END_ARROW = Pattern.compile("^>");
  34 + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
  35 + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
  36 + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
  37 + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
  38 + private static final Pattern P_AMP = Pattern.compile("&");
  39 + private static final Pattern P_QUOTE = Pattern.compile("\"");
  40 + private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
  41 + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
  42 + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
  43 +
  44 + // @xxx could grow large... maybe use sesat's ReferenceMap
  45 + private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>();
  46 + private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>();
  47 +
  48 + /**
  49 + * set of allowed html elements, along with allowed attributes for each element
  50 + **/
  51 + private final Map<String, List<String>> vAllowed;
  52 + /**
  53 + * counts of open tags for each (allowable) html element
  54 + **/
  55 + private final Map<String, Integer> vTagCounts = new HashMap<>();
  56 +
  57 + /**
  58 + * html elements which must always be self-closing (e.g. "<img />")
  59 + **/
  60 + private final String[] vSelfClosingTags;
  61 + /**
  62 + * html elements which must always have separate opening and closing tags (e.g. "<b></b>")
  63 + **/
  64 + private final String[] vNeedClosingTags;
  65 + /**
  66 + * set of disallowed html elements
  67 + **/
  68 + private final String[] vDisallowed;
  69 + /**
  70 + * attributes which should be checked for valid protocols
  71 + **/
  72 + private final String[] vProtocolAtts;
  73 + /**
  74 + * allowed protocols
  75 + **/
  76 + private final String[] vAllowedProtocols;
  77 + /**
  78 + * tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
  79 + **/
  80 + private final String[] vRemoveBlanks;
  81 + /**
  82 + * entities allowed within html markup
  83 + **/
  84 + private final String[] vAllowedEntities;
  85 + /**
  86 + * flag determining whether comments are allowed in input String.
  87 + */
  88 + private final boolean stripComment;
  89 + private final boolean encodeQuotes;
  90 + /**
  91 + * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>"
  92 + * becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped.
  93 + */
  94 + private final boolean alwaysMakeTags;
  95 +
  96 + /**
  97 + * Default constructor.
  98 + */
  99 + public HTMLFilter()
  100 + {
  101 + vAllowed = new HashMap<>();
  102 +
  103 + final ArrayList<String> a_atts = new ArrayList<>();
  104 + a_atts.add("href");
  105 + a_atts.add("target");
  106 + vAllowed.put("a", a_atts);
  107 +
  108 + final ArrayList<String> img_atts = new ArrayList<>();
  109 + img_atts.add("src");
  110 + img_atts.add("width");
  111 + img_atts.add("height");
  112 + img_atts.add("alt");
  113 + vAllowed.put("img", img_atts);
  114 +
  115 + final ArrayList<String> no_atts = new ArrayList<>();
  116 + vAllowed.put("b", no_atts);
  117 + vAllowed.put("strong", no_atts);
  118 + vAllowed.put("i", no_atts);
  119 + vAllowed.put("em", no_atts);
  120 +
  121 + vSelfClosingTags = new String[] { "img" };
  122 + vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" };
  123 + vDisallowed = new String[] {};
  124 + vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp.
  125 + vProtocolAtts = new String[] { "src", "href" };
  126 + vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" };
  127 + vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
  128 + stripComment = true;
  129 + encodeQuotes = true;
  130 + alwaysMakeTags = false;
  131 + }
  132 +
  133 + /**
  134 + * Map-parameter configurable constructor.
  135 + *
  136 + * @param conf map containing configuration. keys match field names.
  137 + */
  138 + @SuppressWarnings("unchecked")
  139 + public HTMLFilter(final Map<String, Object> conf)
  140 + {
  141 +
  142 + assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
  143 + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
  144 + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
  145 + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
  146 + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
  147 + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
  148 + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
  149 + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
  150 +
  151 + vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
  152 + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
  153 + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
  154 + vDisallowed = (String[]) conf.get("vDisallowed");
  155 + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
  156 + vProtocolAtts = (String[]) conf.get("vProtocolAtts");
  157 + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
  158 + vAllowedEntities = (String[]) conf.get("vAllowedEntities");
  159 + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
  160 + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
  161 + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
  162 + }
  163 +
  164 + private void reset()
  165 + {
  166 + vTagCounts.clear();
  167 + }
  168 +
  169 + // ---------------------------------------------------------------
  170 + // my versions of some PHP library functions
  171 + public static String chr(final int decimal)
  172 + {
  173 + return String.valueOf((char) decimal);
  174 + }
  175 +
  176 + public static String htmlSpecialChars(final String s)
  177 + {
  178 + String result = s;
  179 + result = regexReplace(P_AMP, "&amp;", result);
  180 + result = regexReplace(P_QUOTE, "&quot;", result);
  181 + result = regexReplace(P_LEFT_ARROW, "&lt;", result);
  182 + result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
  183 + return result;
  184 + }
  185 +
  186 + // ---------------------------------------------------------------
  187 +
  188 + /**
  189 + * given a user submitted input String, filter out any invalid or restricted html.
  190 + *
  191 + * @param input text (i.e. submitted by a user) than may contain html
  192 + * @return "clean" version of input, with only valid, whitelisted html elements allowed
  193 + */
  194 + public String filter(final String input)
  195 + {
  196 + reset();
  197 + String s = input;
  198 +
  199 + s = escapeComments(s);
  200 +
  201 + s = balanceHTML(s);
  202 +
  203 + s = checkTags(s);
  204 +
  205 + s = processRemoveBlanks(s);
  206 +
  207 + // s = validateEntities(s);
  208 +
  209 + return s;
  210 + }
  211 +
  212 + public boolean isAlwaysMakeTags()
  213 + {
  214 + return alwaysMakeTags;
  215 + }
  216 +
  217 + public boolean isStripComments()
  218 + {
  219 + return stripComment;
  220 + }
  221 +
  222 + private String escapeComments(final String s)
  223 + {
  224 + final Matcher m = P_COMMENTS.matcher(s);
  225 + final StringBuffer buf = new StringBuffer();
  226 + if (m.find())
  227 + {
  228 + final String match = m.group(1); // (.*?)
  229 + m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
  230 + }
  231 + m.appendTail(buf);
  232 +
  233 + return buf.toString();
  234 + }
  235 +
  236 + private String balanceHTML(String s)
  237 + {
  238 + if (alwaysMakeTags)
  239 + {
  240 + //
  241 + // try and form html
  242 + //
  243 + s = regexReplace(P_END_ARROW, "", s);
  244 + // 不追加结束标签
  245 + s = regexReplace(P_BODY_TO_END, "<$1>", s);
  246 + s = regexReplace(P_XML_CONTENT, "$1<$2", s);
  247 +
  248 + }
  249 + else
  250 + {
  251 + //
  252 + // escape stray brackets
  253 + //
  254 + s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
  255 + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
  256 +
  257 + //
  258 + // the last regexp causes '<>' entities to appear
  259 + // (we need to do a lookahead assertion so that the last bracket can
  260 + // be used in the next pass of the regexp)
  261 + //
  262 + s = regexReplace(P_BOTH_ARROWS, "", s);
  263 + }
  264 +
  265 + return s;
  266 + }
  267 +
  268 + private String checkTags(String s)
  269 + {
  270 + Matcher m = P_TAGS.matcher(s);
  271 +
  272 + final StringBuffer buf = new StringBuffer();
  273 + while (m.find())
  274 + {
  275 + String replaceStr = m.group(1);
  276 + replaceStr = processTag(replaceStr);
  277 + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
  278 + }
  279 + m.appendTail(buf);
  280 +
  281 + // these get tallied in processTag
  282 + // (remember to reset before subsequent calls to filter method)
  283 + final StringBuilder sBuilder = new StringBuilder(buf.toString());
  284 + for (String key : vTagCounts.keySet())
  285 + {
  286 + for (int ii = 0; ii < vTagCounts.get(key); ii++)
  287 + {
  288 + sBuilder.append("</").append(key).append(">");
  289 + }
  290 + }
  291 + s = sBuilder.toString();
  292 +
  293 + return s;
  294 + }
  295 +
  296 + private String processRemoveBlanks(final String s)
  297 + {
  298 + String result = s;
  299 + for (String tag : vRemoveBlanks)
  300 + {
  301 + if (!P_REMOVE_PAIR_BLANKS.containsKey(tag))
  302 + {
  303 + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
  304 + }
  305 + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
  306 + if (!P_REMOVE_SELF_BLANKS.containsKey(tag))
  307 + {
  308 + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
  309 + }
  310 + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
  311 + }
  312 +
  313 + return result;
  314 + }
  315 +
  316 + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s)
  317 + {
  318 + Matcher m = regex_pattern.matcher(s);
  319 + return m.replaceAll(replacement);
  320 + }
  321 +
  322 + private String processTag(final String s)
  323 + {
  324 + // ending tags
  325 + Matcher m = P_END_TAG.matcher(s);
  326 + if (m.find())
  327 + {
  328 + final String name = m.group(1).toLowerCase();
  329 + if (allowed(name))
  330 + {
  331 + if (!inArray(name, vSelfClosingTags))
  332 + {
  333 + if (vTagCounts.containsKey(name))
  334 + {
  335 + vTagCounts.put(name, vTagCounts.get(name) - 1);
  336 + return "</" + name + ">";
  337 + }
  338 + }
  339 + }
  340 + }
  341 +
  342 + // starting tags
  343 + m = P_START_TAG.matcher(s);
  344 + if (m.find())
  345 + {
  346 + final String name = m.group(1).toLowerCase();
  347 + final String body = m.group(2);
  348 + String ending = m.group(3);
  349 +
  350 + // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
  351 + if (allowed(name))
  352 + {
  353 + final StringBuilder params = new StringBuilder();
  354 +
  355 + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
  356 + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
  357 + final List<String> paramNames = new ArrayList<>();
  358 + final List<String> paramValues = new ArrayList<>();
  359 + while (m2.find())
  360 + {
  361 + paramNames.add(m2.group(1)); // ([a-z0-9]+)
  362 + paramValues.add(m2.group(3)); // (.*?)
  363 + }
  364 + while (m3.find())
  365 + {
  366 + paramNames.add(m3.group(1)); // ([a-z0-9]+)
  367 + paramValues.add(m3.group(3)); // ([^\"\\s']+)
  368 + }
  369 +
  370 + String paramName, paramValue;
  371 + for (int ii = 0; ii < paramNames.size(); ii++)
  372 + {
  373 + paramName = paramNames.get(ii).toLowerCase();
  374 + paramValue = paramValues.get(ii);
  375 +
  376 + // debug( "paramName='" + paramName + "'" );
  377 + // debug( "paramValue='" + paramValue + "'" );
  378 + // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
  379 +
  380 + if (allowedAttribute(name, paramName))
  381 + {
  382 + if (inArray(paramName, vProtocolAtts))
  383 + {
  384 + paramValue = processParamProtocol(paramValue);
  385 + }
  386 + params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\"");
  387 + }
  388 + }
  389 +
  390 + if (inArray(name, vSelfClosingTags))
  391 + {
  392 + ending = " /";
  393 + }
  394 +
  395 + if (inArray(name, vNeedClosingTags))
  396 + {
  397 + ending = "";
  398 + }
  399 +
  400 + if (ending == null || ending.length() < 1)
  401 + {
  402 + if (vTagCounts.containsKey(name))
  403 + {
  404 + vTagCounts.put(name, vTagCounts.get(name) + 1);
  405 + }
  406 + else
  407 + {
  408 + vTagCounts.put(name, 1);
  409 + }
  410 + }
  411 + else
  412 + {
  413 + ending = " /";
  414 + }
  415 + return "<" + name + params + ending + ">";
  416 + }
  417 + else
  418 + {
  419 + return "";
  420 + }
  421 + }
  422 +
  423 + // comments
  424 + m = P_COMMENT.matcher(s);
  425 + if (!stripComment && m.find())
  426 + {
  427 + return "<" + m.group() + ">";
  428 + }
  429 +
  430 + return "";
  431 + }
  432 +
  433 + private String processParamProtocol(String s)
  434 + {
  435 + s = decodeEntities(s);
  436 + final Matcher m = P_PROTOCOL.matcher(s);
  437 + if (m.find())
  438 + {
  439 + final String protocol = m.group(1);
  440 + if (!inArray(protocol, vAllowedProtocols))
  441 + {
  442 + // bad protocol, turn into local anchor link instead
  443 + s = "#" + s.substring(protocol.length() + 1);
  444 + if (s.startsWith("#//"))
  445 + {
  446 + s = "#" + s.substring(3);
  447 + }
  448 + }
  449 + }
  450 +
  451 + return s;
  452 + }
  453 +
  454 + private String decodeEntities(String s)
  455 + {
  456 + StringBuffer buf = new StringBuffer();
  457 +
  458 + Matcher m = P_ENTITY.matcher(s);
  459 + while (m.find())
  460 + {
  461 + final String match = m.group(1);
  462 + final int decimal = Integer.decode(match).intValue();
  463 + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
  464 + }
  465 + m.appendTail(buf);
  466 + s = buf.toString();
  467 +
  468 + buf = new StringBuffer();
  469 + m = P_ENTITY_UNICODE.matcher(s);
  470 + while (m.find())
  471 + {
  472 + final String match = m.group(1);
  473 + final int decimal = Integer.valueOf(match, 16).intValue();
  474 + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
  475 + }
  476 + m.appendTail(buf);
  477 + s = buf.toString();
  478 +
  479 + buf = new StringBuffer();
  480 + m = P_ENCODE.matcher(s);
  481 + while (m.find())
  482 + {
  483 + final String match = m.group(1);
  484 + final int decimal = Integer.valueOf(match, 16).intValue();
  485 + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
  486 + }
  487 + m.appendTail(buf);
  488 + s = buf.toString();
  489 +
  490 + s = validateEntities(s);
  491 + return s;
  492 + }
  493 +
  494 + private String validateEntities(final String s)
  495 + {
  496 + StringBuffer buf = new StringBuffer();
  497 +
  498 + // validate entities throughout the string
  499 + Matcher m = P_VALID_ENTITIES.matcher(s);
  500 + while (m.find())
  501 + {
  502 + final String one = m.group(1); // ([^&;]*)
  503 + final String two = m.group(2); // (?=(;|&|$))
  504 + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
  505 + }
  506 + m.appendTail(buf);
  507 +
  508 + return encodeQuotes(buf.toString());
  509 + }
  510 +
  511 + private String encodeQuotes(final String s)
  512 + {
  513 + if (encodeQuotes)
  514 + {
  515 + StringBuffer buf = new StringBuffer();
  516 + Matcher m = P_VALID_QUOTES.matcher(s);
  517 + while (m.find())
  518 + {
  519 + final String one = m.group(1); // (>|^)
  520 + final String two = m.group(2); // ([^<]+?)
  521 + final String three = m.group(3); // (<|$)
  522 + // 不替换双引号为&quot;,防止json格式无效 regexReplace(P_QUOTE, "&quot;", two)
  523 + m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three));
  524 + }
  525 + m.appendTail(buf);
  526 + return buf.toString();
  527 + }
  528 + else
  529 + {
  530 + return s;
  531 + }
  532 + }
  533 +
  534 + private String checkEntity(final String preamble, final String term)
  535 + {
  536 +
  537 + return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&amp;" + preamble;
  538 + }
  539 +
  540 + private boolean isValidEntity(final String entity)
  541 + {
  542 + return inArray(entity, vAllowedEntities);
  543 + }
  544 +
  545 + private static boolean inArray(final String s, final String[] array)
  546 + {
  547 + for (String item : array)
  548 + {
  549 + if (item != null && item.equals(s))
  550 + {
  551 + return true;
  552 + }
  553 + }
  554 + return false;
  555 + }
  556 +
  557 + private boolean allowed(final String name)
  558 + {
  559 + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
  560 + }
  561 +
  562 + private boolean allowedAttribute(final String name, final String paramName)
  563 + {
  564 + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
  565 + }
  566 +}
  1 +package com.zhonglai.luhui.util.poi;
  2 +
  3 +/**
  4 + * Excel数据格式处理适配器
  5 + *
  6 + * @author ruoyi
  7 + */
  8 +public interface ExcelHandlerAdapter
  9 +{
  10 + /**
  11 + * 格式化
  12 + *
  13 + * @param value 单元格数据值
  14 + * @param args excel注解args参数组
  15 + *
  16 + * @return 处理后的值
  17 + */
  18 + Object format(Object value, String[] args);
  19 +}
  1 +package com.zhonglai.luhui.util.sign;
  2 +
  3 +/**
  4 + * Base64工具类
  5 + *
  6 + * @author ruoyi
  7 + */
  8 +public final class Base64
  9 +{
  10 + static private final int BASELENGTH = 128;
  11 + static private final int LOOKUPLENGTH = 64;
  12 + static private final int TWENTYFOURBITGROUP = 24;
  13 + static private final int EIGHTBIT = 8;
  14 + static private final int SIXTEENBIT = 16;
  15 + static private final int FOURBYTE = 4;
  16 + static private final int SIGN = -128;
  17 + static private final char PAD = '=';
  18 + static final private byte[] base64Alphabet = new byte[BASELENGTH];
  19 + static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
  20 +
  21 + static
  22 + {
  23 + for (int i = 0; i < BASELENGTH; ++i)
  24 + {
  25 + base64Alphabet[i] = -1;
  26 + }
  27 + for (int i = 'Z'; i >= 'A'; i--)
  28 + {
  29 + base64Alphabet[i] = (byte) (i - 'A');
  30 + }
  31 + for (int i = 'z'; i >= 'a'; i--)
  32 + {
  33 + base64Alphabet[i] = (byte) (i - 'a' + 26);
  34 + }
  35 +
  36 + for (int i = '9'; i >= '0'; i--)
  37 + {
  38 + base64Alphabet[i] = (byte) (i - '0' + 52);
  39 + }
  40 +
  41 + base64Alphabet['+'] = 62;
  42 + base64Alphabet['/'] = 63;
  43 +
  44 + for (int i = 0; i <= 25; i++)
  45 + {
  46 + lookUpBase64Alphabet[i] = (char) ('A' + i);
  47 + }
  48 +
  49 + for (int i = 26, j = 0; i <= 51; i++, j++)
  50 + {
  51 + lookUpBase64Alphabet[i] = (char) ('a' + j);
  52 + }
  53 +
  54 + for (int i = 52, j = 0; i <= 61; i++, j++)
  55 + {
  56 + lookUpBase64Alphabet[i] = (char) ('0' + j);
  57 + }
  58 + lookUpBase64Alphabet[62] = (char) '+';
  59 + lookUpBase64Alphabet[63] = (char) '/';
  60 + }
  61 +
  62 + private static boolean isWhiteSpace(char octect)
  63 + {
  64 + return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
  65 + }
  66 +
  67 + private static boolean isPad(char octect)
  68 + {
  69 + return (octect == PAD);
  70 + }
  71 +
  72 + private static boolean isData(char octect)
  73 + {
  74 + return (octect < BASELENGTH && base64Alphabet[octect] != -1);
  75 + }
  76 +
  77 + /**
  78 + * Encodes hex octects into Base64
  79 + *
  80 + * @param binaryData Array containing binaryData
  81 + * @return Encoded Base64 array
  82 + */
  83 + public static String encode(byte[] binaryData)
  84 + {
  85 + if (binaryData == null)
  86 + {
  87 + return null;
  88 + }
  89 +
  90 + int lengthDataBits = binaryData.length * EIGHTBIT;
  91 + if (lengthDataBits == 0)
  92 + {
  93 + return "";
  94 + }
  95 +
  96 + int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
  97 + int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
  98 + int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
  99 + char encodedData[] = null;
  100 +
  101 + encodedData = new char[numberQuartet * 4];
  102 +
  103 + byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
  104 +
  105 + int encodedIndex = 0;
  106 + int dataIndex = 0;
  107 +
  108 + for (int i = 0; i < numberTriplets; i++)
  109 + {
  110 + b1 = binaryData[dataIndex++];
  111 + b2 = binaryData[dataIndex++];
  112 + b3 = binaryData[dataIndex++];
  113 +
  114 + l = (byte) (b2 & 0x0f);
  115 + k = (byte) (b1 & 0x03);
  116 +
  117 + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
  118 + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
  119 + byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
  120 +
  121 + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  122 + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
  123 + encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
  124 + encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
  125 + }
  126 +
  127 + // form integral number of 6-bit groups
  128 + if (fewerThan24bits == EIGHTBIT)
  129 + {
  130 + b1 = binaryData[dataIndex];
  131 + k = (byte) (b1 & 0x03);
  132 + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
  133 + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  134 + encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
  135 + encodedData[encodedIndex++] = PAD;
  136 + encodedData[encodedIndex++] = PAD;
  137 + }
  138 + else if (fewerThan24bits == SIXTEENBIT)
  139 + {
  140 + b1 = binaryData[dataIndex];
  141 + b2 = binaryData[dataIndex + 1];
  142 + l = (byte) (b2 & 0x0f);
  143 + k = (byte) (b1 & 0x03);
  144 +
  145 + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
  146 + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
  147 +
  148 + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
  149 + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
  150 + encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
  151 + encodedData[encodedIndex++] = PAD;
  152 + }
  153 + return new String(encodedData);
  154 + }
  155 +
  156 + /**
  157 + * Decodes Base64 data into octects
  158 + *
  159 + * @param encoded string containing Base64 data
  160 + * @return Array containind decoded data.
  161 + */
  162 + public static byte[] decode(String encoded)
  163 + {
  164 + if (encoded == null)
  165 + {
  166 + return null;
  167 + }
  168 +
  169 + char[] base64Data = encoded.toCharArray();
  170 + // remove white spaces
  171 + int len = removeWhiteSpace(base64Data);
  172 +
  173 + if (len % FOURBYTE != 0)
  174 + {
  175 + return null;// should be divisible by four
  176 + }
  177 +
  178 + int numberQuadruple = (len / FOURBYTE);
  179 +
  180 + if (numberQuadruple == 0)
  181 + {
  182 + return new byte[0];
  183 + }
  184 +
  185 + byte decodedData[] = null;
  186 + byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
  187 + char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
  188 +
  189 + int i = 0;
  190 + int encodedIndex = 0;
  191 + int dataIndex = 0;
  192 + decodedData = new byte[(numberQuadruple) * 3];
  193 +
  194 + for (; i < numberQuadruple - 1; i++)
  195 + {
  196 +
  197 + if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
  198 + || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++])))
  199 + {
  200 + return null;
  201 + } // if found "no data" just return null
  202 +
  203 + b1 = base64Alphabet[d1];
  204 + b2 = base64Alphabet[d2];
  205 + b3 = base64Alphabet[d3];
  206 + b4 = base64Alphabet[d4];
  207 +
  208 + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  209 + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  210 + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
  211 + }
  212 +
  213 + if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])))
  214 + {
  215 + return null;// if found "no data" just return null
  216 + }
  217 +
  218 + b1 = base64Alphabet[d1];
  219 + b2 = base64Alphabet[d2];
  220 +
  221 + d3 = base64Data[dataIndex++];
  222 + d4 = base64Data[dataIndex++];
  223 + if (!isData((d3)) || !isData((d4)))
  224 + {// Check if they are PAD characters
  225 + if (isPad(d3) && isPad(d4))
  226 + {
  227 + if ((b2 & 0xf) != 0)// last 4 bits should be zero
  228 + {
  229 + return null;
  230 + }
  231 + byte[] tmp = new byte[i * 3 + 1];
  232 + System.arraycopy(decodedData, 0, tmp, 0, i * 3);
  233 + tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
  234 + return tmp;
  235 + }
  236 + else if (!isPad(d3) && isPad(d4))
  237 + {
  238 + b3 = base64Alphabet[d3];
  239 + if ((b3 & 0x3) != 0)// last 2 bits should be zero
  240 + {
  241 + return null;
  242 + }
  243 + byte[] tmp = new byte[i * 3 + 2];
  244 + System.arraycopy(decodedData, 0, tmp, 0, i * 3);
  245 + tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  246 + tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  247 + return tmp;
  248 + }
  249 + else
  250 + {
  251 + return null;
  252 + }
  253 + }
  254 + else
  255 + { // No PAD e.g 3cQl
  256 + b3 = base64Alphabet[d3];
  257 + b4 = base64Alphabet[d4];
  258 + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
  259 + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
  260 + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
  261 +
  262 + }
  263 + return decodedData;
  264 + }
  265 +
  266 + /**
  267 + * remove WhiteSpace from MIME containing encoded Base64 data.
  268 + *
  269 + * @param data the byte array of base64 data (with WS)
  270 + * @return the new length
  271 + */
  272 + private static int removeWhiteSpace(char[] data)
  273 + {
  274 + if (data == null)
  275 + {
  276 + return 0;
  277 + }
  278 +
  279 + // count characters that's not whitespace
  280 + int newSize = 0;
  281 + int len = data.length;
  282 + for (int i = 0; i < len; i++)
  283 + {
  284 + if (!isWhiteSpace(data[i]))
  285 + {
  286 + data[newSize++] = data[i];
  287 + }
  288 + }
  289 + return newSize;
  290 + }
  291 +}
  1 +package com.zhonglai.luhui.util.sign; import java.nio.charset.StandardCharsets;import java.security.MessageDigest;import java.util.logging.Level;import java.util.logging.Logger; /** * Md5加密方法 * * @author ruoyi */public class Md5Utils{ private static final Logger log = Logger.getLogger(Md5Utils.class.getName()); private static byte[] md5(String s) { MessageDigest algorithm; try { algorithm = MessageDigest.getInstance("MD5"); algorithm.reset(); algorithm.update(s.getBytes("UTF-8")); byte[] messageDigest = algorithm.digest(); return messageDigest; } catch (Exception e) { log.log(Level.WARNING,"MD5 Error...", e); } return null; } private static final String toHex(byte hash[]) { if (hash == null) { return null; } StringBuffer buf = new StringBuffer(hash.length * 2); int i; for (i = 0; i < hash.length; i++) { if ((hash[i] & 0xff) < 0x10) { buf.append("0"); } buf.append(Long.toString(hash[i] & 0xff, 16)); } return buf.toString(); } public static String hash(String s) { try { return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); } catch (Exception e) { log.log(Level.WARNING,"not supported charset...{}", e); return s; } }}
  1 +package com.zhonglai.luhui.util.sql;
  2 +
  3 +import java.util.HashMap;
  4 +import java.util.Map;
  5 +
  6 +/**
  7 + * Entity基类
  8 + *
  9 + * @author ruoyi
  10 + */
  11 +public class BaseEntity
  12 +{
  13 + private Map<String,Object[]> timeMap; //时间条件(如:{"create_time":[开始时间,结束时间]})
  14 + private String[] keyValue; //模糊匹配的关键字(如:["value","name,no"])
  15 + private Map<String, QueryType> params; //字段对应的比较符号(如:{"id":"EQ"})
  16 +
  17 + private String orderBy; //排序(如:"id,name")
  18 +
  19 + public Map<String, Object[]> getTimeMap() {
  20 + return timeMap;
  21 + }
  22 +
  23 + public void setTimeMap(Map<String, Object[]> timeMap) {
  24 + this.timeMap = timeMap;
  25 + }
  26 +
  27 +
  28 + public String[] getKeyValue() {
  29 + return keyValue;
  30 + }
  31 +
  32 + public void setKeyValue(String[] keyValue) {
  33 + this.keyValue = keyValue;
  34 + }
  35 +
  36 + public Map<String, QueryType> getParams() {
  37 + return params;
  38 + }
  39 +
  40 + public void setParams(Map<String, QueryType> params) {
  41 + this.params = params;
  42 + }
  43 +}
  1 +package com.zhonglai.luhui.util.sql;
  2 +
  3 +public enum QueryType {
  4 + EQ,NE,GT,GTE,LT,LTE,LIKE
  5 +}
  1 +package com.zhonglai.luhui.util.sql;
  2 +
  3 +
  4 +import com.sun.xml.internal.ws.util.UtilException;
  5 +import org.apache.commons.lang3.StringUtils;
  6 +
  7 +/**
  8 + * sql操作工具类
  9 + *
  10 + * @author ruoyi
  11 + */
  12 +public class SqlUtil
  13 +{
  14 + /**
  15 + * 定义常用的 sql关键字
  16 + */
  17 + public static String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
  18 +
  19 + /**
  20 + * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
  21 + */
  22 + public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
  23 +
  24 + /**
  25 + * 检查字符,防止注入绕过
  26 + */
  27 + public static String escapeOrderBySql(String value)
  28 + {
  29 + if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
  30 + {
  31 + throw new UtilException("参数不符合规范,不能进行查询");
  32 + }
  33 + return value;
  34 + }
  35 +
  36 + /**
  37 + * 验证 order by 语法是否符合规范
  38 + */
  39 + public static boolean isValidOrderBySql(String value)
  40 + {
  41 + return value.matches(SQL_PATTERN);
  42 + }
  43 +
  44 + /**
  45 + * SQL关键字检查
  46 + */
  47 + public static void filterKeyword(String value)
  48 + {
  49 + if (StringUtils.isEmpty(value))
  50 + {
  51 + return;
  52 + }
  53 + String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
  54 + for (String sqlKeyword : sqlKeywords)
  55 + {
  56 + if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
  57 + {
  58 + throw new UtilException("参数存在SQL注入风险");
  59 + }
  60 + }
  61 + }
  62 +}
  1 +package com.zhonglai.luhui.util.uuid;
  2 +
  3 +/**
  4 + * ID生成器工具类
  5 + *
  6 + * @author ruoyi
  7 + */
  8 +public class IdUtils
  9 +{
  10 + /**
  11 + * 获取随机UUID
  12 + *
  13 + * @return 随机UUID
  14 + */
  15 + public static String randomUUID()
  16 + {
  17 + return UUID.randomUUID().toString();
  18 + }
  19 +
  20 + /**
  21 + * 简化的UUID,去掉了横线
  22 + *
  23 + * @return 简化的UUID,去掉了横线
  24 + */
  25 + public static String simpleUUID()
  26 + {
  27 + return UUID.randomUUID().toString(true);
  28 + }
  29 +
  30 + /**
  31 + * 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID
  32 + *
  33 + * @return 随机UUID
  34 + */
  35 + public static String fastUUID()
  36 + {
  37 + return UUID.fastUUID().toString();
  38 + }
  39 +
  40 + /**
  41 + * 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID
  42 + *
  43 + * @return 简化的UUID,去掉了横线
  44 + */
  45 + public static String fastSimpleUUID()
  46 + {
  47 + return UUID.fastUUID().toString(true);
  48 + }
  49 +}
  1 +package com.zhonglai.luhui.util.uuid;
  2 +
  3 +
  4 +import com.zhonglai.luhui.util.DateUtils;
  5 +import com.zhonglai.luhui.util.StringUtils;
  6 +
  7 +import java.util.concurrent.atomic.AtomicInteger;
  8 +
  9 +/**
  10 + * @author ruoyi 序列生成类
  11 + */
  12 +public class Seq
  13 +{
  14 + // 通用序列类型
  15 + public static final String commSeqType = "COMMON";
  16 +
  17 + // 上传序列类型
  18 + public static final String uploadSeqType = "UPLOAD";
  19 +
  20 + // 通用接口序列数
  21 + private static AtomicInteger commSeq = new AtomicInteger(1);
  22 +
  23 + // 上传接口序列数
  24 + private static AtomicInteger uploadSeq = new AtomicInteger(1);
  25 +
  26 + // 机器标识
  27 + private static String machineCode = "A";
  28 +
  29 + /**
  30 + * 获取通用序列号
  31 + *
  32 + * @return 序列值
  33 + */
  34 + public static String getId()
  35 + {
  36 + return getId(commSeqType);
  37 + }
  38 +
  39 + /**
  40 + * 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串
  41 + *
  42 + * @return 序列值
  43 + */
  44 + public static String getId(String type)
  45 + {
  46 + AtomicInteger atomicInt = commSeq;
  47 + if (uploadSeqType.equals(type))
  48 + {
  49 + atomicInt = uploadSeq;
  50 + }
  51 + return getId(atomicInt, 3);
  52 + }
  53 +
  54 + /**
  55 + * 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串
  56 + *
  57 + * @param atomicInt 序列数
  58 + * @param length 数值长度
  59 + * @return 序列值
  60 + */
  61 + public static String getId(AtomicInteger atomicInt, int length)
  62 + {
  63 + String result = DateUtils.dateTimeNow();
  64 + result += machineCode;
  65 + result += getSeq(atomicInt, length);
  66 + return result;
  67 + }
  68 +
  69 + /**
  70 + * 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数
  71 + *
  72 + * @return 序列值
  73 + */
  74 + private synchronized static String getSeq(AtomicInteger atomicInt, int length)
  75 + {
  76 + // 先取值再+1
  77 + int value = atomicInt.getAndIncrement();
  78 +
  79 + // 如果更新后值>=10 的 (length)幂次方则重置为1
  80 + int maxSeq = (int) Math.pow(10, length);
  81 + if (atomicInt.get() >= maxSeq)
  82 + {
  83 + atomicInt.set(1);
  84 + }
  85 + // 转字符串,用0左补齐
  86 + return StringUtils.padl(value, length);
  87 + }
  88 +}
  1 +package com.zhonglai.luhui.util.uuid;
  2 +
  3 +
  4 +import com.sun.xml.internal.ws.util.UtilException;
  5 +
  6 +import java.security.MessageDigest;
  7 +import java.security.NoSuchAlgorithmException;
  8 +import java.security.SecureRandom;
  9 +import java.util.Random;
  10 +import java.util.concurrent.ThreadLocalRandom;
  11 +
  12 +/**
  13 + * 提供通用唯一识别码(universally unique identifier)(UUID)实现
  14 + *
  15 + * @author ruoyi
  16 + */
  17 +public final class UUID implements java.io.Serializable, Comparable<UUID>
  18 +{
  19 + private static final long serialVersionUID = -1185015143654744140L;
  20 +
  21 + /**
  22 + * SecureRandom 的单例
  23 + *
  24 + */
  25 + private static class Holder
  26 + {
  27 + static final SecureRandom numberGenerator = getSecureRandom();
  28 + }
  29 +
  30 + /** 此UUID的最高64有效位 */
  31 + private final long mostSigBits;
  32 +
  33 + /** 此UUID的最低64有效位 */
  34 + private final long leastSigBits;
  35 +
  36 + /**
  37 + * 私有构造
  38 + *
  39 + * @param data 数据
  40 + */
  41 + private UUID(byte[] data)
  42 + {
  43 + long msb = 0;
  44 + long lsb = 0;
  45 + assert data.length == 16 : "data must be 16 bytes in length";
  46 + for (int i = 0; i < 8; i++)
  47 + {
  48 + msb = (msb << 8) | (data[i] & 0xff);
  49 + }
  50 + for (int i = 8; i < 16; i++)
  51 + {
  52 + lsb = (lsb << 8) | (data[i] & 0xff);
  53 + }
  54 + this.mostSigBits = msb;
  55 + this.leastSigBits = lsb;
  56 + }
  57 +
  58 + /**
  59 + * 使用指定的数据构造新的 UUID。
  60 + *
  61 + * @param mostSigBits 用于 {@code UUID} 的最高有效 64 位
  62 + * @param leastSigBits 用于 {@code UUID} 的最低有效 64 位
  63 + */
  64 + public UUID(long mostSigBits, long leastSigBits)
  65 + {
  66 + this.mostSigBits = mostSigBits;
  67 + this.leastSigBits = leastSigBits;
  68 + }
  69 +
  70 + /**
  71 + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。
  72 + *
  73 + * @return 随机生成的 {@code UUID}
  74 + */
  75 + public static UUID fastUUID()
  76 + {
  77 + return randomUUID(false);
  78 + }
  79 +
  80 + /**
  81 + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
  82 + *
  83 + * @return 随机生成的 {@code UUID}
  84 + */
  85 + public static UUID randomUUID()
  86 + {
  87 + return randomUUID(true);
  88 + }
  89 +
  90 + /**
  91 + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
  92 + *
  93 + * @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能
  94 + * @return 随机生成的 {@code UUID}
  95 + */
  96 + public static UUID randomUUID(boolean isSecure)
  97 + {
  98 + final Random ng = isSecure ? Holder.numberGenerator : getRandom();
  99 +
  100 + byte[] randomBytes = new byte[16];
  101 + ng.nextBytes(randomBytes);
  102 + randomBytes[6] &= 0x0f; /* clear version */
  103 + randomBytes[6] |= 0x40; /* set to version 4 */
  104 + randomBytes[8] &= 0x3f; /* clear variant */
  105 + randomBytes[8] |= 0x80; /* set to IETF variant */
  106 + return new UUID(randomBytes);
  107 + }
  108 +
  109 + /**
  110 + * 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。
  111 + *
  112 + * @param name 用于构造 UUID 的字节数组。
  113 + *
  114 + * @return 根据指定数组生成的 {@code UUID}
  115 + */
  116 + public static UUID nameUUIDFromBytes(byte[] name)
  117 + {
  118 + MessageDigest md;
  119 + try
  120 + {
  121 + md = MessageDigest.getInstance("MD5");
  122 + }
  123 + catch (NoSuchAlgorithmException nsae)
  124 + {
  125 + throw new InternalError("MD5 not supported");
  126 + }
  127 + byte[] md5Bytes = md.digest(name);
  128 + md5Bytes[6] &= 0x0f; /* clear version */
  129 + md5Bytes[6] |= 0x30; /* set to version 3 */
  130 + md5Bytes[8] &= 0x3f; /* clear variant */
  131 + md5Bytes[8] |= 0x80; /* set to IETF variant */
  132 + return new UUID(md5Bytes);
  133 + }
  134 +
  135 + /**
  136 + * 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。
  137 + *
  138 + * @param name 指定 {@code UUID} 字符串
  139 + * @return 具有指定值的 {@code UUID}
  140 + * @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常
  141 + *
  142 + */
  143 + public static UUID fromString(String name)
  144 + {
  145 + String[] components = name.split("-");
  146 + if (components.length != 5)
  147 + {
  148 + throw new IllegalArgumentException("Invalid UUID string: " + name);
  149 + }
  150 + for (int i = 0; i < 5; i++)
  151 + {
  152 + components[i] = "0x" + components[i];
  153 + }
  154 +
  155 + long mostSigBits = Long.decode(components[0]).longValue();
  156 + mostSigBits <<= 16;
  157 + mostSigBits |= Long.decode(components[1]).longValue();
  158 + mostSigBits <<= 16;
  159 + mostSigBits |= Long.decode(components[2]).longValue();
  160 +
  161 + long leastSigBits = Long.decode(components[3]).longValue();
  162 + leastSigBits <<= 48;
  163 + leastSigBits |= Long.decode(components[4]).longValue();
  164 +
  165 + return new UUID(mostSigBits, leastSigBits);
  166 + }
  167 +
  168 + /**
  169 + * 返回此 UUID 的 128 位值中的最低有效 64 位。
  170 + *
  171 + * @return 此 UUID 的 128 位值中的最低有效 64 位。
  172 + */
  173 + public long getLeastSignificantBits()
  174 + {
  175 + return leastSigBits;
  176 + }
  177 +
  178 + /**
  179 + * 返回此 UUID 的 128 位值中的最高有效 64 位。
  180 + *
  181 + * @return 此 UUID 的 128 位值中最高有效 64 位。
  182 + */
  183 + public long getMostSignificantBits()
  184 + {
  185 + return mostSigBits;
  186 + }
  187 +
  188 + /**
  189 + * 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。
  190 + * <p>
  191 + * 版本号具有以下含意:
  192 + * <ul>
  193 + * <li>1 基于时间的 UUID
  194 + * <li>2 DCE 安全 UUID
  195 + * <li>3 基于名称的 UUID
  196 + * <li>4 随机生成的 UUID
  197 + * </ul>
  198 + *
  199 + * @return 此 {@code UUID} 的版本号
  200 + */
  201 + public int version()
  202 + {
  203 + // Version is bits masked by 0x000000000000F000 in MS long
  204 + return (int) ((mostSigBits >> 12) & 0x0f);
  205 + }
  206 +
  207 + /**
  208 + * 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。
  209 + * <p>
  210 + * 变体号具有以下含意:
  211 + * <ul>
  212 + * <li>0 为 NCS 向后兼容保留
  213 + * <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>(Leach-Salz), 用于此类
  214 + * <li>6 保留,微软向后兼容
  215 + * <li>7 保留供以后定义使用
  216 + * </ul>
  217 + *
  218 + * @return 此 {@code UUID} 相关联的变体号
  219 + */
  220 + public int variant()
  221 + {
  222 + // This field is composed of a varying number of bits.
  223 + // 0 - - Reserved for NCS backward compatibility
  224 + // 1 0 - The IETF aka Leach-Salz variant (used by this class)
  225 + // 1 1 0 Reserved, Microsoft backward compatibility
  226 + // 1 1 1 Reserved for future definition.
  227 + return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
  228 + }
  229 +
  230 + /**
  231 + * 与此 UUID 相关联的时间戳值。
  232 + *
  233 + * <p>
  234 + * 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br>
  235 + * 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。
  236 + *
  237 + * <p>
  238 + * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
  239 + * 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
  240 + *
  241 + * @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。
  242 + */
  243 + public long timestamp() throws UnsupportedOperationException
  244 + {
  245 + checkTimeBase();
  246 + return (mostSigBits & 0x0FFFL) << 48//
  247 + | ((mostSigBits >> 16) & 0x0FFFFL) << 32//
  248 + | mostSigBits >>> 32;
  249 + }
  250 +
  251 + /**
  252 + * 与此 UUID 相关联的时钟序列值。
  253 + *
  254 + * <p>
  255 + * 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。
  256 + * <p>
  257 + * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出
  258 + * UnsupportedOperationException。
  259 + *
  260 + * @return 此 {@code UUID} 的时钟序列
  261 + *
  262 + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
  263 + */
  264 + public int clockSequence() throws UnsupportedOperationException
  265 + {
  266 + checkTimeBase();
  267 + return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
  268 + }
  269 +
  270 + /**
  271 + * 与此 UUID 相关的节点值。
  272 + *
  273 + * <p>
  274 + * 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。
  275 + * <p>
  276 + * 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
  277 + * 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
  278 + *
  279 + * @return 此 {@code UUID} 的节点值
  280 + *
  281 + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
  282 + */
  283 + public long node() throws UnsupportedOperationException
  284 + {
  285 + checkTimeBase();
  286 + return leastSigBits & 0x0000FFFFFFFFFFFFL;
  287 + }
  288 +
  289 + /**
  290 + * 返回此{@code UUID} 的字符串表现形式。
  291 + *
  292 + * <p>
  293 + * UUID 的字符串表示形式由此 BNF 描述:
  294 + *
  295 + * <pre>
  296 + * {@code
  297 + * UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
  298 + * time_low = 4*<hexOctet>
  299 + * time_mid = 2*<hexOctet>
  300 + * time_high_and_version = 2*<hexOctet>
  301 + * variant_and_sequence = 2*<hexOctet>
  302 + * node = 6*<hexOctet>
  303 + * hexOctet = <hexDigit><hexDigit>
  304 + * hexDigit = [0-9a-fA-F]
  305 + * }
  306 + * </pre>
  307 + *
  308 + * </blockquote>
  309 + *
  310 + * @return 此{@code UUID} 的字符串表现形式
  311 + * @see #toString(boolean)
  312 + */
  313 + @Override
  314 + public String toString()
  315 + {
  316 + return toString(false);
  317 + }
  318 +
  319 + /**
  320 + * 返回此{@code UUID} 的字符串表现形式。
  321 + *
  322 + * <p>
  323 + * UUID 的字符串表示形式由此 BNF 描述:
  324 + *
  325 + * <pre>
  326 + * {@code
  327 + * UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
  328 + * time_low = 4*<hexOctet>
  329 + * time_mid = 2*<hexOctet>
  330 + * time_high_and_version = 2*<hexOctet>
  331 + * variant_and_sequence = 2*<hexOctet>
  332 + * node = 6*<hexOctet>
  333 + * hexOctet = <hexDigit><hexDigit>
  334 + * hexDigit = [0-9a-fA-F]
  335 + * }
  336 + * </pre>
  337 + *
  338 + * </blockquote>
  339 + *
  340 + * @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串
  341 + * @return 此{@code UUID} 的字符串表现形式
  342 + */
  343 + public String toString(boolean isSimple)
  344 + {
  345 + final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
  346 + // time_low
  347 + builder.append(digits(mostSigBits >> 32, 8));
  348 + if (!isSimple)
  349 + {
  350 + builder.append('-');
  351 + }
  352 + // time_mid
  353 + builder.append(digits(mostSigBits >> 16, 4));
  354 + if (!isSimple)
  355 + {
  356 + builder.append('-');
  357 + }
  358 + // time_high_and_version
  359 + builder.append(digits(mostSigBits, 4));
  360 + if (!isSimple)
  361 + {
  362 + builder.append('-');
  363 + }
  364 + // variant_and_sequence
  365 + builder.append(digits(leastSigBits >> 48, 4));
  366 + if (!isSimple)
  367 + {
  368 + builder.append('-');
  369 + }
  370 + // node
  371 + builder.append(digits(leastSigBits, 12));
  372 +
  373 + return builder.toString();
  374 + }
  375 +
  376 + /**
  377 + * 返回此 UUID 的哈希码。
  378 + *
  379 + * @return UUID 的哈希码值。
  380 + */
  381 + @Override
  382 + public int hashCode()
  383 + {
  384 + long hilo = mostSigBits ^ leastSigBits;
  385 + return ((int) (hilo >> 32)) ^ (int) hilo;
  386 + }
  387 +
  388 + /**
  389 + * 将此对象与指定对象比较。
  390 + * <p>
  391 + * 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。
  392 + *
  393 + * @param obj 要与之比较的对象
  394 + *
  395 + * @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
  396 + */
  397 + @Override
  398 + public boolean equals(Object obj)
  399 + {
  400 + if ((null == obj) || (obj.getClass() != UUID.class))
  401 + {
  402 + return false;
  403 + }
  404 + UUID id = (UUID) obj;
  405 + return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
  406 + }
  407 +
  408 + // Comparison Operations
  409 +
  410 + /**
  411 + * 将此 UUID 与指定的 UUID 比较。
  412 + *
  413 + * <p>
  414 + * 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。
  415 + *
  416 + * @param val 与此 UUID 比较的 UUID
  417 + *
  418 + * @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
  419 + *
  420 + */
  421 + @Override
  422 + public int compareTo(UUID val)
  423 + {
  424 + // The ordering is intentionally set up so that the UUIDs
  425 + // can simply be numerically compared as two numbers
  426 + return (this.mostSigBits < val.mostSigBits ? -1 : //
  427 + (this.mostSigBits > val.mostSigBits ? 1 : //
  428 + (this.leastSigBits < val.leastSigBits ? -1 : //
  429 + (this.leastSigBits > val.leastSigBits ? 1 : //
  430 + 0))));
  431 + }
  432 +
  433 + // -------------------------------------------------------------------------------------------------------------------
  434 + // Private method start
  435 + /**
  436 + * 返回指定数字对应的hex值
  437 + *
  438 + * @param val 值
  439 + * @param digits 位
  440 + * @return 值
  441 + */
  442 + private static String digits(long val, int digits)
  443 + {
  444 + long hi = 1L << (digits * 4);
  445 + return Long.toHexString(hi | (val & (hi - 1))).substring(1);
  446 + }
  447 +
  448 + /**
  449 + * 检查是否为time-based版本UUID
  450 + */
  451 + private void checkTimeBase()
  452 + {
  453 + if (version() != 1)
  454 + {
  455 + throw new UnsupportedOperationException("Not a time-based UUID");
  456 + }
  457 + }
  458 +
  459 + /**
  460 + * 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG)
  461 + *
  462 + * @return {@link SecureRandom}
  463 + */
  464 + public static SecureRandom getSecureRandom()
  465 + {
  466 + try
  467 + {
  468 + return SecureRandom.getInstance("SHA1PRNG");
  469 + }
  470 + catch (NoSuchAlgorithmException e)
  471 + {
  472 + throw new UtilException(e);
  473 + }
  474 + }
  475 +
  476 + /**
  477 + * 获取随机数生成器对象<br>
  478 + * ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。
  479 + *
  480 + * @return {@link ThreadLocalRandom}
  481 + */
  482 + public static ThreadLocalRandom getRandom()
  483 + {
  484 + return ThreadLocalRandom.current();
  485 + }
  486 +}
  1 +package com.zhonglai.luhui.util.xss;
  2 +
  3 +import javax.validation.Constraint;
  4 +import javax.validation.Payload;
  5 +import java.lang.annotation.ElementType;
  6 +import java.lang.annotation.Retention;
  7 +import java.lang.annotation.RetentionPolicy;
  8 +import java.lang.annotation.Target;
  9 +
  10 +/**
  11 + * 自定义xss校验注解
  12 + *
  13 + * @author ruoyi
  14 + */
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
  17 +@Constraint(validatedBy = { XssValidator.class })
  18 +public @interface Xss
  19 +{
  20 + String message()
  21 +
  22 + default "不允许任何脚本运行";
  23 +
  24 + Class<?>[] groups() default {};
  25 +
  26 + Class<? extends Payload>[] payload() default {};
  27 +}
  1 +package com.zhonglai.luhui.util.xss;
  2 +
  3 +
  4 +import org.apache.commons.lang3.StringUtils;
  5 +
  6 +import javax.validation.ConstraintValidator;
  7 +import javax.validation.ConstraintValidatorContext;
  8 +import java.util.regex.Matcher;
  9 +import java.util.regex.Pattern;
  10 +
  11 +/**
  12 + * 自定义xss校验注解实现
  13 + *
  14 + * @author ruoyi
  15 + */
  16 +public class XssValidator implements ConstraintValidator<Xss, String>
  17 +{
  18 + private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";
  19 +
  20 + @Override
  21 + public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext)
  22 + {
  23 + if (StringUtils.isBlank(value))
  24 + {
  25 + return true;
  26 + }
  27 + return !containsHtml(value);
  28 + }
  29 +
  30 + public static boolean containsHtml(String value)
  31 + {
  32 + Pattern pattern = Pattern.compile(HTML_PATTERN);
  33 + Matcher matcher = pattern.matcher(value);
  34 + return matcher.matches();
  35 + }
  36 +}
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <modelVersion>4.0.0</modelVersion>
  6 + <parent>
  7 + <groupId>com.zhonglai.luhui</groupId>
  8 + <artifactId>lh-common</artifactId>
  9 + <version>1.0.0</version>
  10 + </parent>
  11 +
  12 + <artifactId>lh-domain</artifactId>
  13 + <description>数据库表实体类</description>
  14 +
  15 + <properties>
  16 + <maven.compiler.source>8</maven.compiler.source>
  17 + <maven.compiler.target>8</maven.compiler.target>
  18 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  19 + </properties>
  20 +
  21 + <dependencies>
  22 + <!-- 文档 -->
  23 + <dependency >
  24 + <groupId>io.springfox</groupId>
  25 + <artifactId>springfox-swagger2</artifactId>
  26 + <version>${swagger.version}</version>
  27 + <exclusions>
  28 + <exclusion>
  29 + <groupId>io.swagger</groupId>
  30 + <artifactId>swagger-models</artifactId>
  31 + </exclusion>
  32 + <exclusion>
  33 + <groupId>com.google.guava</groupId>
  34 + <artifactId>guava</artifactId>
  35 + </exclusion>
  36 + </exclusions>
  37 + </dependency>
  38 + <!--常用工具类 -->
  39 + <dependency>
  40 + <groupId>org.apache.commons</groupId>
  41 + <artifactId>commons-lang3</artifactId>
  42 + </dependency>
  43 + <dependency>
  44 + <groupId>com.zhonglai.luhui</groupId>
  45 + <artifactId>lh-common-util</artifactId>
  46 + </dependency>
  47 + </dependencies>
  48 +</project>
  1 +package com.zhonglai.luhui.domain.cb;
  2 +
  3 +
  4 +import com.zhonglai.luhui.util.sql.BaseEntity;
  5 +import io.swagger.annotations.ApiModel;
  6 +import io.swagger.annotations.ApiModelProperty;
  7 +import org.apache.commons.lang3.builder.ToStringBuilder;
  8 +import org.apache.commons.lang3.builder.ToStringStyle;
  9 +
  10 +/**
  11 + * 标粗结转成本表对象 cb_bold_closing_cost
  12 + *
  13 + * @author 钟来
  14 + * @date 2024-04-11
  15 + */
  16 +@ApiModel("标粗结转成本表")
  17 +public class CbBoldClosingCost extends BaseEntity
  18 +{
  19 + private static final long serialVersionUID = 1L;
  20 +
  21 + /** 主键ID,自增长 */
  22 + @ApiModelProperty("主键ID,自增长")
  23 + private Integer id;
  24 +
  25 + /** 养殖场 */
  26 + @ApiModelProperty("养殖场")
  27 + private String farm_name;
  28 +
  29 + /** 养殖造次 */
  30 + @ApiModelProperty("养殖造次")
  31 + private String breeding_round;
  32 +
  33 + /** 养殖区域 */
  34 + @ApiModelProperty("养殖区域")
  35 + private String breeding_area;
  36 +
  37 + /** 塘口/箱号 */
  38 + @ApiModelProperty("塘口/箱号")
  39 + private String pond_or_box;
  40 +
  41 + /** 养殖品种 */
  42 + @ApiModelProperty("养殖品种")
  43 + private String breeding_species;
  44 +
  45 + /** 分苗日期 */
  46 + @ApiModelProperty("分苗日期")
  47 + private java.util.Date seedling_info_date;
  48 +
  49 + /** 分苗数量 */
  50 + @ApiModelProperty("分苗数量")
  51 + private java.math.BigDecimal seedling_quantity;
  52 +
  53 + /** 分苗重量 */
  54 + @ApiModelProperty("分苗重量")
  55 + private java.math.BigDecimal seedling_weight;
  56 +
  57 + /** 分苗规格 */
  58 + @ApiModelProperty("分苗规格")
  59 + private String seedling_specification;
  60 +
  61 + /** 变动成本 */
  62 + @ApiModelProperty("变动成本")
  63 + private java.math.BigDecimal variable_costs;
  64 +
  65 + /** 种苗成本 */
  66 + @ApiModelProperty("种苗成本")
  67 + private java.math.BigDecimal seedling_cost;
  68 +
  69 + /** 饲料数量(kg) */
  70 + @ApiModelProperty("饲料数量(kg)")
  71 + private java.math.BigDecimal feed_quantity;
  72 +
  73 + /** 饲料金额 */
  74 + @ApiModelProperty("饲料金额")
  75 + private java.math.BigDecimal feed_amount;
  76 +
  77 + /** 动保 */
  78 + @ApiModelProperty("动保")
  79 + private java.math.BigDecimal animal_health_protection;
  80 +
  81 + /** 电费 */
  82 + @ApiModelProperty("电费")
  83 + private java.math.BigDecimal electricity_fee;
  84 +
  85 + /** 人工 */
  86 + @ApiModelProperty("人工")
  87 + private java.math.BigDecimal labor_cost;
  88 +
  89 + /** 低值易耗品 */
  90 + @ApiModelProperty("低值易耗品")
  91 + private java.math.BigDecimal consumables_cost;
  92 +
  93 + /** 拉网费 */
  94 + @ApiModelProperty("拉网费")
  95 + private java.math.BigDecimal netting_fee;
  96 +
  97 + /** 折旧与摊销 */
  98 + @ApiModelProperty("折旧与摊销")
  99 + private java.math.BigDecimal depreciation_and_amortization;
  100 +
  101 + /** 修理费 */
  102 + @ApiModelProperty("修理费")
  103 + private java.math.BigDecimal repair_fee;
  104 +
  105 + /** 燃料费 */
  106 + @ApiModelProperty("燃料费")
  107 + private java.math.BigDecimal fuel_fee;
  108 +
  109 + /** 租赁费 */
  110 + @ApiModelProperty("租赁费")
  111 + private java.math.BigDecimal lease_fee;
  112 +
  113 + /** 其他公摊 */
  114 + @ApiModelProperty("其他公摊")
  115 + private java.math.BigDecimal other_shared_costs;
  116 +
  117 + /** 定额费用 */
  118 + @ApiModelProperty("定额费用")
  119 + private java.math.BigDecimal fixed_costs;
  120 +
  121 + /** 网箱折旧费 */
  122 + @ApiModelProperty("网箱折旧费")
  123 + private java.math.BigDecimal cage_depreciation_fee;
  124 +
  125 + /** 网箱管理费 */
  126 + @ApiModelProperty("网箱管理费")
  127 + private java.math.BigDecimal cage_management_fee;
  128 +
  129 + /** 海域费 */
  130 + @ApiModelProperty("海域费")
  131 + private java.math.BigDecimal sea_area_fee;
  132 +
  133 + /** 塘租 */
  134 + @ApiModelProperty("塘租")
  135 + private java.math.BigDecimal pond_rent;
  136 +
  137 + /** 合计 */
  138 + @ApiModelProperty("合计")
  139 + private java.math.BigDecimal total_cost;
  140 +
  141 + public void setId(Integer id)
  142 + {
  143 + this.id = id;
  144 + }
  145 +
  146 + public Integer getId()
  147 + {
  148 + return id;
  149 + }
  150 + public void setFarm_name(String farm_name)
  151 + {
  152 + this.farm_name = farm_name;
  153 + }
  154 +
  155 + public String getFarm_name()
  156 + {
  157 + return farm_name;
  158 + }
  159 + public void setBreeding_round(String breeding_round)
  160 + {
  161 + this.breeding_round = breeding_round;
  162 + }
  163 +
  164 + public String getBreeding_round()
  165 + {
  166 + return breeding_round;
  167 + }
  168 + public void setBreeding_area(String breeding_area)
  169 + {
  170 + this.breeding_area = breeding_area;
  171 + }
  172 +
  173 + public String getBreeding_area()
  174 + {
  175 + return breeding_area;
  176 + }
  177 + public void setPond_or_box(String pond_or_box)
  178 + {
  179 + this.pond_or_box = pond_or_box;
  180 + }
  181 +
  182 + public String getPond_or_box()
  183 + {
  184 + return pond_or_box;
  185 + }
  186 + public void setBreeding_species(String breeding_species)
  187 + {
  188 + this.breeding_species = breeding_species;
  189 + }
  190 +
  191 + public String getBreeding_species()
  192 + {
  193 + return breeding_species;
  194 + }
  195 + public void setSeedling_info_date(java.util.Date seedling_info_date)
  196 + {
  197 + this.seedling_info_date = seedling_info_date;
  198 + }
  199 +
  200 + public java.util.Date getSeedling_info_date()
  201 + {
  202 + return seedling_info_date;
  203 + }
  204 + public void setSeedling_quantity(java.math.BigDecimal seedling_quantity)
  205 + {
  206 + this.seedling_quantity = seedling_quantity;
  207 + }
  208 +
  209 + public java.math.BigDecimal getSeedling_quantity()
  210 + {
  211 + return seedling_quantity;
  212 + }
  213 + public void setSeedling_weight(java.math.BigDecimal seedling_weight)
  214 + {
  215 + this.seedling_weight = seedling_weight;
  216 + }
  217 +
  218 + public java.math.BigDecimal getSeedling_weight()
  219 + {
  220 + return seedling_weight;
  221 + }
  222 + public void setSeedling_specification(String seedling_specification)
  223 + {
  224 + this.seedling_specification = seedling_specification;
  225 + }
  226 +
  227 + public String getSeedling_specification()
  228 + {
  229 + return seedling_specification;
  230 + }
  231 + public void setVariable_costs(java.math.BigDecimal variable_costs)
  232 + {
  233 + this.variable_costs = variable_costs;
  234 + }
  235 +
  236 + public java.math.BigDecimal getVariable_costs()
  237 + {
  238 + return variable_costs;
  239 + }
  240 + public void setSeedling_cost(java.math.BigDecimal seedling_cost)
  241 + {
  242 + this.seedling_cost = seedling_cost;
  243 + }
  244 +
  245 + public java.math.BigDecimal getSeedling_cost()
  246 + {
  247 + return seedling_cost;
  248 + }
  249 + public void setFeed_quantity(java.math.BigDecimal feed_quantity)
  250 + {
  251 + this.feed_quantity = feed_quantity;
  252 + }
  253 +
  254 + public java.math.BigDecimal getFeed_quantity()
  255 + {
  256 + return feed_quantity;
  257 + }
  258 + public void setFeed_amount(java.math.BigDecimal feed_amount)
  259 + {
  260 + this.feed_amount = feed_amount;
  261 + }
  262 +
  263 + public java.math.BigDecimal getFeed_amount()
  264 + {
  265 + return feed_amount;
  266 + }
  267 + public void setAnimal_health_protection(java.math.BigDecimal animal_health_protection)
  268 + {
  269 + this.animal_health_protection = animal_health_protection;
  270 + }
  271 +
  272 + public java.math.BigDecimal getAnimal_health_protection()
  273 + {
  274 + return animal_health_protection;
  275 + }
  276 + public void setElectricity_fee(java.math.BigDecimal electricity_fee)
  277 + {
  278 + this.electricity_fee = electricity_fee;
  279 + }
  280 +
  281 + public java.math.BigDecimal getElectricity_fee()
  282 + {
  283 + return electricity_fee;
  284 + }
  285 + public void setLabor_cost(java.math.BigDecimal labor_cost)
  286 + {
  287 + this.labor_cost = labor_cost;
  288 + }
  289 +
  290 + public java.math.BigDecimal getLabor_cost()
  291 + {
  292 + return labor_cost;
  293 + }
  294 + public void setConsumables_cost(java.math.BigDecimal consumables_cost)
  295 + {
  296 + this.consumables_cost = consumables_cost;
  297 + }
  298 +
  299 + public java.math.BigDecimal getConsumables_cost()
  300 + {
  301 + return consumables_cost;
  302 + }
  303 + public void setNetting_fee(java.math.BigDecimal netting_fee)
  304 + {
  305 + this.netting_fee = netting_fee;
  306 + }
  307 +
  308 + public java.math.BigDecimal getNetting_fee()
  309 + {
  310 + return netting_fee;
  311 + }
  312 + public void setDepreciation_and_amortization(java.math.BigDecimal depreciation_and_amortization)
  313 + {
  314 + this.depreciation_and_amortization = depreciation_and_amortization;
  315 + }
  316 +
  317 + public java.math.BigDecimal getDepreciation_and_amortization()
  318 + {
  319 + return depreciation_and_amortization;
  320 + }
  321 + public void setRepair_fee(java.math.BigDecimal repair_fee)
  322 + {
  323 + this.repair_fee = repair_fee;
  324 + }
  325 +
  326 + public java.math.BigDecimal getRepair_fee()
  327 + {
  328 + return repair_fee;
  329 + }
  330 + public void setFuel_fee(java.math.BigDecimal fuel_fee)
  331 + {
  332 + this.fuel_fee = fuel_fee;
  333 + }
  334 +
  335 + public java.math.BigDecimal getFuel_fee()
  336 + {
  337 + return fuel_fee;
  338 + }
  339 + public void setLease_fee(java.math.BigDecimal lease_fee)
  340 + {
  341 + this.lease_fee = lease_fee;
  342 + }
  343 +
  344 + public java.math.BigDecimal getLease_fee()
  345 + {
  346 + return lease_fee;
  347 + }
  348 + public void setOther_shared_costs(java.math.BigDecimal other_shared_costs)
  349 + {
  350 + this.other_shared_costs = other_shared_costs;
  351 + }
  352 +
  353 + public java.math.BigDecimal getOther_shared_costs()
  354 + {
  355 + return other_shared_costs;
  356 + }
  357 + public void setFixed_costs(java.math.BigDecimal fixed_costs)
  358 + {
  359 + this.fixed_costs = fixed_costs;
  360 + }
  361 +
  362 + public java.math.BigDecimal getFixed_costs()
  363 + {
  364 + return fixed_costs;
  365 + }
  366 + public void setCage_depreciation_fee(java.math.BigDecimal cage_depreciation_fee)
  367 + {
  368 + this.cage_depreciation_fee = cage_depreciation_fee;
  369 + }
  370 +
  371 + public java.math.BigDecimal getCage_depreciation_fee()
  372 + {
  373 + return cage_depreciation_fee;
  374 + }
  375 + public void setCage_management_fee(java.math.BigDecimal cage_management_fee)
  376 + {
  377 + this.cage_management_fee = cage_management_fee;
  378 + }
  379 +
  380 + public java.math.BigDecimal getCage_management_fee()
  381 + {
  382 + return cage_management_fee;
  383 + }
  384 + public void setSea_area_fee(java.math.BigDecimal sea_area_fee)
  385 + {
  386 + this.sea_area_fee = sea_area_fee;
  387 + }
  388 +
  389 + public java.math.BigDecimal getSea_area_fee()
  390 + {
  391 + return sea_area_fee;
  392 + }
  393 + public void setPond_rent(java.math.BigDecimal pond_rent)
  394 + {
  395 + this.pond_rent = pond_rent;
  396 + }
  397 +
  398 + public java.math.BigDecimal getPond_rent()
  399 + {
  400 + return pond_rent;
  401 + }
  402 + public void setTotal_cost(java.math.BigDecimal total_cost)
  403 + {
  404 + this.total_cost = total_cost;
  405 + }
  406 +
  407 + public java.math.BigDecimal getTotal_cost()
  408 + {
  409 + return total_cost;
  410 + }
  411 +
  412 + @Override
  413 + public String toString() {
  414 + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
  415 + .append("id", getId())
  416 + .append("farm_name", getFarm_name())
  417 + .append("breeding_round", getBreeding_round())
  418 + .append("breeding_area", getBreeding_area())
  419 + .append("pond_or_box", getPond_or_box())
  420 + .append("breeding_species", getBreeding_species())
  421 + .append("seedling_info_date", getSeedling_info_date())
  422 + .append("seedling_quantity", getSeedling_quantity())
  423 + .append("seedling_weight", getSeedling_weight())
  424 + .append("seedling_specification", getSeedling_specification())
  425 + .append("variable_costs", getVariable_costs())
  426 + .append("seedling_cost", getSeedling_cost())
  427 + .append("feed_quantity", getFeed_quantity())
  428 + .append("feed_amount", getFeed_amount())
  429 + .append("animal_health_protection", getAnimal_health_protection())
  430 + .append("electricity_fee", getElectricity_fee())
  431 + .append("labor_cost", getLabor_cost())
  432 + .append("consumables_cost", getConsumables_cost())
  433 + .append("netting_fee", getNetting_fee())
  434 + .append("depreciation_and_amortization", getDepreciation_and_amortization())
  435 + .append("repair_fee", getRepair_fee())
  436 + .append("fuel_fee", getFuel_fee())
  437 + .append("lease_fee", getLease_fee())
  438 + .append("other_shared_costs", getOther_shared_costs())
  439 + .append("fixed_costs", getFixed_costs())
  440 + .append("cage_depreciation_fee", getCage_depreciation_fee())
  441 + .append("cage_management_fee", getCage_management_fee())
  442 + .append("sea_area_fee", getSea_area_fee())
  443 + .append("pond_rent", getPond_rent())
  444 + .append("total_cost", getTotal_cost())
  445 + .toString();
  446 + }
  447 +}
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <modelVersion>4.0.0</modelVersion>
  6 + <parent>
  7 + <groupId>com.zhonglai.luhui</groupId>
  8 + <artifactId>lh-common</artifactId>
  9 + <version>1.0.0</version>
  10 + </parent>
  11 +
  12 + <artifactId>lh-jedis-redis</artifactId>
  13 + <description>redis连接池操作</description>
  14 +
  15 + <properties>
  16 + <maven.compiler.source>8</maven.compiler.source>
  17 + <maven.compiler.target>8</maven.compiler.target>
  18 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  19 + </properties>
  20 +
  21 + <dependencies>
  22 + <dependency>
  23 + <groupId>redis.clients</groupId>
  24 + <artifactId>jedis</artifactId>
  25 + </dependency>
  26 + </dependencies>
  27 +
  28 +</project>
  1 +package com.zhonglai.luhui.redis.config;
  2 +
  3 +import com.zhonglai.luhui.redis.service.RedisService;
  4 +import redis.clients.jedis.JedisPoolConfig;
  5 +
  6 +import java.io.File;
  7 +import java.io.FileInputStream;
  8 +import java.io.IOException;
  9 +import java.io.InputStream;
  10 +import java.util.Properties;
  11 +
  12 +public class RedisConfig {
  13 + private String host = "127.0.0.1";
  14 + private Integer port = 6379;
  15 +
  16 + private String user;
  17 + private String password;
  18 +
  19 + private Integer timeout;
  20 +
  21 + private Integer database;
  22 +
  23 + private JedisPoolConfig poolConfig;
  24 +
  25 + private String propertiesPath;
  26 +
  27 + public RedisConfig()
  28 + {
  29 + init();
  30 + }
  31 +
  32 + public RedisConfig(String propertiesPath)
  33 + {
  34 + this.propertiesPath = propertiesPath;
  35 + init();
  36 + }
  37 +
  38 + public void init(Properties properties)
  39 + {
  40 + poolConfig = new JedisPoolConfig();
  41 + // 设置连接池参数
  42 + poolConfig.setMaxTotal(Integer.parseInt(properties.getProperty("jedis.pool.maxTotal"))); // 最多的连接个数
  43 + poolConfig.setMaxIdle(Integer.parseInt(properties.getProperty("jedis.pool.maxIdle"))); // 最多空闲的连接个数
  44 + poolConfig.setMinIdle(Integer.parseInt(properties.getProperty("jedis.pool.minIdle"))); // 最小空闲的连接个数
  45 + poolConfig.setTestOnBorrow(Boolean.parseBoolean(properties.getProperty("jedis.pool.testOnBorrow"))); // 在获取连接对象时是否验证该连接对象的连通性
  46 + poolConfig.setTestOnReturn(Boolean.parseBoolean(properties.getProperty("jedis.pool.testOnReturn")));
  47 + poolConfig.setTestWhileIdle(Boolean.parseBoolean(properties.getProperty("jedis.pool.testWhileIdle")));
  48 + poolConfig.setMinEvictableIdleTimeMillis(Long.parseLong(properties.getProperty("jedis.pool.minEvictableIdleTimeMillis")));
  49 + poolConfig.setTimeBetweenEvictionRunsMillis(Long.parseLong(properties.getProperty("jedis.pool.timeBetweenEvictionRunsMillis")));
  50 + poolConfig.setNumTestsPerEvictionRun(Integer.parseInt(properties.getProperty("jedis.pool.numTestsPerEvictionRun")));
  51 + poolConfig.setBlockWhenExhausted(Boolean.parseBoolean(properties.getProperty("jedis.pool.blockWhenExhausted")));
  52 +
  53 + host = properties.getProperty("jedis.host");
  54 + port = Integer.parseInt(properties.getProperty("jedis.port"));
  55 + timeout = Integer.parseInt(properties.getProperty("jedis.timeout"));
  56 + password = properties.getProperty("jedis.password");
  57 + user = properties.getProperty("jedis.user");
  58 + database = Integer.parseInt(null!=properties.getProperty("jedis.database")?properties.getProperty("jedis.database"):"0");
  59 + }
  60 +
  61 + public void init()
  62 + {
  63 + Properties properties = loadProperties();
  64 + init(properties);
  65 + }
  66 +
  67 + private Properties loadProperties()
  68 + {
  69 + if(null != propertiesPath && !"".equals(propertiesPath))
  70 + {
  71 + Properties properties = new Properties();
  72 + try {
  73 + properties.load(new FileInputStream(propertiesPath));
  74 + return properties;
  75 + } catch (IOException e) {
  76 + throw new RuntimeException(e);
  77 + }
  78 + }
  79 + return loadDefaultProperties();
  80 + }
  81 +
  82 +
  83 +
  84 + private Properties loadDefaultProperties()
  85 + {
  86 + // 加载属性文件
  87 + Properties properties = new Properties();
  88 + try (InputStream input = RedisService.class.getClassLoader().getResourceAsStream("jedis.properties")) {
  89 + if (input == null) {
  90 + System.out.println("Cannot find jedis.properties file in the classpath");
  91 + return properties;
  92 + }
  93 + properties.load(input);
  94 + } catch (IOException ex) {
  95 + ex.printStackTrace();
  96 + }
  97 + return properties;
  98 + }
  99 +
  100 + public String getHost() {
  101 + return host;
  102 + }
  103 +
  104 + public void setHost(String host) {
  105 + this.host = host;
  106 + }
  107 +
  108 + public Integer getPort() {
  109 + return port;
  110 + }
  111 +
  112 + public void setPort(Integer port) {
  113 + this.port = port;
  114 + }
  115 +
  116 + public String getPassword() {
  117 + return password;
  118 + }
  119 +
  120 + public void setPassword(String password) {
  121 + this.password = password;
  122 + }
  123 +
  124 + public Integer getTimeout() {
  125 + return timeout;
  126 + }
  127 +
  128 + public void setTimeout(Integer timeout) {
  129 + this.timeout = timeout;
  130 + }
  131 +
  132 + public JedisPoolConfig getPoolConfig() {
  133 + return poolConfig;
  134 + }
  135 +
  136 + public void setPoolConfig(JedisPoolConfig poolConfig) {
  137 + this.poolConfig = poolConfig;
  138 + }
  139 +
  140 + public Integer getDatabase() {
  141 + return database;
  142 + }
  143 +
  144 + public void setDatabase(Integer database) {
  145 + this.database = database;
  146 + }
  147 +
  148 + public String getUser() {
  149 + return user;
  150 + }
  151 +
  152 + public void setUser(String user) {
  153 + this.user = user;
  154 + }
  155 +}
  1 +package com.zhonglai.luhui.redis.service;
  2 +
  3 +import com.zhonglai.luhui.redis.config.RedisConfig;
  4 +import redis.clients.jedis.Jedis;
  5 +import redis.clients.jedis.JedisPool;
  6 +
  7 +public class RedisService {
  8 +
  9 + private JedisPool jedisPool;
  10 +
  11 + public RedisService(RedisConfig redisConfig)
  12 + {
  13 + // 创建JedisPool实例,并传入密码
  14 + jedisPool = new JedisPool(redisConfig.getPoolConfig(), redisConfig.getHost(), redisConfig.getPort(), redisConfig.getTimeout(),redisConfig.getUser(), redisConfig.getPassword(),redisConfig.getDatabase());
  15 + }
  16 +
  17 + public Jedis getJedis()
  18 + {
  19 + return jedisPool.getResource();
  20 + }
  21 +
  22 + public void exeJedis(RedisServiceExe redisServiceExe)
  23 + {
  24 + Jedis jedis = getJedis();
  25 + redisServiceExe.exe(jedis);
  26 + jedis.close();//归还连接池
  27 + }
  28 +
  29 +}
  1 +package com.zhonglai.luhui.redis.service;
  2 +
  3 +import redis.clients.jedis.Jedis;
  4 +
  5 +public interface RedisServiceExe {
  6 + void exe(Jedis jedis);
  7 +}
  1 +# jedis.properties
  2 +jedis.pool.maxTotal=100
  3 +jedis.pool.maxIdle=50
  4 +jedis.pool.minIdle=10
  5 +jedis.pool.testOnBorrow=true
  6 +jedis.pool.testOnReturn=true
  7 +jedis.pool.testWhileIdle=true
  8 +jedis.pool.minEvictableIdleTimeMillis=60000
  9 +jedis.pool.timeBetweenEvictionRunsMillis=30000
  10 +jedis.pool.numTestsPerEvictionRun=3
  11 +jedis.pool.blockWhenExhausted=true
  12 +jedis.host=47.112.163.61
  13 +jedis.port=9527
  14 +jedis.timeout=2000
  15 +jedis.password=Luhui586
  16 +jedis.database=3
  1 +import com.zhonglai.luhui.redis.config.RedisConfig;
  2 +import com.zhonglai.luhui.redis.service.RedisService;
  3 +
  4 +import java.util.concurrent.atomic.AtomicReference;
  5 +
  6 +public class Test {
  7 + public static void main(String[] args) {
  8 + RedisService redisService = new RedisService(new RedisConfig());
  9 +
  10 + AtomicReference<String> str = new AtomicReference<>("");
  11 + redisService.exeJedis(jedis -> {
  12 + str.set(jedis.set("myKey", "myValue"));
  13 + long seconds = 10;
  14 + jedis.expire("myKey", seconds);
  15 + });
  16 +
  17 + System.out.println(str);
  18 + }
  19 +}
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <modelVersion>4.0.0</modelVersion>
  6 + <parent>
  7 + <groupId>com.zhonglai.luhui</groupId>
  8 + <artifactId>lh-common</artifactId>
  9 + <version>1.0.0</version>
  10 + </parent>
  11 +
  12 + <artifactId>lh-public-dao</artifactId>
  13 + <description>数据库操作</description>
  14 +
  15 + <properties>
  16 + <maven.compiler.source>8</maven.compiler.source>
  17 + <maven.compiler.target>8</maven.compiler.target>
  18 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  19 + </properties>
  20 +
  21 + <dependencies>
  22 + <dependency>
  23 + <groupId>com.zhonglai.luhui</groupId>
  24 + <artifactId>lh-common-util</artifactId>
  25 + </dependency>
  26 + <dependency>
  27 + <groupId>tk.mybatis</groupId>
  28 + <artifactId>mapper</artifactId>
  29 + <!-- 建议使用最新版本,最新版本请从项目首页查找 -->
  30 + </dependency>
  31 + <dependency>
  32 + <groupId>tk.mybatis</groupId>
  33 + <artifactId>mapper-spring-boot-starter</artifactId>
  34 + </dependency>
  35 +<!-- <dependency>-->
  36 +<!-- <groupId>org.mybatis.spring.boot</groupId>-->
  37 +<!-- <artifactId>mybatis-spring-boot-starter</artifactId>-->
  38 +<!-- </dependency>-->
  39 + <!--常用工具类 -->
  40 + <dependency>
  41 + <groupId>org.apache.commons</groupId>
  42 + <artifactId>commons-lang3</artifactId>
  43 + </dependency>
  44 +
  45 + </dependencies>
  46 +</project>
  1 +package com.zhonglai.luhui.dao.annotation;
  2 +
  3 +
  4 +import java.lang.annotation.ElementType;
  5 +import java.lang.annotation.Retention;
  6 +import java.lang.annotation.RetentionPolicy;
  7 +import java.lang.annotation.Target;
  8 +
  9 +@Target(ElementType.FIELD)
  10 +@Retention(RetentionPolicy.RUNTIME)
  11 +public @interface PublicSQLConfig {
  12 + boolean isSelect() default true;
  13 + boolean isPrimarykey() default false;
  14 +}